Skip to main content
A failed call returns an HTTP status code and, almost always, a JSON body. The status code tells you what kind of problem it is. The body tells you which one. This page lists the bodies the API returns, word for word, and what to do about each. Errors that only one endpoint returns are listed in that endpoint’s guide.

Read an error

Branch on the status code first, then read the body. The keys in the body depend on which part of the platform refused the call: To log a readable message, take the first of detail, error_message, details, error and message that the body contains. If it has none of them, the body is a set of field errors. Some bodies add a machine-readable key: resource on allowance and capacity refusals, and code on some Attack Surface refusals. Branch on those keys when they are present. When you match a message, match its start, not the whole string.
A 4xx from the service behind an endpoint is forwarded with its own keys. Do not rely on the value types inside it: numbers, true, false and null can arrive as strings such as "25", "True", "False" and "None".
Not every error body is JSON. A path that does not exist returns an HTML page with 404.

The order of checks

The API checks each request in this order and stops at the first refusal:
  1. Path. An unknown path returns 404 with an HTML page. A path missing its trailing / returns a 301 redirect.
  2. API key. A missing, unknown, revoked or expired key returns 401.
  3. Organization. A request that names another organization returns 403.
  4. License and plan feature. 403.
  5. Per-second rate limit and API Calls allowance. 429.
  6. Method. A method the endpoint does not accept returns 405.
  7. The endpoint itself. A spent feature allowance (429), a full capacity slot (409), request validation (400), then the service behind the endpoint: its own 4xx, or 502, 503 and 504. Endpoints differ in whether they validate the body before or after the allowance and capacity checks.
When Content-Type is exactly application/json, a body that does not parse is refused with 400 at step 3, before the license check and the rate limit. Refusals at steps 1 to 4 never reach the rate limit. They carry no X-RateLimit-* headers and count toward none of your limits. From step 5 on, a response that is not a 2xx uses none of your API Calls allowance and none of any feature allowance: a unit taken for the call is refunded. A response that passed the rate limit still counts toward the per-second limit. Rate limits and Plans and quotas explain the limits.

Branch on the status code

The helper below retries only what can succeed on a retry: a per-second 429 on any method, and a 500, 502, 503 or 504 on a GET. It raises everything else with the status and the body attached, so your code can branch on them.
Check before you retry a call that starts a job. After a 500, 502, 503 or 504 on a POST that starts a scan, a search or a report, list that feature’s jobs before you send it again. The service behind the endpoint may have started the job before the error. A 504 means only that the API stopped waiting.
A 2xx can still carry refusals. Quick search answers 201, and 200 when you read the record again. Each source in it reports its own outcome, such as not_entitled or quota_exceeded. See Quick search.

400 Bad Request

Request validation answers with one key per field. Each key holds a list of problems:
A rule that spans several fields uses non_field_errors:
A body that is not valid JSON returns {"detail": "JSON parse error - …"}, followed by the parser’s message.
Send JSON bodies with Content-Type: application/json. Without that header, curl -d sends a form body. The API reads it as a form and reports every field as missing.
Other 400 bodies come from parameter checks in the API, such as {"error": "filter_task_id parameter is required"}, or from the service behind the endpoint. Some of those enforce a business rule that clears with time. Attack Surface, for example, refuses a new assessment while your organization already has the maximum number running or queued, and refuses an assessment equivalent to one started for the same domain in the last 30 minutes. Both answer 400 with a details message. See Attack Surface assessments.

401 Unauthorized

A 401 with any other body comes from the service behind the endpoint, not from your key. Retry a GET later with backoff, and contact support if it repeats. Authentication explains how to create, send and replace keys.

403 Forbidden

To tell a plan refusal from a lapsed license, call get_api_call_usage for the current month. It has no plan feature check, so it returns Your license is not active. when the license is the cause. get_direct_org_info answers even without a license in force, which confirms the key itself works. On monitor create and update, a service that is missing or not recognized also returns This feature is not included in your plan. See Monitors. A 403 with any other body comes from the service behind the endpoint. The endpoint’s guide describes it.

404 Not Found

Copy each path exactly as the API reference shows it. Most paths end in /, and a few do not. A request that drops the trailing / gets a 301 redirect to the path with it. Most HTTP clients follow the redirect and resend a POST as a GET, so the call you meant never runs.

409 Conflict

A 409 with resource and limit means a capacity slot is full. Nothing is created:
limit is your organization’s slot count, packs included. A limit of 0 means your plan includes none. Retrying fails until you free a slot or add a pack. Capacity slots explains how each slot is freed. Other 409s mean the object is not in a state that allows the call. Most come from the service behind the endpoint: A Filtered credentials export that has expired or failed returns 410 from the same download call, with an error_message. Exports expire 24 hours after creation. Create a new one.

422 Unprocessable Entity

A 422 comes from the service behind the endpoint. It refused a value that passed the API’s own validation, such as an impossible date. The API reference lists it for Credential Check and Ransomwatch endpoints. Credential Check answers {"detail": ...}, where detail is a message or a list of field errors. See Credential Check errors. Do not retry the same value.

429 Too Many Requests

The API returns four kinds of 429. Tell them apart by the body: The two rate-limit 429s carry a Retry-After header. The other two do not. Rate limits shows both rate-limit bodies in full. A 429 with any other body comes from the service behind the endpoint, and the endpoint’s guide describes it. A feature allowance refusal names the allowance in resource:
period is month, or year for takedowns. limit is your allowance for that window, packs included. Metered allowances lists every allowance. The Attack Surface refusal comes from the assessment service:
An assessment is heavy when it enables perform_port_scan, active_vuln_scan or dns_typosquatting_enabled, or sets domain_mode to dual_domain or all. A full assessment enables port scanning and typosquatting by default. A targeted assessment is heavy too when its report type is domain_spoofing_risk or application_security, or infrastructure_risk with port scanning left on, which is the default. The assessment unit is refunded. See Attack Surface assessments.

500, 502, 503 and 504

A few endpoints word their 502 differently, or pass the service’s own 5xx through. Credential comparison reports, for example, answer {"message": "Please try again later..."}, and Credential Check passes the lookup service’s error through. Their guides list them. Handle every 5xx the same way. Back off between retries: wait 2, 4, 8 and 16 seconds, add up to a second of random delay, and stop after 5 attempts. See the warning above before you retry a call that starts a job.

Statuses the reference does not list

Each operation in the API reference lists the statuses it documents. The rules on this page apply to every operation, including those whose entry leaves a status out:
  • 401 applies to every endpoint that needs a key. Several entries list none, including Quick search, Paste search and report schedules.
  • 403 for a license that is not in force applies to almost every endpoint. About half of the entries list no 403.
  • 409 for a full capacity slot applies to alert_system_alert_create_alert_rule, create_report_schedule and update_report_schedule. Their entries list no 409.
  • 429 for the per-second rate limit applies to every endpoint that needs a key. Several entries list none, including Quick search, Telegram search, Paste search, report schedules and the usage and organization endpoints.
  • 503 and 504 apply to every endpoint that calls a service behind it. Most entries list only 502.
  • 405 and 415 are never listed. 405 returns {"detail": "Method \"GET\" not allowed."}, naming the method you sent. 415 returns {"detail": "Unsupported media type \"text/plain\" in request."}, naming the Content-Type you sent. The API accepts JSON, form and multipart bodies.
One status in the reference never means what its label suggests:
  • 402 Payment Required appears on four Discord search entries. There are no credits. A plan refusal is a 403, and a spent allowance is a 429.
The reference gives every 429 a generic description. On a metered endpoint, it can be any of the four refusals in 429 Too Many Requests, so read the body before you retry.

Endpoints