Hosts#
A key manages a list of hosts. A host is a whole domain (example.com) or a name inside one (advisor.example.com). You manage records at each host and under it (_dmarc.advisor.example.com, google._domainkey.advisor.example.com).
When a key's host is a name inside a domain, everything else in that root domain belongs to someone else: you never see it and can't change it. The rest of this page is about that case; for a whole-domain host, the host and the root are the same name.
Two ways to address a host#
Every API style accepts either form, call by call.
1. The host as its own domain (simplest)#
Put the host in domain (Dynadot style) or in the path (Spaceship style):
- Records at the host are main records (Dynadot) or name
@(Spaceship). - Records under it use the part in front of the host as the subhost or name:
_dmarc,google._domainkey.
curl https://api.maildns.io/api3.json \
--data-urlencode key=KEY --data-urlencode command=set_dns2 \
--data-urlencode domain=advisor.example.com \
--data-urlencode add_dns_to_current_setting=1 \
--data-urlencode subdomain0=_dmarc \
--data-urlencode sub_record_type0=txt \
--data-urlencode 'sub_record0=v=DMARC1; p=quarantine'2. Root domain plus subhost#
Put the root domain in domain and the full name under it as the subhost, the way registrars normally store subdomain records. Scripts written against a registrar often work this way already.
curl https://api.maildns.io/api3.json \
--data-urlencode key=KEY --data-urlencode command=set_dns2 \
--data-urlencode domain=example.com \
--data-urlencode add_dns_to_current_setting=1 \
--data-urlencode subdomain0=_dmarc.advisor \
--data-urlencode sub_record_type0=txt \
--data-urlencode 'sub_record0=v=DMARC1; p=quarantine'In root form, get_dns lists only your hosts' records, all as subhosts. Main records (Dynadot) and @ (the other styles) mean the root domain itself, which is not yours: sending one is an error.
Both forms in each style#
| Style | Host form | Root form |
|---|---|---|
| Dynadot | domain=advisor.example.com; main records, or subdomain0=_dmarc |
domain=example.com; subdomain0=_dmarc.advisor |
| Spaceship | /dns/records/advisor.example.com; names @, _dmarc |
/dns/records/example.com; names advisor, _dmarc.advisor |
| Cloudflare | the host's zone (/zones?name=advisor.example.com); names @, _dmarc or full |
the root's zone (/zones?name=example.com); full names |
| GoDaddy | /v1/domains/advisor.example.com/records; names @, _dmarc |
/v1/domains/example.com/records; names advisor, _dmarc.advisor |
| Porkbun | /dns/create/advisor.example.com; name empty or _dmarc |
/dns/create/example.com; name advisor or _dmarc.advisor |
| Namecheap | SLD=advisor.example&TLD=com; HostName1=@ or _dmarc |
SLD=example&TLD=com; HostName1=advisor or _dmarc.advisor |
Replies name records the way each style does: Cloudflare and Porkbun give full names, the others give names relative to what you addressed.
The same records in both forms#
| Full name | Type | Host form: domain=advisor.example.com |
Root form: domain=example.com |
|---|---|---|---|
advisor.example.com |
TXT, MX | main record, or name @ |
subhost advisor |
google._domainkey.advisor.example.com |
TXT | google._domainkey |
google._domainkey.advisor |
_dmarc.advisor.example.com |
TXT | _dmarc |
_dmarc.advisor |
mail.advisor.example.com |
CNAME | mail |
mail.advisor |
example.com |
any | not reachable | not yours: error |
www.example.com |
any | not reachable | not yours: error |
Which form to use#
- One host at a time: host form. Names are shorter and there is only one way to get them right.
- Several hosts in the same root domain in one call: root form. One call (
set_dns2,PUT,PATCH,setHosts) can carry records for every host your key has in that root, and it is applied as one change. - Reading: either. In root form, reads return the records of all your hosts in that root, and nothing else.
Replace calls work per host#
Some calls replace instead of adding: every host the call mentions ends up with exactly the records in the call, including the records under it. Hosts the call does not mention keep all their records.
| Style | Replaces | Adds |
|---|---|---|
| Dynadot | set_dns2 without add_dns_to_current_setting=1 |
set_dns2 with add_dns_to_current_setting=1 |
| GoDaddy | PUT /records; PUT /records/{type} (that type only) |
PATCH /records |
| Namecheap | setHosts, always |
none: read with getHosts and send everything back |
| Spaceship | never | PUT |
| Cloudflare | never (PUT replaces one record by id) |
POST |
| Porkbun | never (editByNameType changes one type at one name) |
/dns/create |
- In host form, the call mentions the host in
domain. - In root form, it mentions each host that one of its subhosts belongs to:
_dmarc.advisormentionsadvisor.example.com.
Careful: a replace that sends only the DMARC record (
subdomain0=_dmarc.advisor, orHostName1=_dmarc) leavesadvisor.example.comwith that one record. Its MX, SPF, verification and DKIM records are removed. Use the add call unless you mean to replace.
On Dynadot, GoDaddy and Namecheap themselves a replace rewrites the whole domain. MailDNS limits it to the hosts you name, so a record forgotten for one host can't take another host down.
Listing hosts#
Every style lists your key's hosts and nothing else: list_domain (Dynadot), GET /api/v1/domains (Spaceship), GET /zones (Cloudflare), GET /v1/domains (GoDaddy), /domain/listAll (Porkbun), namecheap.domains.getList (Namecheap). Hosts can't be added through the API.
Names that are not yours#
| You sent | Reply (Error or detail) |
|---|---|
| A domain that is neither one of your hosts nor the root of one | could not find domain in your account (404 in the styles that use status codes) |
| A name in the root that is not at or under one of your hosts | www.example.com is not one of your hosts (403) |
A main record with domain set to the root |
main records of example.com are not on your account; set records on your hosts with subdomain0 / sub_record_type0 / sub_record0 (403) |