The error object
When a request fails, the API returns an HTTP error status and a JSON body like the following:
{
"error": {
"code": "invalid_parameter",
"message": "\"checks\" takes ai, readiness, popularity, tech, dns, trust, summary and history; \"whois\" isn't one of them.",
"param": "checks",
"docs": "https://docs.checkanysite.com/errors#invalid_parameter",
"requestId": "req_8Hk2Qm9xT4bWzL0pRc7V"
}
}codeis stable. Branch on it in your code.messagesays what happened in plain language, and is safe to log.paramnames the parameter that caused the error, when there is one.docslinks to the code’s entry on this page.requestIdmatches theX-Request-Idheader. Include it when you contact us.
The MCP server returns the same codes inside a tool result, with isError set to true.
Status codes
The following table lists every code and whether sending the same request again can succeed. Rate limits explains how long to wait. We may add codes within v1, so handle a code you don’t recognise by its status.
| Status | Code | Retry? |
|---|---|---|
| 400 | invalid_json | No |
| 400 | invalid_parameter | No |
| 400 | invalid_domain | No |
| 401 | missing_api_key | No |
| 401 | invalid_api_key | No |
| 401 | revoked_api_key | No |
| 401 | expired_api_key | No |
| 403 | read_only_key | No |
| 403 | browser_request | No |
| 404 | not_found | No |
| 404 | no_result | No |
| 404 | scan_not_found | No |
| 405 | method_not_allowed | No |
| 409 | idempotency_key_in_use | Yes, with backoff |
| 410 | scan_expired | No |
| 413 | request_too_large | No |
| 415 | unsupported_media_type | No |
| 422 | site_refused | No |
| 422 | idempotency_key_reused | No |
| 429 | rate_limited | Yes, after Retry-After |
| 429 | quota_exceeded | No |
| 429 | key_limit_reached | No |
| 429 | scan_limit_reached | No |
| 500 | internal_error | Yes, with backoff |
| 503 | capacity | Yes, after Retry-After |
Status 400
invalid_jsonInvalid JSONRetry: No
The request body isn’t a valid JSON object.
What to do: Send a JSON object, such as
{"domain": "example.com"}, withContent-Type: application/json.invalid_parameterInvalid parameterRetry: No
A parameter is missing, unknown or has a value the API doesn’t accept.
paramnames it.What to do: Check the parameter’s name, type and allowed values in the API reference.
invalid_domainNot a public domainRetry: No
The address isn’t a public domain name we can check, such as an IP address, a private name or a typo.
What to do: Send a domain, such as
example.com. A full URL also works; we ignore its path.
Status 401
missing_api_keyNo API keyRetry: No
The request has no API key.
What to do: Send your key in the Authorization header as
Bearer cas_live_…, or in anX-API-Keyheader. Create a key at https://checkanysite.com/account/keys.invalid_api_keyUnknown API keyRetry: No
The API key doesn’t exist, or it was copied incorrectly.
What to do: Copy the key again from where you stored it. We show a key only once, so create a new one if you no longer have it.
revoked_api_keyRevoked API keyRetry: No
The API key was revoked and no longer works.
What to do: Use another key, or create a new one at https://checkanysite.com/account/keys.
expired_api_keyExpired API keyRetry: No
The API key has expired: it reached the expiry date set when it was created, or the end of its grace period after a rotation.
What to do: Use the key that replaced it, or create a new one at https://checkanysite.com/account/keys. To avoid downtime, rotate keys before they expire.
Status 403
read_only_keyRead-only keyRetry: No
This key is read-only. It can read stored results but can’t start a scan.
What to do: Get the stored result with GET /v1/sites/{domain}, or use a key with full access to start scans.
browser_requestRequest from a browserRetry: No
The API accepts requests from servers only, because a key sent from a browser is visible to anyone who opens the page.
What to do: Call the API from your server or a serverless function, and keep the key there.
Status 404
not_foundEndpoint not foundRetry: No
There is no API endpoint at this path.
What to do: Check the path in the API reference. Every endpoint is under the base URL, such as /v1/sites/{domain}.
no_resultNo stored resultRetry: No
We have no stored result for this site with these checks, or none as recent as you asked for.
What to do: Scan the site with POST /v1/scans. This request cost nothing.
scan_not_foundScan not foundRetry: No
There is no scan with this ID.
What to do: Use the
idreturned when you started the scan.
Status 405
method_not_allowedMethod not allowedRetry: No
The endpoint exists but doesn’t accept this HTTP method. The
Allowheader lists the methods it accepts.What to do: Use one of the methods in the
Allowheader.
Status 409
idempotency_key_in_useRequest in progressRetry: Yes, with backoff
A request with this
Idempotency-Keyis still being processed.What to do: Retry in a second with the same key. You’ll get the first request’s response, without a second charge.
Status 410
scan_expiredScan expiredRetry: No
This scan is older than the results we keep, so its result is no longer available. We keep each site’s latest result.
What to do: Get the site’s latest result with GET /v1/sites/{domain}, or scan it again with POST /v1/scans.
Status 413
request_too_largeBody too largeRetry: No
The request body is larger than the API accepts.
What to do: Send only the documented fields.
Status 415
unsupported_media_typeUnsupported content typeRetry: No
The request body has a content type other than JSON.
What to do: Send the body as JSON, with
Content-Type: application/json.
Status 422
site_refusedSite not checkedRetry: No
We don’t check this kind of site, such as adult websites.
What to do: There’s nothing to do. This request cost nothing.
idempotency_key_reusedIdempotency key reusedRetry: No
This
Idempotency-Keywas sent with a different request in the last 24 hours. Each key belongs to one request.What to do: Send a new key, such as a new UUID, with each new request. Reuse a key only to retry the same request.
Status 429
rate_limitedToo many requestsRetry: Yes, after Retry-After
This key has made more requests than its rate limit allows.
What to do: Wait the number of seconds in the
Retry-Afterheader, then retry. Spread your requests out over time.quota_exceededMonthly credits used upRetry: No
The account has used all its credits for this month.
What to do: Wait for the reset on the first of the month (UTC), or ask for more credits at https://checkanysite.com/account/usage#more-credits; extra credits are free during launch. Stored results cost the fewest credits.
key_limit_reachedKey limit reachedRetry: No
This key has used the monthly credit limit set for it.
What to do: Raise the key’s limit at https://checkanysite.com/account/keys, use another key, or wait for the reset on the first of the month (UTC).
scan_limit_reachedDaily scan limit reachedRetry: No
The account has started its 25 new scans for today (UTC).
What to do: Get stored results with GET /v1/sites/{domain}, or start the scan after 00:00 UTC. This request cost nothing.
Status 500
internal_errorInternal errorRetry: Yes, with backoff
Something went wrong on our side. This request cost nothing.
What to do: Retry in a minute. If the error continues, contact us and include the
requestId.
Status 503
capacityNo scan capacityRetry: Yes, after Retry-After
The API can’t start new scans right now. Stored results still work.
What to do: Get stored results with GET /v1/sites/{domain}, or start the scan later; the message says when.