Docs
Custom domains
Send and receive from your own domain: DNS records, verification and limits.
Use your own domain (or a subdomain such as agents.your-domain.eu) so recipients see your brand. A subdomain is recommended: it keeps agent mail separate from your team's mail.
1. Add the domain
curl -s -X POST https://api.mueslimail.com/v0/domains \
-H "Authorization: Bearer $MAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"domain": "agents.your-domain.eu"}'The response contains the DNS records to publish. A fresh DKIM key is generated for each domain. Copy the values exactly as returned; the table shows their shape.
| Type | Name | Value | Purpose |
|---|---|---|---|
| MX | agents.your-domain.eu | 10 <platform mail host>. | Routes inbound mail to the platform. |
| TXT | agents.your-domain.eu | v=spf1 mx include:<relay> -all | SPF: authorizes the platform to send. |
| TXT | <selector>._domainkey.agents.your-domain.eu | v=DKIM1; k=rsa; p=<public key> | DKIM: public key for signatures. |
| TXT | _dmarc.agents.your-domain.eu | v=DMARC1; p=quarantine; rua=mailto:dmarc@agents.your-domain.eu | DMARC policy. |
2. Verify
Call POST /v0/domains/{domain}/verify to check DNS now. The scheduler also checks every 5 minutes for 7 days after you add the domain. Each record reports verified or missing; when all four are found the domain becomes verified and the domain.verified event fires.
3. Create inboxes on it
Pass domain when you create an inbox. Until the domain is verified the call returns 403 domain_not_verified.
Catch-all: one inbox for unknown addresses
A verified domain can nominate one inbox that receives the mail addressed to a local part nobody created: PATCH /v0/domains/{domain} with {"catch_all_inbox": "triage@agents.your-domain.eu"}, and null turns it off. The lookup is exact-address first, so an address that exists always wins and the catch-all only ever catches what would otherwise be refused.
- The nominated inbox must be on that same domain (
422 catch_all_inbox_wrong_domain) and the domain must be verified (422 domain_not_verified); an unknown address is404. - A quarantined address is never caught: an address whose inbox was deleted less than 90 days ago is refused, because the quarantine exists so that mail for the previous owner reaches nobody.
- One sender may fill at most
MAI_CATCH_ALL_PER_HOURunknown local parts per domain per hour (20 by default). Past that, the recipient is refused, not accepted: a catch-all without a budget is a backscatter amplifier. - Caught mail is ordinary inbound mail: the same screening, the same rules, the same events. If the nominated inbox is deleted the catch-all switches itself off, and an unknown recipient is a
550at RCPT, never a silent drop.
Limits and deletion
- The number of custom domains depends on the plan: 1 on Free, 5 on Builder, 20 on Growth, 50 on Team.
- A domain can be deleted only when it has no inboxes left; otherwise the API returns
409 cannot_delete. GET /v0/domainslists your domains and the shared platform domain.
Endpoints
POST/v0/domains
Add a custom domain; returns the DNS records to publish
Body
| Name | Type | Notes |
|---|---|---|
domain | string | required |
Responses
201Created: Domain403Error envelope: Error409Error envelope: Error
GET/v0/domains
List own and shared domains
Responses
200OK
GET/v0/domains/{domain}
Get a domain with record status
Parameters
| Name | Type | Notes |
|---|---|---|
domain | string | in path, required |
Responses
200OK: Domain
DELETE/v0/domains/{domain}
Delete a domain without inboxes
Parameters
| Name | Type | Notes |
|---|---|---|
domain | string | in path, required |
Responses
204Deleted409Error envelope: Error
POST/v0/domains/{domain}/verify
Check DNS now (the scheduler also checks every 5 minutes for 7 days)
Parameters
| Name | Type | Notes |
|---|---|---|
domain | string | in path, required |
Responses
200OK: Domain
Domain object
| Name | Type | Notes |
|---|---|---|
domain_id | string (uuid) | |
domain | string | |
shared | boolean | |
status | pending | verified | |
records | object[] | |
last_checked_at | string (date-time) | |
verified_at | string (date-time) | |
catch_all_inbox | string (email) | The inbox that receives mail addressed to a local part nobody created on this domain, or null for no catch-all (D5) |