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
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" }'
json
{
  "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"
}
The dns_records array is what you publish at your DNS provider. The host column is relative to your zone; most DNS panels append the domain by themselves.

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
curl -X POST https://api.mailer.quathos.com/api/v1/email/domains/{domain_id}/verify \
  -H "Authorization: Bearer $QUATHOS_TOKEN"
A send from an unverified identity is refused. This is not a formality: it is what stops one tenant from sending as another.

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.

These thresholds are the ones Gmail Postmaster publishes. Crossing them there means the whole shared IP is at risk, not only your domain, which is why the pause is not optional.