Domains & DNS
A domain is what lets MailKite receive mail for you and send authenticated mail on your behalf. You can add unlimited domains — one per product, per environment, per tenant — at no per-domain cost.
Add a domain
Add any domain or subdomain you control. Subdomains like
mail.myapp.ai or a free myapp.mailkite.dev are a great
fit and keep your root domain's reputation separate.
Dashboard → Domains
Click [ + Add domain ]
Type myapp.ai
Click [ Add ]Add the domain "myapp.ai"const res = await mk.createDomain({ domain: "myapp.ai" });res = mk.createDomain({"domain": "myapp.ai"})$res = $mk->createDomain(['domain' => 'myapp.ai']);Object res = mk.createDomain(Map.of("domain", "myapp.ai"));res, err := mk.CreateDomain(map[string]any{"domain": "myapp.ai"})res = mk.createDomain("domain" => "myapp.ai")curl https://api.mailkite.dev/api/domains \
-H "Authorization: Bearer <session-token>" \
-H "Content-Type: application/json" \
-d '{ "domain": "myapp.ai" }'
The response includes the DNS records to publish. New domains start in
pending and move to verified once DNS resolves.
Register a new domain
Don't have a domain yet? Register one from the dashboard and we'll set it up for you —
you're the legal owner. Search a name (we check popular TLDs like
.com, .ai, .io, .dev), pick an
available one, and we register it in your name and provision the mail DNS automatically, so it's
usually verified the moment it's registered — no DNS to paste.
Registration requires a card on file (add it in Billing). The price shown is what you pay — the registrar's cost plus payment processing and a small service fee. Domain registrations are non-refundable. Your card is also used for usage-based billing (below).
Free *.mailkite.dev subdomain
The fastest start: claim a free your-app.mailkite.dev subdomain. We set up the DNS
in our zone for you, so it works the instant you claim it — no registrar, no card, no DNS. Great
for trying MailKite or for projects that don't need a custom domain.
The DNS records
Add these four records at your DNS provider. Names are shown for
myapp.ai — substitute your own domain.
| Type | Name | Value | Purpose |
|---|---|---|---|
MX | myapp.ai | mx.mailkite.dev (priority 10) | Routes inbound mail to MailKite. Required to receive. |
TXT | myapp.ai | v=spf1 include:mailkite.dev ~all | SPF — authorizes MailKite to send for the domain. |
TXT | mailkite._domainkey.myapp.ai | v=DKIM1; k=rsa; p=… | DKIM — signs outbound so it passes authentication. |
TXT | _dmarc.myapp.ai | v=DMARC1; p=none; | DMARC — alignment policy. Start at none, tighten later. |
The exact values — including your per-domain DKIM public key — are shown in the dashboard and returned fromPOST /api/domainsandGET /api/domains/:id. Always copy from there rather than this page.
Verify
After publishing the records, trigger a check. MailKite looks up your records over DNS-over-HTTPS and records the result.
Dashboard → Domains → myapp.ai
Click [ Verify DNS ]Verify the DNS for myapp.aiawait mk.verifyDomain("dom_…");mk.verifyDomain("dom_…")$mk->verifyDomain('dom_…');mk.verifyDomain("dom_…");_, err := mk.VerifyDomain("dom_…")mk.verifyDomain("dom_…")curl -X POST https://api.mailkite.dev/api/domains/dom_…/verify \
-H "Authorization: Bearer <session-token>" {
"status": "verified",
"checks": { "mx": true, "spf": true, "dkim": true, "dmarc": true },
"checkedAt": 1750000000000
}
A domain becomes verified as soon as MX resolves
to mx.mailkite.dev — that's the record that enables receiving.
SPF, DKIM, and DMARC are reported separately and monitored on an ongoing
basis so you know if a record drifts. DNS can take anywhere from a minute to a
few hours to propagate; re-run verification until everything is green.
Addresses on a domain
Once verified, every address on the domain receives. By default a
catch-all routes all mail (*@myapp.ai) to the
webhook you set for the domain. To split traffic — say, send
support@ to one endpoint and billing@ to another —
create per-address routes. This is what lets you
give every agent, task, or tenant its own address with no extra setup.
Removing a domain
await mk.deleteDomain("dom_…");mk.deleteDomain("dom_…")$mk->deleteDomain('dom_…');mk.deleteDomain("dom_…");_, err := mk.DeleteDomain("dom_…")mk.deleteDomain("dom_…")curl -X DELETE https://api.mailkite.dev/api/domains/dom_… \
-H "Authorization: Bearer <session-token>" Deleting a domain stops inbound routing for it. Remove the MX record at your DNS provider too if you no longer want mail attempted for the domain.
Next: receive your first message, or set up authentication for the API.