Most of what makes an API client reliable is how it behaves when a request does not succeed.
The envelope
Every response, success or failure, has the same outer shape:
{ "ok": true, "data": { ... } }
{ "ok": false, "error": { ... } }
Branch on ok, not on the status code alone. The code tells you the class of problem; the error object names the specific one.
Status codes
| Code | Means | Retry? |
|---|---|---|
200 | Success | — |
400 | The request was malformed or failed validation | No — fix the request |
401 | The key is missing, wrong or revoked | No |
403 | The key is valid but lacks the scope | No |
404 | The zone or record does not exist | No |
409 | It conflicts with something that exists | No |
422 | Refused by a plan limit or a DNS rule | No |
429 | Rate limited | Yes, after waiting |
5xx | Something failed on our side | Yes, with backoff |
The pattern worth internalising: only 429 and 5xx are worth retrying. Everything else will fail identically however many times you send it, and a client that retries a 400 in a loop is a client that gets rate limited for no reason.
Rate limiting
Requests are counted per key, per minute. The default allowance is 120 requests a minute; exceed it and you get 429.
When you do:
- Wait before retrying. Immediately re-sending is what turns a brief limit into a sustained one.
- Back off exponentially — a second, then two, then four — rather than a fixed interval.
- Add jitter if several workers share a key, or they will all retry in step and hit the limit together.
Better still, do not reach it. Most clients that get rate limited are polling for something that rarely changes. List a zone's records once and work from that, rather than fetching before every write.
Failures that are not the API's
Two worth separating out, because the fix is elsewhere:
A plan limit. 422 on creating a zone or a record type usually means the plan does not allow it — not a bug in the request. The API enforces exactly what the portal does.
A validation rule. A CNAME at the apex, an MX pointing at an IP, a hostname that is an IP: refused, because each produces a record resolvers reject. The error says which rule; the record types article says why.
Designing for the boring cases
- Make writes idempotent where you can. Fetch, compare, and write only if different. It costs one read and removes a whole class of duplicate-record bug.
- Log the error object, not just the code.
400on its own tells a future reader nothing. - Fail loudly on
401and403. A revoked key produces those on every request, and a client that swallows them looks like it is working while doing nothing. - Do not hard-code the base URL. It follows the panel's hostname — see getting started with the API.
Related
Last reviewed 2026-09-16.
Open a ticket from the control panel, or use the contact form if you cannot sign in. If a domain is down, the status page is the fastest way to find out whether it is us.