Docs

Use your own domain

Sending agent mail from a domain you control means publishing DNS records yourself. This application never writes, edits or removes a record on your behalf — it tells you the exact values and then checks what is actually published.

A platform address on agents.emailforagents.ai works with no DNS at all and is the right place to start; this page is for when an agent inbox needs to be at your own domain instead. If you have not created any inbox yet, do the quickstart first.

What you need first

  • A live project. Test projects cannot attach domains at all; the attempt returns test_mode_unsupported, and test addresses stay on non-routable .mail.invalid hosts.
  • An eligible paid subscription. Attaching a domain without one returns payment_required. Each plan has a custom-domain count; exceeding it returns quota_exceeded.
  • Access to your DNS zone, and a change window if the domain already carries mail.

Paid checkout is currently disabled, so the paid subscription this feature requires cannot be bought today. Domain setup does not route around that requirement. Until checkout ships, the usable path is a platform address. See pricing.

Start with a dedicated subdomain

Use a hostname such as agents.example.com rather than your company's root domain. Three reasons, in order of how much they will cost you if you ignore them:

  1. Receiving mail at a hostname means publishing MX there. Publish MX at a hostname that already receives employee mail and you redirect that mail. A subdomain has no existing MX to break.
  2. Sending reputation stays separated. An agent that gets a bounce or a complaint does not drag your primary domain's reputation with it.
  3. Revocation is a zone edit. Removing a subdomain's records is a contained change you can make in a minute.

Preview the exact hostname in Domains before attaching it. The preview resolves DNS to see whether MX already exists; it does not attach a provider domain and it changes nothing. If MX is found, keep the default preserve_existing mode: that enables sending verification for the hostname and leaves receiving disabled, so nothing you publish can interrupt delivery to existing mailboxes. The preview will also suggest agents.<your domain> as the safer target.

Choose migrate only when you genuinely intend to move all receiving mail at that hostname. It records your consent; it still makes no DNS changes.

The records, and the order they appear in

You do not get every record up front, and that is deliberate: the provider-issued sending and receiving values are only created after ownership is proven. Asking you to publish them earlier would mean handing out mail-routing records for a hostname nobody had demonstrated control of.

StageRecordPurposeWhere it comes from
1 TXT at _efa-challenge.<domain> Ownership Issued immediately on attach. Value is efa-ownership= plus a token unique to this attachment.
2 TXT at the domain — SPF Sending Issued by the mail provider after ownership verifies.
2 DKIM record at the host the provider names Sending Issued by the provider after ownership verifies. Publish the type, host and value exactly as displayed; do not retype the key.
3 MX at the domain, with a priority Receiving Issued by the provider after ownership verifies, and only when receiving is not held back by existing MX.
Type   TXT
Host   _efa-challenge.agents.example.com     (relative: _efa-challenge)
Value  efa-ownership=efa_9c41a7...

The console shows both the fully-qualified host and the relative host, because DNS providers disagree about which one they want — some expect _efa-challenge.agents.example.com, others expect _efa-challenge with the zone appended for you. Publishing both forms creates a record at _efa-challenge.agents.example.com.agents.example.com, which is the single most common reason verification does not complete.

Each record carries its own status while you work:

Record statusMeaning
pendingPublished value expected; not yet observed.
foundThe expected value was observed in DNS.
missingNothing at all was found at that host.
mismatchSomething is there, but it is not the expected value. Usually a truncated or re-wrapped TXT string.
awaiting_providerThe value does not exist yet. It appears after ownership verifies.
blocked_existing_mxReceiving here would replace existing MX, and you chose to preserve it.

Do not replace an existing root SPF record with a value intended for a sending subdomain. SPF is per-hostname: the record shown for agents.example.com belongs at agents.example.com. Overwriting the SPF at example.com with it can stop your existing mail authenticating. A hostname should also have exactly one SPF TXT record — two is a permanent error in the specification, not a merge.

Verifying ownership

  1. Attach the domain. Copy its unique _efa-challenge TXT record into your DNS provider.
  2. Leave the TXT record in place — permanently — and choose Check verification and provider setup.
  3. Once ownership is confirmed, the console displays the exact SPF, DKIM and receiving records returned by the mail provider, including MX priority.
  4. Publish those records at their displayed hosts.
  5. Check again after DNS propagates. Each check reads DNS live; it never writes.

Only one verification check runs at a time per domain — a second concurrent request returns temporarily_unavailable rather than racing the first. An explicit check can also ask the provider to re-run its own verification, at most once a minute. Between your checks, the system re-reads DNS in the background roughly every five minutes, so a record you remove later will be noticed.

Three statuses, not one

Ownership, sending and receiving are tracked separately because they can genuinely disagree: a domain can be authenticated for sending while receiving nothing.

StatusValuesWhat it gates
ownership_status pending, verified, lost Everything. Losing it disables routing for every inbox on the domain.
sending_status disabled, pending, ready Whether the provider has verified SPF and DKIM for the hostname.
receiving_status disabled, pending, ready Whether mail addressed to the hostname arrives here.

Receiving readiness requires the MX set at the hostname to match the provider's set exactly — same hosts, same values, same priorities, and no extras. An additional MX at any priority is a real routing path to somewhere else, so readiness stays pending until it is removed. This is the check that most often surprises people who left an old record behind.

Creating an address

Attaching a domain does not create an inbox. When the statuses you need are ready, go back to Inboxes, select the same live project, choose the custom hostname under Address domain, and give the inbox a display name and optional local part.

Then prove both directions before you hand it to an agent: send a message to the new address from a mailbox you control, and have the inbox reply. A ready status is evidence that the configuration is correct. It is not a promise about whether a particular recipient's provider will place your mail in their inbox, and nothing on this page can be.

Using the API

POST /v1/projects/{project_id}/domains
{
  "domain": "agents.example.com",
  "receiving_mode": "preserve_existing"
}

receiving_mode defaults to preserve_existing. Supply "receiving_mode": "migrate" to record an intentional migration of all mail at that hostname; it changes what the wizard will offer, not your DNS.

CallDoes
POST /v1/projects/{project_id}/domains/preview Resolves DNS and returns the record plan. Nothing is stored.
POST /v1/projects/{project_id}/domains Attaches the domain and issues the ownership token.
GET /v1/projects/{project_id}/domains/{domain_id} Returns every record with its host, expected value, priority and status.
POST /v1/projects/{project_id}/domains/{domain_id}/verify Re-reads DNS and re-checks provider setup.
POST /v1/projects/{project_id}/inboxes With domain_id and an optional local_part, creates the address.

The domain must be a hostname, not a URL or a mailbox: agents.example.com, never https://agents.example.com or ada@example.com. Bare IP addresses and localhost are refused. Anything else returns invalid_request with a message saying so. Every response carries mutates_customer_dns: false, which is not decoration — it is the invariant this whole flow is built around.

When setup needs attention

SymptomWhat to do
Ownership lost The challenge TXT is gone or changed. Restore the exact value. Sending and routing stop until verification succeeds again, and a later owner of the domain gets a new token rather than inheriting yours.
Ownership record shows mismatch Something is published but not the expected string. Check for added quotes, a split TXT string, or the doubled-host mistake above.
Receiving stuck at pending Compare host, value and priority exactly, and remove every MX that is not in the provider's set. An extra record keeps receiving pending.
Sending stuck at pending The provider has not yet verified SPF and DKIM. Confirm both are at the hostname the console names, then re-check. DNS caches can hold an old negative answer for a while.
Provider status unknown or failed Do not repeatedly delete and re-attach. Provider-side creation may have completed despite a timeout, and re-attaching can leave two claims on one hostname. Custody in that state needs support review.
Inbox paused right after creation The address is reserved while a provisioning result is reconciled. Creating it again will not silently allocate a second address.