---
title: "Register a sending domain."
method: POST
path: "/domains"
tags: ["domains"]
---

# Register a sending domain.

`POST /domains`

## Request

- Base URL: `https://api.agentisend.com`
- URL: `https://api.agentisend.com/domains`
- Auth: HTTP bearer

Region is optional and defaults to us (Oregon); the stored value is returned.

## Headers

- `Idempotency-Key` string
- `Resend-Idempotency-Key` string

## Request body

- PostDomainsBody
  - `name` string, required: The domain you send from, such as yourdomain.com.
  - `region` 'us' | 'eu': us or eu. Default us. The region is recorded on the domain. All mail is sent from the US today. For one release the legacy names us-east-1, sa-east-1 and ap-northeast-1 map to us; eu-west-1 maps to eu.
  - `tracking` boolean: Whether to publish a tracking host. On by default. Not required to verify the domain.
  - `tracking_subdomain` string: The label of the tracking host. Default links, which publishes links.yourdomain.com.
  - `return_path_subdomain` string: The label of the return-path host. Default send. Up to 63 characters, starting with a letter.
  - `tls_mode` 'opportunistic' | 'enforced': opportunistic tries TLS and falls back. enforced refuses a receiver that cannot do TLS.
  - `tls` 'opportunistic' | 'enforced': Same as tls_mode. tls_mode wins if both are sent.
  - `open_tracking` boolean: Count opens. Off unless you set this.
  - `click_tracking` boolean: Rewrite links so clicks can be counted. Off unless you set this.
  - `openTracking` boolean: Same as open_tracking. open_tracking wins if both are sent.
  - `clickTracking` boolean: Same as click_tracking. click_tracking wins if both are sent.
  - `custom_return_path` string: Same as return_path_subdomain.
  - `customReturnPath` string: Same as custom_return_path.
  - `capabilities` object: What the domain does: sending (default enabled) and receiving (default disabled), each enabled or disabled. At least one must be enabled.
    - `sending` 'enabled' | 'disabled': enabled or disabled. Default enabled. Disabled: mail from this domain is refused and the domain is not signed for.
    - `receiving` 'enabled' | 'disabled': enabled or disabled. Default disabled. Enabled: this domain accepts inbound mail.

## Response `201`

Success

- PostDomainsReply
  - `object` 'domain', required
  - `id` string, uuid, required
  - `name` string, required
  - `zone` string, required
  - `region` 'us' | 'eu', required
  - `status` 'pending' | 'verified' | 'failed' | 'partially_verified' | 'partially_failed', required
  - `dkim_selector` string, required
  - `click_tracking` boolean, required
  - `open_tracking` boolean, required
  - `tracking_subdomain` string, required
  - `return_path_subdomain` string, required
  - `tls_mode` 'opportunistic' | 'enforced', required
  - `capabilities` object, required
    - `sending` 'enabled' | 'disabled', required
    - `receiving` 'enabled' | 'disabled', required
  - `records` object[], required
    - `record` 'SPF' | 'DKIM' | 'DMARC' | 'RETURN_PATH' | 'TRACKING' | 'RECEIVING' | 'TRACKING_CAA', required
    - `name` string, required
    - `name_relative` string, required
    - `host` string, required
    - `type` 'TXT' | 'MX' | 'CNAME' | 'CAA', required
    - `value` string, required
    - `value_strings` string[], required
    - `value_bind` string, required
    - `ttl` integer, required
    - `priority` integer, nullable, required
    - `status` 'pending' | 'verified' | 'failed' | 'recommended', required
    - `required` boolean, required
    - `reason` 'ok' | 'not_found' | 'unreachable' | 'mismatch' | 'not_published', nullable, required
    - `observed` string, nullable, required
    - `checked_at` string, date-time, nullable, required
    - `fix` string, required
  - `created_at` string, date-time, required
  - `verified_at` string, date-time, nullable, required
  - `tracking_issues` object[], required
    - `record` 'TRACKING' | 'TRACKING_CAA', required
    - `message` string, required
    - `fix` string, required
  - `provider_hints` object, required
    - `cloudflare` string, required
    - `route53` string, required
    - `namecheap` string, required
    - `godaddy` string, required
  - `warnings` object[], required
    - `code` 'spf_conflict' | 'spf_lookup_limit' | 'legacy_region', required
    - `message` string, required
    - `fix` string, required
    - `observed` string, required
    - `merged` string, nullable, required
  - `recent_events` object[], required
    - `id` string, required
    - `type` 'domain.added' | 'domain.first_check' | 'domain.record_seen' | 'domain.record_lost' | 'domain.verified' | 'domain.demoted' | 'domain.window_closed' | 'domain.deleted', required
    - `occurred_at` string, date-time, required
    - `detail` string, required

## Other responses

- `400`: The request is malformed or a field failed validation. Codes: validation_error, invalid_idempotency_key, invalid_cursor, plan_not_purchasable, stripe_signature_invalid, support_upload_rejected, sign_in_check_required.
- `401`: No usable credential was sent. Codes: missing_api_key, session_required, mfa_required.
- `403`: The credential may not do this, or the account or key is stopped. Codes: sending_domain_blocked, young_domain_held, domain_sending_disabled, domain_not_verified, onboarding_recipient_not_a_member, onboarding_sender_unavailable, account_suspended, account_sandboxed, human_action_required, csrf_origin_rejected, charge_not_this_account, invalid_api_key, restricted_api_key, insufficient_role, invite_email_mismatch, domain_scope_violation, dedicated_ip_assigned_by_us, approval_required, staff_review_required, trust_paused, kill_switch_active.
- `404`: Nothing with this id exists on the account. Codes: billing_customer_missing, not_found, session_expired, support_ticket_not_found.
- `409`: The request conflicts with the current state. Codes: domain_already_exists, template_name_taken, template_alias_taken, template_in_use, segment_in_use, contact_resubscribe_required, email_still_scheduled, domain_verified_elsewhere, domain_not_claimable, return_path_subdomain_in_use, overage_not_on_plan, term_not_on_sale, subscription_active, portal_change_unavailable, already_in_account, idempotency_in_flight, idempotency_payload_mismatch, approval_expired, support_closed, support_reopen_expired, support_merge_conflict, support_reply_too_soon.
- `413`: The request body is larger than this operation accepts. Codes: payload_too_large, support_upload_too_large.
- `415`: The request body is not JSON. Codes: unsupported_media_type.
- `422`: A field is well formed but was refused. Codes: missing_required_field, invalid_from_address, invalid_parameter, invalid_attachment, invalid_region, tracking_subdomain_unverified, tracking_subdomain_cannot_be_removed, domain_field_immutable, open_tracking_on_transactional, header_replaced, html_clipped_by_gmail, link_domain_listed, domain_blocklisted, mailbox_provider_domain, onboarding_shape_refused, dkim_key_mismatch, domain_check_window_expired, spf_conflict, spf_lookup_limit, review_sandbox_recipient_only, suppressed_recipient, content_refused, recipient_blocklisted, last_owner_required, seat_limit_reached, invite_not_valid, key_budget_exceeds_plan, domain_limit_reached, webhook_endpoint_limit_reached.
- `429`: A rate, quota or ramp ceiling was reached. Codes: onboarding_daily_cap_reached, trust_throttled, invite_limit_reached, rate_ceiling_exceeded, daily_quota_exceeded, monthly_quota_exceeded, rate_limit_exceeded, support_rate_limited.
- `500`: Something failed on our side. Codes: internal_server_error.

---

[API](https://skmtc.dev/agentisend/apis/agentisend-api.md) · [All operations](https://skmtc.dev/agentisend/apis/agentisend-api/llms.txt) · [OpenAPI document](https://skmtc.dev/agentisend/apis/agentisend-api/revisions/3066dda62a56?raw)
