Failed requests return a non-2xx status and a JSON body with one error object:
{
"error": {
"type": "billing_error",
"code": "insufficient_credits",
"message": "This needs 40 credits, and the balance is 12. Top up to continue.",
"credits_required": 40,
"credits_balance": 12,
"doc_url": "/docs/api-reference/error-codes#insufficient_credits"
}
}
| Field | Description |
|---|---|
type |
Broad category. Branch on this first. |
code |
Specific reason. Stable, safe to match in code. |
message |
Human-readable. May change, so don't parse it. |
param |
The request field at fault, as a dotted path for nested fields, e.g. redirect_rules.0.source. |
doc_url |
Link to the code's entry on this page. |
| extra fields | Some codes add context, e.g. credits_required and credits_balance, limit and current, details, audit_id. |
Error types
| Type | Status | Meaning |
|---|---|---|
invalid_request_error |
400, 404, 409, 422 |
The request was malformed, conflicted or pointed at nothing |
authentication_error |
401 |
No API key, or a bad one |
billing_error |
402 |
The credit balance can't cover the request |
permission_error |
403 |
Valid key, not allowed to do this |
rate_limit_error |
429 |
Too many requests. Back off and retry. |
api_error |
5xx |
Something failed on our side. Safe to retry. |
invalid_request_error
parameter_missing
A required parameter is missing, and param names it. Status 400.
parameter_invalid
A parameter has the wrong type or format, or is out of range. It's also returned for an ID with the wrong prefix. param names the parameter. Status 400.
parameter_unknown
The body contains a field that doesn't exist, often the camelCase spelling of a snake_case field. param names it, and snake_case explains the convention. Status 400.
invalid_hostname
The hostname is empty or isn't a valid hostname. Status 400.
invalid_origin_host
The origin host doesn't normalize to a valid hostname. Status 400.
origin_host_same_as_domain
The origin host can't be the same as the domain. Status 400.
origin_host_is_editor_url
The origin host is an editor URL. Use the published project URL instead. Status 400.
redirect_limit_reached
The domain already has the maximum number of redirect rules. The error includes limit and current. Status 400.
invalid_custom_headers
One or more response header rules failed validation. The error's details lists the problems. Status 400.
sitemap_fetch_failed
The sitemap URL couldn't be fetched. Status 400.
sitemap_parse_failed
The sitemap URL returned something other than a valid XML sitemap. Status 400.
invalid_urls
At least one audit seed URL is invalid or isn't on the target domain. Status 400.
no_sitemap
The operation needs a sitemap, and the domain doesn't have one. Status 400.
resource_missing
The domain, audit, prompt or other object doesn't exist on your account, or no endpoint matches the URL and method. Status 404.
audit_in_progress
An audit is already running for this domain. The error includes its audit_id. Status 409.
domain_already_connected
The domain is already connected to an account. Status 409.
business_already_claimed
Another account has already verified this business's website. Contact support to move it. Status 409.
action_not_waiting
The action was already approved, dismissed or published. Only a waiting action can be approved or dismissed. Status 409.
verification_failed
The business couldn't be verified: the signed-in email isn't at its website's domain, or nobody is signed in. On Growth, its prompts aren't checked until it is. Status 422.
no_new_pages
new_pages_only was set, and nothing has changed since the last audit. Status 422.
authentication_error
missing_api_key
The request doesn't include an API key. Status 401.
invalid_api_key
The API key is invalid or has been revoked. See Authentication. Status 401.
billing_error
insufficient_credits
Your credit balance can't cover the request. The error includes credits_required and credits_balance, so you know how much to top up before retrying. Status 402.
plan_limit_reached
Adding this would pass your plan's limit: active questions, or markets. The error includes limit and current. Upgrade, or pause or remove one first; a paused question doesn't count. Status 403.
permission_error
requires_unscoped_key
This endpoint needs an account-wide key rather than a domain-scoped one. Status 403.
domain_not_owned
The domain isn't connected to your account. Status 403.
api_key_domain_scope_mismatch
The key is valid, but it's scoped to a different domain. Status 403.
domain_suspended
The domain is suspended and can't be added again. Status 403.
permission_denied
You're signed in as a team member whose role doesn't allow this change. Viewers can only read; editors can't manage billing, the team, API keys or account settings, and approve fixes only when the owner allows it. Status 403.
rate_limit_error
rate_limited
This key sent too many requests. Wait about a minute, then retry. Status 429.
api_error
internal_error
Something failed unexpectedly on our side. Retry, and contact support if it keeps happening. Status 500.
insert_failed
The record couldn't be saved. Retry the request. Status 500.
not_implemented
The endpoint exists, but its logic hasn't shipped yet. Status 501.
archive_unavailable
The audit's archived pages couldn't be read. Retry later. Status 503.
service_unavailable
The configuration couldn't be applied. Retry the request. Status 503.
Best practices
- Branch on
typefirst and then oncode. Don't parsemessage, since its wording can change. - Send
Accept: text/htmlon render requests made for crawlers. - Rotate keys regularly, and revoke any key that leaks from the dashboard.
- Keep
prewarmon for important pages so they're cache hits right after a purge. - When the Render API returns
304, followLocationto the origin.