# GoDaddy-style API

`https://api.maildns.io/v1` takes the same paths, header and JSON bodies as GoDaddy's Domains API (v1) for DNS records. Point a GoDaddy client at that base URL and give it your MailDNS key and secret.

## Requests and replies

```http
Authorization: sso-key KEY:SECRET
Content-Type: application/json
```

- Reads reply **200** with JSON. Adds and replaces reply **200** with an empty body once the change is saved at the authoritative nameservers. `DELETE` replies **204**.
- `{domain}` is one of your hosts (`advisor.example.com`) or the root domain they live in (`example.com`). Record names are relative to it, and `@` is `{domain}` itself. See [Hosts](https://maildns.io/docs/hosts.md).
- Errors are GoDaddy's `{"code", "message"}`:

```json
{"code": "ACCESS_DENIED", "message": "This API key doesn't work for nameservers."}
```

| HTTP | `code` | Meaning |
|---|---|---|
| 401 | `UNABLE_TO_AUTHENTICATE` | Wrong key or secret, or a call from an IP address the key is not locked to |
| 403 | `ACCESS_DENIED` | A name outside your hosts, an NS record, a nameserver change, or anything outside DNS records |
| 404 | `NOT_FOUND` | A domain that is not yours, or an unknown path |
| 422 | `INVALID_BODY` | An invalid record: type, data, TTL, CNAME clash, too many records. `message` says which. |
| 429 | `TOO_MANY_REQUESTS` | Too many requests, or an earlier change to the same root domain is still running. Wait `Retry-After` seconds and retry. |
| 503 | `UNAVAILABLE` | The change could not be made right now. Nothing was changed. |

## Endpoints

| Method and path | Body | Does |
|---|---|---|
| `GET /v1/domains` | | Your hosts |
| `GET /v1/domains/{domain}` | | One host, with `nameServers` |
| `GET /v1/domains/{domain}/records` | | All records |
| `GET /v1/domains/{domain}/records/{type}` | | Records of one type |
| `GET /v1/domains/{domain}/records/{type}/{name}` | | Records of one type at one name |
| `PATCH /v1/domains/{domain}/records` | `[records]` | **Add** records |
| `PUT /v1/domains/{domain}/records` | `[records]` | **Replace** all records of each host the body mentions |
| `PUT /v1/domains/{domain}/records/{type}` | `[records]` | **Replace** all records of that type on each host the body mentions |
| `PUT /v1/domains/{domain}/records/{type}/{name}` | `[{data, ttl, priority}]` | **Replace** the records of that type at that name |
| `DELETE /v1/domains/{domain}/records/{type}/{name}` | | Delete the records of that type at that name |

## Records

```json
{"type": "TXT", "name": "@", "data": "google-site-verification=3J9tq0iV8pTt1yW5zKc2mE7aR4bN6hD0sF1gL8xQ", "ttl": 3600}
{"type": "MX", "name": "@", "data": "smtp.google.com", "priority": 1, "ttl": 3600}
{"type": "TXT", "name": "google._domainkey", "data": "v=DKIM1; k=rsa; p=MIIBIjANBgkqh...", "ttl": 3600}
{"type": "CNAME", "name": "mail", "data": "ghs.googlehosted.com", "ttl": 3600}
{"type": "A", "name": "@", "data": "203.0.113.10", "ttl": 3600}
```

`priority` is for MX only. `ttl` follows [the TTL rule](https://maildns.io/docs/keys.md#record-rules). TXT `data` goes without surrounding quotes, in one piece.

## List hosts

```bash
curl https://api.maildns.io/v1/domains \
  -H 'Authorization: sso-key KEY:SECRET'
```

```json
[
  {"domain": "advisor.example.com", "status": "ACTIVE", "expires": "2027-01-01T00:00:00.000Z", "renewAuto": true},
  {"domain": "billing.example.com", "status": "ACTIVE", "expires": "2027-01-01T00:00:00.000Z", "renewAuto": true}
]
```

`expires` and `renewAuto` describe the root domain. One host, with its nameservers (read-only):

```bash
curl https://api.maildns.io/v1/domains/advisor.example.com \
  -H 'Authorization: sso-key KEY:SECRET'
```

```json
{"domain": "advisor.example.com", "status": "ACTIVE", "expires": "2027-01-01T00:00:00.000Z", "renewAuto": true, "nameServers": ["ns1.example.net", "ns2.example.net"]}
```

## Read records

```bash
curl https://api.maildns.io/v1/domains/advisor.example.com/records/TXT \
  -H 'Authorization: sso-key KEY:SECRET'
```

```json
[
  {"type": "TXT", "name": "@", "data": "v=spf1 include:_spf.google.com ~all", "ttl": 3600},
  {"type": "TXT", "name": "_dmarc", "data": "v=DMARC1; p=quarantine", "ttl": 3600}
]
```

## Add records

`PATCH` adds the records to what is there. Records already there (same type, name and data) are skipped, so repeating it is harmless.

```bash
curl -X PATCH https://api.maildns.io/v1/domains/advisor.example.com/records \
  -H 'Authorization: sso-key KEY:SECRET' -H 'Content-Type: application/json' \
  -d '[
    {"type": "MX", "name": "@", "data": "smtp.google.com", "priority": 1, "ttl": 3600},
    {"type": "TXT", "name": "@", "data": "v=spf1 include:_spf.google.com ~all", "ttl": 3600},
    {"type": "TXT", "name": "_dmarc", "data": "v=DMARC1; p=quarantine", "ttl": 3600}
  ]'
```

## Replace records

The three `PUT` calls replace, so use them with care:

- `PUT /records` leaves each host the body mentions with **exactly** the records in the body, including the records under it. On GoDaddy itself this call replaces the whole domain; MailDNS limits it to the hosts you name.
- `PUT /records/{type}` replaces every record of that type on those hosts. `PUT /records/TXT` with only an SPF record removes the host's verification, DKIM and DMARC records too.
- `PUT /records/{type}/{name}` touches one type at one name. It is the safe way to change a single record, such as DMARC:

```bash
curl -X PUT https://api.maildns.io/v1/domains/advisor.example.com/records/TXT/_dmarc \
  -H 'Authorization: sso-key KEY:SECRET' -H 'Content-Type: application/json' \
  -d '[{"data": "v=DMARC1; p=reject", "ttl": 3600}]'
```

## Delete records

Deletes every record of that type at that name:

```bash
curl -X DELETE https://api.maildns.io/v1/domains/advisor.example.com/records/TXT/_dmarc \
  -H 'Authorization: sso-key KEY:SECRET'
```

To delete one of several TXT records at the same name, `PUT /records/TXT/@` with the ones to keep.

## Nameservers

Changing nameservers (`PATCH /v1/domains/{domain}` with `nameServers`, or any NS record) is refused with HTTP 403, `ACCESS_DENIED`, `This API key doesn't work for nameservers.` Registration calls (purchase, renew, transfer, contacts) are not available either. Reading `nameServers` is fine.

## Check that a record is live

The live check is a [Dynadot-style call](https://maildns.io/docs/propagation.md), and it takes the same key:

```bash
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=_dmarc \
  --data-urlencode record_type=txt --data-urlencode 'value=v=DMARC1; p=quarantine'
```

Wait for `"Live": "yes"` before asking Google or Microsoft to verify.
