Skip to content
YourMail

API reference

Domains

GET/v1/domains
POST/v1/domains
GET/v1/domains/:id
DELETE/v1/domains/:id

Add a sending domain and get its DNS records back in the same response, read its verification status, and remove it. What the Domains & DNS guide walks through by hand, from a script.

Why use this

Without this, the one step of setup that could not be automated was the first one. A provisioning script or an AI agent could send mail, but had to hand a human a browser to add the domain it was sending from.

For example

Your platform onboards a customer, adds mail.<their-domain> here, and shows them the returned records inside your own UI — with no visit to a YourMail dashboard.

Example

import { YourMail } from "yourmail";

const yourmail = new YourMail(process.env.YOURMAIL_API_KEY!);

// Add the domain and get its DNS records in the same call.
const domain = await yourmail.domains.create("mail.acme.com");
for (const r of domain.dnsRecords) {
  console.log(r.type, r.name, r.value);
}

// Verification runs on its own once the records are live — poll if you like.
const { status } = await yourmail.domains.get(domain.id); // "pending" -> "verified"

Response

// 201 Created (POST) — the same shape GET returns
{
  "id": "jd7abc...",
  "name": "mail.acme.com",
  "status": "pending",
  "verifiedAt": null,
  "createdAt": 1756800000000,
  "dnsHost": "cloudflare",
  "dnsRecords": [
    {
      "type": "CNAME",
      "name": "abc._domainkey.mail.acme.com",
      "value": "abc.dkim.amazonses.com",
      "found": null,
      "observed": null
    }
  ],
  "recommendedRecords": [
    {
      "type": "TXT",
      "name": "_dmarc.mail.acme.com",
      "value": "v=DMARC1; p=none;",
      "found": null,
      "observed": null
    }
  ],
  "failureReason": null,
  "dnsCheckedAt": null,
  "dnsRegressedAt": null,
  "suspendedAt": null,
  "trackEngagement": true
}

GET /v1/domains returns { data: [ ...rows ] }, and DELETE returns { id, deleted: true }. Deleting removes the SES identity too, so the same name can be added again afterwards — by you, or by another account.

statusstring
pending, verified or failed. A failed domain stops verifying, but you do not have to DELETE it first — POSTing the same name again recycles the row and issues fresh records. The exception is a name suspended for abuse, which cannot be re-added.
dnsRecordsarray
The records verification is gated on. Publish every one exactly as given.
dnsRecords[].foundboolean | null
What the last DNS check observed: true, false, or null if it has never been checked. Tri-state on purpose — never checked is not the same as not there.
dnsRecords[].observedstring | null
The value actually found at that name on the last check, so a record that is present but wrong shows what was published rather than only that it did not match. Null if never checked, or if nothing was found.
recommendedRecordsarray
A DMARC monitoring policy. Recommended, never gated on — an org-level DMARC record you already run is fine.
trackEngagementboolean
Whether opens and clicks are tracked for sends from this domain. Read-only over HTTP — there is no API field to change it; the toggle is in the dashboard.
dnsHoststring | null
The registrar detected from the nameservers, so you can tell a person which control panel to open.
failureReasonstring | null
Why a failed domain failed, in the same words the dashboard uses.
dnsCheckedAtnumber | null
When the DNS records were last looked up, or null if they never have been.
dnsRegressedAtnumber | null
Set while a verified domain's DNS has gone missing. Advisory — the domain still sends, and it clears itself when the record comes back.
suspendedAtnumber | null
Set while a plan downgrade has parked the domain. It keeps its verification; it cannot send until the plan is raised.

Errors

Every endpoint on this page needs a full-access key. A send-only key is issued so it can be handed to something that only sends — if it could also manage the account, the scope would be decorative. See Errors for the full error shape.

400validation_error

name is missing or not a valid hostname

401authentication_error

The API key is missing, malformed or revoked

403authentication_error

The key is send-only; managing domains requires a full-access key

403domain_error

The name is one of ours, your plan's domain allowance is full, or the name was suspended for abuse

409domain_error

You have already added this domain, or another account holds it

404not_found

No domain with that id on this account

502domain_error

We could not provision the identity with SES — transient, and the one failure here worth retrying