Error codes
Every error from the dnswiz API conforms to
RFC 7807
problem-details. The type field is a stable URI that points back
to this page anchored at the slug.
{
"type": "https://dnswiz.io/errors/conflict",
"title": "Conflict",
"status": 409,
"detail": "record name+type already exists in zone",
"instance": "/v1/zones/abc.../records",
"code": "conflict",
"errors": { "field": "name" }
}
codeis the slug, the same string that’s the last path segment oftype. Easier to match against than the full URI.errorsis an optional map for field-level details (validation errors usually carry the offending field name here).instanceis the request path. Combined withX-Request-IDon the response, this is enough to grep our logs.
Catalog
| Slug | Status | When it fires |
|---|---|---|
bad-request | 400 | Generic client error, usually validation failed before we could pick a more specific code. Look at detail and errors. |
unauthorized | 401 | Missing, invalid, or expired bearer token. |
quota-exceeded | 402 | Your plan’s quota is hit (max zones, max records per zone, monthly query cap). |
forbidden | 403 | Auth is good but the action isn’t allowed (RBAC, sudo required, API-key IP allow-list, etc). |
not-found | 404 | The resource doesn’t exist, or it’s in another workspace and we won’t confirm it. |
conflict | 409 | Resource state collides with the request (CNAME exclusivity, duplicate name+type, deleting a zone that has records, etc). |
gone | 410 | Resource was deleted and won’t return. Hit by re-runs of a delete with a stale id. |
unprocessable | 422 | Body parsed but semantically invalid (e.g. SRV missing port). |
rate-limited | 429 | Per-IP or per-tenant API rate limit. Retry-After header tells you when to try again. |
internal | 500 | We broke something. The response carries a request id; include it when you contact support. |
bad-gateway | 502 | A third-party service we rely on (payments, certificate authority, email) returned an error. Retry usually works. |
unavailable | 503 | A feature isn’t configured on this instance yet (e.g. certificate issuance or outbound email). |
Per-error notes
bad-request
Catch-all for client errors that didn’t fall into a more specific
slug. If you see this and the detail doesn’t make sense, file an
issue, we’d rather promote it to a real slug than leave you
guessing.
unauthorized
Bearer is missing, malformed, expired, or revoked. Re-auth (magic link or API key mint) and retry. If you’re using an API key, check Settings → API keys for revocation or expiry.
quota-exceeded
Hit on POST /v1/zones, POST /v1/zones/.../records, and at
query-volume boundaries. Upgrade or remove some resources. Current
usage vs cap is on the dashboard usage card.
forbidden
Three common causes:
- RBAC: your tenant role doesn’t allow the action (only owners can delete the workspace, for example).
- Sudo required: destructive actions (like deleting the workspace) need a recent re-authentication.
- IP allow-list: the API key was minted with a CIDR allow-list
and you’re calling from outside it. The
errors.codewill beip-not-allowed.
not-found
“Doesn’t exist” and “exists in another workspace” look identical on purpose, we never confirm whether an id belongs to someone else. Probing ids tells you nothing.
conflict
Common cases:
- CNAME exclusivity: adding any record at a name that already has a CNAME, or adding a CNAME at a name that already has another record. RFC 1034 §3.6.2.
- Duplicate (zone, name, type): records are unique on that key.
- Zone has records: delete the records first, then the zone. (Or use the destructive force-delete in the danger zone.)
gone
You requested a resource that was deleted. Distinct from not-found
so retry logic can tell “never existed” from “no longer exists.”
unprocessable
Body parsed as valid JSON, but failed semantic validation. Examples:
SRV record missing port, GEO record with zero regions, CAA with
an invalid tag. errors map points at the offending field.
rate-limited
Two flavors:
- Per-IP auth limit: 10/min sustained, burst 20, on
/v1/auth/sendand/v1/auth/verify. Slow down or use API keys. - Per-tenant API limit: applies to authenticated mutations. Configurable in admin settings.
Retry-After header is the seconds to wait. Honor it.
internal
Means we crashed or hit an unexpected state. The response includes a request id. Send it (and the rough time) and we can find the log line. We watch these closely; they shouldn’t happen.
bad-gateway
A third-party service we depend on (payments, certificate authority, email) returned an error. Usually transient, retry. If it persists, contact support with the request id + rough time.
unavailable
A feature isn’t set up on this instance yet, most often certificate issuance or outbound email before they’ve been configured. It’s an operator setup step, not something wrong on your end.