Docs pages

Quickstart#

From a new key to a live TXT record in five calls. The examples are Dynadot style, the simplest to read; every API style has the same calls in its own shape, and the same key works in all of them. They use the host advisor.example.com: use one of yours, and replace KEY (and SECRET where a style needs one) with yours.

Before you start#

  • You have a MailDNS key. For Spaceship-style calls you also have its secret.
  • If your key is locked to IP addresses, run these from one of them. From anywhere else the key reads as invalid key.
  • Any HTTP client works. The examples use curl; the Google Workspace recipe has the same flow in Python.

1. Check the key#

Shell
curl 'https://api.maildns.io/api3.json?key=KEY&command=account_info'
JSON
{
  "AccountInfoResponse": {
    "ResponseCode": 0,
    "Status": "success",
    "AccountInfo": {"Username": "acme-inboxes", "Hosts": "3"}
  }
}

Username is the name your key was issued under; Hosts is how many hosts it reaches. If you get {"Response": {"ResponseCode": "-1", "Error": "invalid key"}}, check the key and the IP address you are calling from.

2. List your hosts#

Shell
curl 'https://api.maildns.io/api3.json?key=KEY&command=list_domain'
JSON
{
  "ListDomainInfoResponse": {
    "ResponseCode": 0,
    "Status": "success",
    "MainDomains": [
      {
        "Name": "advisor.example.com",
        "RootDomain": "example.com",
        "Expiration": "1798761600000",
        "Registration": "1735689600000",
        "NameServerSettings": {"Type": "Dynadot DNS"},
        "Status": "active"
      }
    ]
  }
}

One entry per host. Name is the host; RootDomain is the registered domain it lives in.

3. Read a host's records#

Shell
curl 'https://api.maildns.io/api3.json?key=KEY&command=get_dns&domain=advisor.example.com'
JSON
{
  "GetDnsResponse": {
    "ResponseCode": 0,
    "Status": "success",
    "GetDns": {
      "NameServerSettings": {
        "Type": "Dynadot DNS",
        "MainDomains": [],
        "SubDomains": [],
        "TTL": "3600"
      }
    }
  }
}

A new host has no records yet. MainDomains are records at the host; SubDomains are records under it.

4. Add a TXT record#

Writes go as a form-encoded POST, so long values and your key stay out of the URL. --data-urlencode encodes each value for you.

Shell
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 main_record_type0=txt \
  --data-urlencode main_record0=google-site-verification=3J9tq0iV8pTt1yW5zKc2mE7aR4bN6hD0sF1gL8xQ
JSON
{"SetDnsResponse": {"ResponseCode": 0, "Status": "success"}}

Always send add_dns_to_current_setting=1 unless you mean to replace every record on the host. Without it, set_dns2 replaces the host's records with exactly the ones in the call. See replace calls.

5. Wait until it is live#

The write returned once the record was saved at the authoritative nameservers. Before you ask Google to verify, check that every one of them serves it:

Shell
curl https://api.maildns.io/api3.json \
  --data-urlencode key=KEY \
  --data-urlencode command=dns_status \
  --data-urlencode domain=advisor.example.com \
  --data-urlencode subdomain=@ \
  --data-urlencode record_type=txt \
  --data-urlencode value=google-site-verification=3J9tq0iV8pTt1yW5zKc2mE7aR4bN6hD0sF1gL8xQ
JSON
{
  "DnsStatusResponse": {
    "ResponseCode": 0,
    "Status": "success",
    "Records": [
      {
        "Name": "advisor.example.com",
        "RecordType": "TXT",
        "Value": "google-site-verification=3J9tq0iV8pTt1yW5zKc2mE7aR4bN6hD0sF1gL8xQ",
        "Live": "yes",
        "Servers": {"ns1.example.net": "yes", "ns2.example.net": "yes"}
      }
    ]
  }
}

Live is yes once every nameserver answers with the record. Until then, ask again every 15 seconds or so. Usually it is yes on the first or second try. More in Checking propagation.

The same five calls, Spaceship style#

Shell
# 1 + 2. Your hosts (a wrong key or secret is HTTP 401)
curl 'https://api.maildns.io/api/v1/domains?take=100' \
  -H 'X-API-Key: KEY' -H 'X-API-Secret: SECRET'

# 3. A host's records
curl 'https://api.maildns.io/api/v1/dns/records/advisor.example.com?take=500' \
  -H 'X-API-Key: KEY' -H 'X-API-Secret: SECRET'

# 4. Add a TXT record (HTTP 204, no body)
curl -X PUT https://api.maildns.io/api/v1/dns/records/advisor.example.com \
  -H 'X-API-Key: KEY' -H 'X-API-Secret: SECRET' -H 'Content-Type: application/json' \
  -d '{"force": false, "items": [{"type": "TXT", "name": "@", "ttl": 3600,
       "value": "google-site-verification=3J9tq0iV8pTt1yW5zKc2mE7aR4bN6hD0sF1gL8xQ"}]}'

# 5. Is it live?
curl -G https://api.maildns.io/api/v1/dns/status/advisor.example.com \
  -H 'X-API-Key: KEY' -H 'X-API-Secret: SECRET' \
  --data-urlencode name=@ --data-urlencode type=TXT \
  --data-urlencode value=google-site-verification=3J9tq0iV8pTt1yW5zKc2mE7aR4bN6hD0sF1gL8xQ

In the other styles#

The add call from step 4, for each style. Full examples are on each style's page.

Style Add a record
Cloudflare POST /client/v4/zones/{zone_id}/dns_records with {"type": "TXT", "name": "@", "content": "..."}
GoDaddy PATCH /v1/domains/advisor.example.com/records with [{"type": "TXT", "name": "@", "data": "..."}]
Porkbun POST /api/json/v3/dns/create/advisor.example.com with {"apikey": "KEY", "secretapikey": "SECRET", "name": "", "type": "TXT", "content": "..."}
Namecheap namecheap.domains.dns.setHosts with SLD=advisor.example, TLD=com, HostName1=@, RecordType1=TXT, Address1=... (replaces: send the host's other records too)

Next#