Setting up a domain, end to end
This is the loop an agent runs. Nothing here needs a human.-
Declare the domain.
bash
curl -X POST -H "x-api-key: $AGENTMAIL_API_KEY" -H "content-type: application/json" \ -d '{"domain":"atelier-nord.fr"}' \ "https://www.agentsmail.io/api/v1/domains" -
Read the records to publish.
GET /api/v1/domainsreturns them. Seven in practice: oneTXTfor the ownership challenge, three DKIMCNAME, oneMXand oneTXTfor the custom MAIL FROM, oneTXTfor DMARC. The challenge record comes first, and it is the one that decides usage. Its name is_agentmail-challenge.<domain>and its value is the organization's own token. DKIM alone is not enough: an identity already verified in the provider account returnsSUCCESSto whoever declares it, soverifiedalso requires this proof. ATXTname accepts several values — two organizations transferring a domain can publish side by side. The challenge record is served even when the provider is unreachable, because its value comes from our own database.json{ "success": true, "data": [ { "id": "…", "domain": "atelier-nord.fr", "dkimStatus": "PENDING", "mailFromStatus": "PENDING", "verified": false, "ownershipProved": false, "lastCheckedAt": "2026-08-12T12:00:00.000Z", "sesUnavailable": false, "dnsRecords": [ {"type": "TXT", "name": "_agentmail-challenge.atelier-nord.fr", "value": "Xy7pQ2rL9mNv4KtB1sZaWg"}, {"type": "CNAME", "name": "abc._domainkey.atelier-nord.fr", "value": "abc.dkim.amazonses.com"}, {"type": "MX", "name": "mail.atelier-nord.fr", "value": "feedback-smtp.eu-west-1.amazonses.com", "priority": 10}, {"type": "TXT", "name": "mail.atelier-nord.fr", "value": "v=spf1 include:amazonses.com ~all"}, {"type": "TXT", "name": "_dmarc.atelier-nord.fr", "value": "v=DMARC1; p=none;"} ] } ] } - Publish them at the registrar. That part is outside the API.
-
Re-check.
POST /api/v1/domains/{domainId}/verifyasks the email provider again and stores the answer. Poll it: DNS propagation takes from a few minutes to 72 h. -
Confirm.
GET /api/v1/menow answers"ready": true.
DKIM and ownership gate sending, together.
mailFromStatus and the DMARC record improve
deliverability — a pending MAIL FROM never blocks a send. The verified field means usable:
dkimStatus === "SUCCESS" and the ownership challenge proved, on the same domain. Read
verified and you never have to reimplement the rule; read ownershipProved and dkimStatus
to know which of the two records is still missing.Ownership is proved once, and never revoked
The proof is a dated event, not a continuous state. Once a domain is proved, removing theTXT
record later does not revoke it — otherwise any DNS outage would cut off sending. Re-publishing
the challenge for another organization transfers the domain: a proved domain belongs to exactly one
organization at a time.
Checking is synchronous only: it happens when you call verify or open the domain screen. There is
no background job.
The records are never stored
The provider records are read back on every call, because they change if the identity is recreated. Do not cache them: a stale copy sends someone to publish records that no longer verify anything. The challenge record is the exception in origin only — its value is ours, which is why it survives a provider outage — but it is served the same way, never cached by you.When the email provider is unreachable
Reads do not fail.GET /api/v1/domains returns the last known state with "sesUnavailable": true
and its lastCheckedAt. verify does fail — checking is precisely what you asked for, and
pretending otherwise would be lying.