Domains
Authenticate a whole sending domain with DNS. Mailbox providers trust the domain, not you: the proof is DNS, and it is not optional.
Register a domain
POST /email/domains registers a domain and returns dns_records: three CNAMEs of delegation (one for mail, two DKIM selectors) plus a recommended DMARC TXT. You publish four records once; SPF and the DKIM keys live at the target of the CNAMEs, on our side. Your existing SPF is not touched, and DKIM keys rotate without you ever editing DNS again. A subdomain such as mail.yourcompany.com is the recommended setup: it isolates your sending reputation from the mail your team reads and writes by hand.
curl -X POST https://api.mailer.quathos.com/api/v1/email/domains \
-H "Authorization: Bearer $QUATHOS_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "domain": "mail.yourcompany.com" }'{
"id": "019f70a4-3c8e-7d21-b0f4-51ac9e77b3aa",
"domain": "mail.yourcompany.com",
"status": "pending",
"can_send": false,
"mail_cname_verified": false,
"dkim_verified": false,
"dmarc_verified": false,
"dns_records": [
{ "type": "CNAME", "host": "em1234", "value": "u51ac9e77b3aa.wl.mailer.quathos.com", "purpose_code": "mail" },
{ "type": "CNAME", "host": "s1._domainkey", "value": "s1.domainkey.u51ac9e77b3aa.wl.mailer.quathos.com", "purpose_code": "dkim1" },
{ "type": "CNAME", "host": "s2._domainkey", "value": "s2.domainkey.u51ac9e77b3aa.wl.mailer.quathos.com", "purpose_code": "dkim2" },
{ "type": "TXT", "host": "_dmarc", "value": "v=DMARC1; p=none; rua=mailto:dmarc@mail.yourcompany.com", "purpose_code": "dmarc" }
],
"dns_provider": "cloudflare"
}Verify and manage
Once the records propagate, POST /email/domains/{id}/verify checks them. The response carries one boolean per proof (mail_cname_verified, dkim_verified, dmarc_verified) and can_send, the one that matters: it flips when the required records check out. Re-verification keeps running after that; if a record disappears later, degraded_since marks when, and you have a window to fix it before sending is paused. GET /email/domains lists them, GET /email/domains/{id} reads one, and DELETE /email/domains/{id} removes it.
curl -X POST https://api.mailer.quathos.com/api/v1/email/domains/{domain_id}/verify \
-H "Authorization: Bearer $QUATHOS_TOKEN"Domain health
GET /email/domains/{id}/health is one traffic light per domain: healthy, degraded or paused. It combines the DNS state (the same records verify checks, rechecked every 10 minutes), the last 7 days of sending from the daily rollup (sent, delivered, bounced, complained, and the bounce and complaint rates) and a list of issues, each with the action that clears it: publish the DMARC record, fix the CNAME that drifted, clean the list that is bouncing.
Tracking defaults per domain
PATCH /email/domains/{id} with track_opens_default and track_clicks_default sets what a message inherits when it does not say tracking itself. A message that sends tracking: { opens: false } wins over the domain; a message that omits the field, or sends null, takes the domain default. The effective value is what gets recorded on the message.
Automatic pause by reputation
Every 15 minutes we look at the last 24 hours of each sending domain. With at least 500 delivered or bounced messages in the window, a complaint rate at or above 0.3% or a hard-bounce rate at or above 5% pauses the domain: paused_at and paused_reason are set, sending from it is refused, the owner gets an email and the domain.sending_paused webhook fires. At 0.1% and 2% you get a warning instead. The DNS state does not change; this is a separate lock.
Resuming is manual: POST /email/domains/{id}/resume clears the pause when the last 24 hours are back below the warning thresholds, and answers 409 with the current rates while they are not. Resuming automatically would pause the same domain twice a day.