DNS API
An API that lets you read and write DNS records programmatically. The underlying primitive most custom-domain SaaS products build on top of.
A DNS API is a programmatic interface to a DNS provider that lets you list, create, update and delete records in a zone without touching a dashboard. It is the primitive most custom-domain automation is built on: verifying a customer's setup, publishing an ACME DNS-01 challenge, or moving traffic during a failover all come down to writing a record from code.
Every major provider has one. They look similar in the documentation and behave very differently under load, which is where the choice actually gets made.
Domainee is a custom domains API for SaaS with a native MCP server — 50 domains and 100 GB free.
What the providers look like from outside
Probed unauthenticated on 2026-08-26, which is the cheapest way to see an API's auth model and how it reports failure:
| Provider | Style | Unauthenticated response |
|---|---|---|
| Cloudflare | REST + GraphQL | 403, error code 9106, Missing X-Auth-Email header |
| Route 53 | AWS SDK / signed REST | 403 SigV4 error |
| Google Cloud DNS | REST | 401, missing credentials |
| DNSimple | REST | 401 Authentication failed |
| Gandi LiveDNS | REST | 401, points at its token docs |
| Vercel DNS | REST | 403, missing authentication token |
| Porkbun | REST (POST + JSON body) | 200 — its ping endpoint is open and echoes your IP |
A detail worth noticing in that first row: Cloudflare's modern auth is a Bearer API token, but an unauthenticated call still gets rejected in terms of X-Auth-Email, the legacy global-key header. Both paths are live. Use scoped tokens rather than the global key — the global key authenticates everything on the account, including billing.
Porkbun's open ping is a genuinely useful design: it gives you a way to confirm reachability and see the source IP the API sees, which matters when a provider allow-lists by IP.
For most record read/write work the API style barely matters. What matters is the two things below.
The rate limits, and why the error codes lie
Published limits, checked 2026-08-26:
| Provider | Limit | On exceed |
|---|---|---|
| Cloudflare | 1,200 requests / 5 min per user, cumulative across dashboard, API key and API token; 200/sec per IP | 429, and all API calls blocked for the next five minutes |
| Route 53 | Two independent limits: API requests per second, and individual record changes per second aggregated across mutating actions | 400 Bad request, Code: Throttling |
| Cloudflare GraphQL | Cost-based, max 320 / 5 min | 429 |
Three consequences that catch people building custom-domain automation.
Cloudflare's budget is shared with humans. The 1,200-per-five-minutes limit is per user and counts dashboard activity. An engineer clicking through zones in a browser draws from the same bucket as your production automation, and blowing it blocks all API calls for five minutes, not just the ones that overran. If automation runs under a personal account, a colleague can throttle production by browsing. Give the automation its own account and its own scoped token.
Route 53 rate-limits record changes, not just calls. The second limit counts individual DNS record changes per second, aggregated across every mutating action. Batching 500 changes into one ChangeResourceRecordSets call does not buy you anything against it — the batch is 500 changes, not one request. Sizing your automation by request count will mislead you.
Route 53 reports throttling as 400, not 429. This is the trap worth writing down. Standard retry logic says retry 429 and 5xx, fail fast on 4xx because a client error will not fix itself. Route 53 returns 400 Bad request with Code: Throttling and Message: Rate exceeded, so a client following that rule treats a temporary overload as a permanent failure and gives up. You have to parse the Code element, not the status.
The Route 53 concurrency rule nobody mentions
There is a second 400 on the same path, and it is not a rate limit at all.
If Route 53 cannot finish processing a ChangeResourceRecordSets request before the next one arrives for the same hosted zone, it rejects the newcomer with 400 Bad request and Code: PriorRequestNotComplete.
Read that as what it is: writes to a single hosted zone are serialized. Not throttled, not queued — rejected. Your effective write throughput per zone is one in-flight change at a time, no matter what the rate limits say and no matter how many workers you run.
This shapes an architectural decision if you are building multi-tenant custom domains. Put every customer's records in one big hosted zone and all customer provisioning contends on that single serialized path, so onboarding ten customers at once produces nine rejections. Split across zones and the contention disappears, because the rule is per zone.
The fix in either design is the same shape: a per-zone work queue with retry on PriorRequestNotComplete, rather than parallel writers hoping not to collide. Treat it as a lock you do not hold, and be aware that this failure mode only appears under concurrency, which means it will not show up in testing and will show up on your best onboarding day.
DNS API and custom domain API are different layers
Easy to conflate, and the distinction decides which one you need:
| DNS API | Custom domain API | |
|---|---|---|
| What it manages | Records inside a zone you control | Hostnames, certificates and routing for your customers |
| Scope | One DNS provider | Any customer, on any DNS provider |
| Who holds the account | You, with the DNS provider | Your customer, with you |
| Certificate handling | None, it moves records | Provisioning and renewal |
| Example call | Create a TXT on example.com | Attach janesbakery.com to tenant 42 |
Both differ again from a domain API, which handles registration itself — who owns a name and until when — and is a wrapper over EPP rather than over a zone.
A SaaS offering custom domains usually consumes a DNS API internally while exposing a custom domain API outward. The internal use is for your own zone: publishing DNS-01 challenges, managing the CNAME target customers point at, running failover. The outward surface is what customers integrate.
When you need direct DNS API access
- You are issuing wildcard certificates. A wildcard can only be validated over DNS-01, which requires programmatic write access to the validating zone. HTTP-01 cannot substitute.
- You are running DNS as code. Zone files in version control, applied by CI.
- You are a registrar reseller, managing DNS on names you sell.
- You are automating internal infrastructure DNS — service discovery, blue/green cutovers, geo routing.
And the case that usually does not need it: a SaaS letting customers connect domains they own. Those zones live at the customer's provider, on accounts you have no access to. Your job there is to verify what they published, not to write it — check that their CNAME resolves to your target and that no stale record is left behind. The CNAME lookup and DNS record lookup do the read-side check, and the DNS propagation checker covers the propagation window.
Choosing one
Rank the criteria in this order, because it is roughly the order in which they will hurt:
- Write concurrency behaviour. Ask what happens when two writes to one zone overlap. This is the limit you will hit first and the one least likely to be in the marketing comparison.
- How throttling is reported. A provider that returns
429withRetry-Afteris meaningfully easier to build against than one that returns400and expects you to parse a body field. - TTL floor. Some providers refuse very low TTLs, which bounds how fast you can cut traffic over.
- Apex alias support. Whether the provider offers CNAME flattening, ALIAS or ANAME determines whether your customers can point an apex domain at you at all.
- Record type coverage. CAA if you pin certificate issuance, TXT for verification, SRV if you need it.
- API style. Last, honestly. REST or SDK, you are still just writing records.
Note that GoDaddy gates DNS API access on account eligibility and returns a 403 with a distinct error code when an account does not qualify, so confirm eligibility before designing around it.
FAQ
What is a DNS API? A programmatic interface to a DNS provider for reading and writing records in a zone — creating a TXT record, updating an A record, deleting a stale CNAME — without using a dashboard. Every major provider offers one, generally as REST with token authentication.
Which DNS API provider is best for a SaaS?
The one whose failure behaviour fits your write pattern, not the one with the nicest documentation. If you provision many records concurrently, weigh per-zone write concurrency first: Route 53 rejects overlapping changes to the same hosted zone outright with PriorRequestNotComplete, while Cloudflare's constraint is a shared 1,200-per-five-minute budget that dashboard use also consumes.
What is the difference between a DNS API and a domain API? A DNS API edits records inside a zone you already control. A domain API handles the registration itself — registering, renewing and transferring names — and is a wrapper over EPP. Different layers, usually different vendors.
Do I need a DNS API to offer custom domains? Not for your customers' zones, which live at their providers on accounts you cannot reach. You need one for your own zone, mainly to publish DNS-01 challenges and manage the CNAME target customers point at. For customer domains the work is verification, not writing.
Why is my Route 53 API call returning HTTP 400 when nothing is wrong with it?
Two causes share that status. Code: Throttling means you exceeded the request-rate or change-throughput limit and should back off exponentially. Code: PriorRequestNotComplete means another change to that same hosted zone is still processing. Both are transient and both need a retry, which is why retry logic keyed on the status code alone fails here — read the Code element.
Are Cloudflare's API rate limits per token? No, they are per user and cumulative: dashboard activity, API key calls and API token calls all draw from the same 1,200 requests per five minutes. Exceeding it blocks every API call for that user for five minutes. Run automation under its own account with a scoped token so a person browsing zones cannot throttle production.