import { createClient } from "@mailsai/sdk";
const client = createClient(); // reads MAILS_API_KEY
const result = await client.domains.create(
"mail.acme.com",
);
console.log(result);from mailsai import create_client
client = create_client() # reads MAILS_API_KEY
result = client.create_domain("mail.acme.com")
print(result)curl -X POST 'https://api.mails.ai/v1/domains' \
-H "Authorization: Bearer $MAILS_API_KEY" \
-H 'Content-Type: application/json' \
-d '{ "domain": "mail.acme.com" }'mails domains create mail.acme.com{
"name": "mails_domains_create",
"arguments": { "domain": "mail.acme.com" }
}{
"id": "dom_01JZXE8S0U2W4Y6A8C0E2G4J6L",
"domain": "mail.acme.com",
"status": "pending",
"provider": "ownmetal",
"dns_records": [
{
"type": "TXT",
"host": "dkim._domainkey.mail.acme.com",
"value": "v=DKIM1; k=rsa; p=MIIBIjANBgkq…",
"purpose": "dkim",
"required": true,
"verified": false,
"instruction": "Add this record exactly as shown."
},
{
"type": "TXT",
"host": "mail.acme.com",
"value": "v=spf1 ip4:15.204.67.226 ~all",
"purpose": "spf",
"required": false,
"verified": false,
"instruction": "If you already publish an SPF.",
"merge_token": "ip4:15.204.67.226"
},
{
"type": "TXT",
"host": "_dmarc.mail.acme.com",
"value": "v=DMARC1; p=none; rua=mailto:dmarc@mail.acme.com",
"purpose": "dmarc",
"required": false,
"verified": false,
"instruction": "Only if you have no DMARC record today. If you already publish one, KEEP IT — never lower an existing p=quarantine or p=reject to p=none. Point rua at a mailbox you control."
}
],
"fail_reason": null,
"last_check_at": null,
"verified_at": null,
"created_at": "2026-07-24T10:30:00.000Z"
}201 The registered domain with the DNS records to
create.
400 Invalid request — malformed JSON or a field failed
validation. Also feature_not_enabled when this
server has a feature switched off (custom domains
before they are available).
401 Missing or invalid API key.
402 Payment required: a plan limit
(plan_limit_exceeded) or a feature the current plan
does not include (feature_not_enabled). The error
object carries upgrade_url, the dashboard page
where the plan can be changed.
403 The API key lacks the required scope
(insufficient_scope), or the token belongs to an
app connected by sign-in and this operation is
closed to connected apps
(connected_app_not_allowed).
500 Internal server error.Add a custom send domain
import { createClient } from "@mailsai/sdk";
const client = createClient(); // reads MAILS_API_KEY
const result = await client.domains.create(
"mail.acme.com",
);
console.log(result);from mailsai import create_client
client = create_client() # reads MAILS_API_KEY
result = client.create_domain("mail.acme.com")
print(result)curl -X POST 'https://api.mails.ai/v1/domains' \
-H "Authorization: Bearer $MAILS_API_KEY" \
-H 'Content-Type: application/json' \
-d '{ "domain": "mail.acme.com" }'mails domains create mail.acme.com{
"name": "mails_domains_create",
"arguments": { "domain": "mail.acme.com" }
}{
"id": "dom_01JZXE8S0U2W4Y6A8C0E2G4J6L",
"domain": "mail.acme.com",
"status": "pending",
"provider": "ownmetal",
"dns_records": [
{
"type": "TXT",
"host": "dkim._domainkey.mail.acme.com",
"value": "v=DKIM1; k=rsa; p=MIIBIjANBgkq…",
"purpose": "dkim",
"required": true,
"verified": false,
"instruction": "Add this record exactly as shown."
},
{
"type": "TXT",
"host": "mail.acme.com",
"value": "v=spf1 ip4:15.204.67.226 ~all",
"purpose": "spf",
"required": false,
"verified": false,
"instruction": "If you already publish an SPF.",
"merge_token": "ip4:15.204.67.226"
},
{
"type": "TXT",
"host": "_dmarc.mail.acme.com",
"value": "v=DMARC1; p=none; rua=mailto:dmarc@mail.acme.com",
"purpose": "dmarc",
"required": false,
"verified": false,
"instruction": "Only if you have no DMARC record today. If you already publish one, KEEP IT — never lower an existing p=quarantine or p=reject to p=none. Point rua at a mailbox you control."
}
],
"fail_reason": null,
"last_check_at": null,
"verified_at": null,
"created_at": "2026-07-24T10:30:00.000Z"
}201 The registered domain with the DNS records to
create.
400 Invalid request — malformed JSON or a field failed
validation. Also feature_not_enabled when this
server has a feature switched off (custom domains
before they are available).
401 Missing or invalid API key.
402 Payment required: a plan limit
(plan_limit_exceeded) or a feature the current plan
does not include (feature_not_enabled). The error
object carries upgrade_url, the dashboard page
where the plan can be changed.
403 The API key lacks the required scope
(insufficient_scope), or the token belongs to an
app connected by sign-in and this operation is
closed to connected apps
(connected_app_not_allowed).
500 Internal server error.Body Parameters
The domain to send from, such as mail.acme.com, 4 to 253 characters, lowercased and without a trailing dot. A name that is not a valid hostname, is under mails.ai, or is already added to any workspace is refused with 400.
Returns the DNS records to create at your registrar — records-only verification, no nameserver changes. Agents whose address is on a VERIFIED custom domain send under their own identity instead of the shared workspace subdomain. A domain that is already added, to this workspace or to another, is refused with 400 duplicate_resource.
Response
Domain id (dom_…).
The custom sending domain, lowercased.
pending → records issued; verifying → checks in progress; verified → agents on this domain send under their own identity; failed → 20 verify calls in a row did not pass. Not final: a failed domain is still re-checked automatically (less often the longer it fails, at most a day apart) and verifies by itself once its records resolve; verify still checks at once, and the count starts over on success or after a day without a verify call.
Backing sending infrastructure for this domain.
The records to create at your DNS host. Each record's verified says whether the last check found it, and every required one must be found for the domain to verify.
Why the last verification did not pass, when it didn't.
When the records were last checked: by a verify call, by the automatic re-checks of unverified domains, or by the daily re-check of verified ones. Null before the first check.
When the domain first verified. Null until then, and cleared again when the daily re-check of verified domains (06:40 UTC) finds a required record gone.
When the domain was added (UTC).
Was this page helpful?