API Errors

The DNS Check API reports errors as RFC 9457 Problem Details, with the content type application/problem+json:

{
  "type": "https://www.dnscheck.co/api/errors#invalid_parameter",
  "title": "Invalid parameter",
  "status": 400,
  "code": "invalid_parameter",
  "detail": "The limit parameter is invalid.",
  "errors": [
    { "field": "limit", "code": "invalid", "message": "Must be a whole number from 1 to 200." }
  ],
  "request_id": "6a1f0c2e-3b7d-4e59-a8c4-2f9d1e7b5a30"
}

Error Codes

Which errors are worth retrying: idempotency_key_in_use, service_unavailable, and every 429 can succeed once you wait the Retry-After header's seconds, and internal_error can succeed later, so retry it with backoff. Every other error needs a change to the request first. When you retry a POST, send the same Idempotency-Key so a request that went through isn't repeated (see idempotency keys).

An error without Problem Details comes from Cloudflare, which sits in front of DNS Check, and never reached DNS Check. Its Content-Type isn't application/problem+json, and its body may be an HTML page or plain text, such as error code: 521, so check the Content-Type before parsing an error as JSON. What to do depends on its status:

Code Status Meaning
api_key_in_query 400 API key sent in the URL. API v2 takes the API key only in the Authorization header (Authorization: Bearer <key>) since a key in a URL ends up in logs, browser history, and Referer headers. Remove the api_key query parameter, and consider rotating the key.
invalid_parameter 400 Invalid parameter. A query parameter or header has a value this endpoint doesn't accept, or the request has a query parameter the endpoint doesn't take, such as a misspelled staus. errors names each one and what it accepts.
malformed_request 400 Malformed request. The request body isn't valid JSON, or isn't a JSON object, or the request takes no body: a GET, a DELETE, or an on-demand check, whose parameters, such as limit, go in the query string (an empty {} body is fine). Send the fields as one object, such as {"name": "Mail"}. Its path, query string, and body must also be valid UTF-8.
api_key_missing 401 API key required. This request needs an API key, sent as Authorization: Bearer <key>. Only the example record group can be read without one.
api_key_invalid 401 Invalid API key. The Authorization header doesn't hold an enabled API key. Check that it reads Bearer, a space, and the whole key, and that the key hasn't been disabled or deleted on the API Keys page.
insufficient_scope 403 API key lacks access. The API key's access doesn't allow this request, and detail names the access it needs. Change the key's access on the API Keys page, or use a key that has that access.
feature_not_in_plan 403 Feature not in plan. The request uses a feature the account's plan doesn't include, such as custom name servers, check frequency, invert check, or load balancer monitoring. detail names it, and upgrade_url links to the plans that have it.
plan_limit_reached 403 Plan limit reached. The account already has as many record groups or DNS records as its plan allows. limit is the plan's limit, and upgrade_url links to larger plans. Deleting some frees room.
account_expired 403 Account expired. The account's subscription has expired, so it can only delete record groups and DNS records until it's renewed, or until it's down to the Basic plan's limits and switched to that plan.
example_group_read_only 403 Example group is read-only. Anyone can read the example record group, but never change it through the API. Create your own record group to try writes.
not_found 404 Not found. Nothing your API key can read has this ID, or no endpoint matches the URL. Anything belonging to another account is also not found, so you can't probe IDs.
method_not_allowed 405 Method not allowed. The endpoint exists, but doesn't take this HTTP method. The Allow header lists the methods it does take. API v2 changes resources with PATCH, never PUT.
idempotency_key_in_use 409 Idempotency key in use. Another request with the same Idempotency-Key is still running. Retry after the Retry-After header's seconds to get its response.
precondition_failed 412 Precondition failed. The resource was edited since the ETag sent in If-Match was read. Get it again, reapply your change, and retry with the new ETag.
unsupported_media_type 415 Unsupported media type. Send request bodies as Content-Type: application/json. PATCH also accepts application/merge-patch+json.
validation_failed 422 Validation failed. One or more fields are missing or invalid. errors lists each problem, with a message saying how to fix it.
idempotency_key_reused 422 Idempotency key reused. The Idempotency-Key was already used within the last 24 hours for a request with a different method, path, query string, or body. Use a new key for each distinct request.
too_many_writes 422 Too many writes for one request. The request needs more writes than the account's plan allows in a minute, so it can't go through as one request. limit is the most one request can use: split the work into requests that fit, such as importing a large zone file in parts.
rate_limited 429 Rate limit reached. The account has used its requests, writes, or on-demand checks for this minute. Wait for the number of seconds in the Retry-After header. Every key on an account shares one budget, and paid plans have larger ones.
daily_quota_exceeded 429 Daily write quota reached. The account has made as many writes today (UTC) as its plan allows, ten times its per-minute limit. Retry-After gives the seconds until midnight UTC.
internal_error 500 Internal error. Something went wrong on our side. Retry later, and if it keeps happening, contact us with the request_id.
service_unavailable 503 Service unavailable. DNS Check is briefly unavailable, such as during database maintenance. Wait for the number of seconds in the Retry-After header, then retry.

The OpenAPI document lists the codes each endpoint can return.

Field Error Codes

validation_failed and invalid_parameter errors list each problem found in errors, and each entry has its own code that says what's wrong with that one field or parameter. The top-level code says what kind of error the request hit. A field error code never changes, but more can be added, so treat any you don't recognize as invalid.

Code Meaning
required The field is missing or empty.
invalid_type The value is the wrong JSON type, such as a string where a number belongs.
unknown_field The body has a field this endpoint doesn't accept.
unknown_parameter The query string has a parameter this request doesn't accept.
too_short The value is too short, or the list has too few entries.
too_long The value is too long, or the list has too many entries.
unsupported The value isn't one this field supports, or doesn't work with the other fields sent, such as load_balancer on a TXT record.
already_exists Another resource already has this value, such as a record group with the same name.
no_records The zone file holds no DNS records we can read.
nothing_imported The zone file added no DNS records, and the message says why.
invalid The value is invalid for any other reason, and the message says how.