Sending domains
You send from addresses on your own domains. Before Postilio sends from a domain, two DNS records prove it is yours and let Postilio sign the mail (DKIM) and receive its bounces (the return path). A domain belongs to one project.
Add a domain
In the portal under Domains, or with a key that has the domains:manage scope:
curl https://api.postilio.eu/v1/domains \
-H "Authorization: Bearer $POSTILIO_KEY" \
-H "Content-Type: application/json" \
-d '{ "name": "mail.example.com" }'
The name needs at least two labels and may not be an IP address. Postilio stores it in lowercase, without a trailing dot. A subdomain such as mail.example.com keeps your transactional mail apart from the rest of your domain's mail. postilio.eu and every name under it are Postilio's own and cannot be added. A name the project has already answers 409 with {"error": "domain_exists"}.
The answer is the domain with the status pending and the records to create:
{
"id": "01a1081b-eb5c-7685-ab38-fdd4a4ab10e5",
"name": "mail.example.com",
"status": "pending",
"checkedAt": null,
"records": [
{ "type": "CNAME", "name": "pst202610._domainkey.mail.example.com", "value": "pst202610.ft6sub3lbo.dkim.postilio.eu", "status": "unknown" },
{ "type": "CNAME", "name": "bounce.mail.example.com", "value": "rp.postilio.eu", "status": "unknown" }
],
"createdAt": "2026-10-04T18:10:09.884+00:00",
"addedBy": null,
"failingSince": null,
"sent30d": 0
}
The two records
| Record | Points to | What it is for |
|---|---|---|
<selector>._domainkey.<domain> | <selector>.<token>.dkim.postilio.eu | DKIM. Postilio signs your mail with a key of this domain's own and publishes its public half under dkim.postilio.eu; your CNAME points there. |
bounce.<domain> | rp.postilio.eu | Return path. The envelope sender of your mail is on bounce.<domain>, so bounces come back to Postilio, and SPF is checked against Postilio's servers through this CNAME. |
Create both as CNAME records with exactly the names and values the portal or the API shows; the selector and token are your domain's own. Postilio publishes the record your DKIM CNAME points to itself; the domain is verified once that one is found too. So when both of your records are found and the domain is still pending, Postilio's own record is not in DNS yet. Both align with your domain for DMARC. If your domain has no DMARC record yet, add one too, for example _dmarc.mail.example.com TXT "v=DMARC1; p=none".
Statuses
| Status | Meaning |
|---|---|
pending | added; not all records found yet. Nothing can be sent from it. |
verified | all records found. You can send from any address on the domain. |
failing | it was verified, but a record went missing. It keeps sending for 72 hours after failingSince, so a DNS slip does not stop your mail at once; after that, sends answer 422 unverified_sender_domain until the records are back. |
Each record has its own status too: found, missing, or unknown before the first check. A domain that was failing becomes verified again as soon as its records are found.
Checks
Postilio checks every domain's records every 10 minutes. To check one now, press Check now in the portal or:
curl -X POST https://api.postilio.eu/v1/domains/$DOMAIN_ID/check \
-H "Authorization: Bearer $POSTILIO_KEY"
It answers the domain with its new status. One check per domain per minute: sooner answers 429 with {"error": "too_many_checks"} and a Retry-After header. When DNS gave no answer at all, the status stays as it was and the answer is 503 with {"error": "dns_unavailable"}; try again a little later.
List and remove
GET /v1/domains lists the project's domains and GET /v1/domains/{id} reads one. sent30d is the number of live messages sent from the domain today and the 29 days before.
DELETE /v1/domains/{id} removes a domain: mail from it stops at once. Delete the two DNS records afterwards.