Errors
HTTP status codes and error codes returned by the Cognism API, what each one means, and which ones are safe to retry.
The Cognism API uses standard HTTP status codes. Successful requests return 200. Failed requests return a 4xx or 5xx status with a JSON body that describes what went wrong. Documented error conditions carry a machine-readable error code alongside a human-readable message; some add fields specific to the condition, such as retryAfter.
Error envelope
{
"error": "rate_limit_exceeded",
"message": "Rate limit exceeded for operation 'search'. Retry after 34 seconds.",
"operation": "search",
"window": "sustained",
"retryAfter": 34
}| Field | Present | Description |
|---|---|---|
error | On documented error conditions | Stable, snake_case code. Branch on this, not on message. |
message | Always | Human-readable explanation. Wording may change; do not parse it. |
retryAfter | 402, 429 | Seconds to wait before retrying. Also sent as the Retry-After header on 429. |
reason | 402 | Why the budget check failed: exhausted, stale_reset or store_unavailable. |
operation, window | 429 | Which rate-limit operation and window was exceeded. |
Error codes
| HTTP | error | Meaning | Recommended action |
|---|---|---|---|
| 400 | (validation detail) | The request failed validation: malformed filter, unknown field, out-of-range limit or offset, cursor and offset sent together. | Fix the request. Validation failures carry field-level detail instead of an error code — request-body failures list the offending paths, query-parameter failures list the constraint messages. |
| 400 | invalid_cursor | The cursor is malformed or from an unsupported version. | Restart pagination from the first page. See Pagination. |
| 400 | cursor_filter_mismatch | The request body changed since the cursor was issued. | Send the original body with the cursor, or start a new journey. |
| 401 | — | Missing, malformed or expired bearer token. | Request a new token and retry once. See Authentication. |
| 402 | insufficient_budget | Search tokens exhausted (reason: exhausted), or the budget could not be verified (stale_reset, store_unavailable). | For exhausted, wait retryAfter seconds or contact your account team — do not retry in a loop. For the other reasons, retry with exponential backoff. See Credits and search tokens. |
| 422 | pagination_depth_exceeded | A cursor journey has passed 100,000 records. | Narrow the filter and start again. |
| 429 | rate_limit_exceeded | The per-account, per-operation request limit was exceeded. | Wait Retry-After seconds, add jitter, retry. See Rate limits. |
| 5xx | — | Unexpected server error or upstream timeout. | Retry with exponential backoff. If the problem persists, check GET /health and contact support with the request timestamp. |
Retry or not
| Status | Retry? | Guidance |
|---|---|---|
| 429 | Yes | Wait Retry-After seconds (never more than 60), add jitter. |
402 stale_reset / store_unavailable | Yes | Exponential backoff starting at a few seconds. |
402 exhausted | Only after retryAfter | The wait can be days. Surface it to a human. |
| 5xx | Yes | Exponential backoff, capped at a small number of attempts. |
| 401 | Once | Refresh the token first. |
| 400, 422 | No | Change the request. Re-sending the same request produces the same error. |
Best practices
- Branch on
error, logmessage. Codes are stable; messages are for humans. - Cache the access token and refresh it before it expires to avoid
401s in the first place. - Validate filter values against the dictionaries before sending them, so
400s surface in development rather than production. - Never retry a
400unchanged, and never retry a402 exhaustedin a tight loop. - Record
X-Rate-Results-*andRateLimit-*headers from successful responses so you can see quota trends before they become errors.
Recovery guidance for AI agents
| Situation | Recovery |
|---|---|
400 on a filter value | Resolve the value with the matching dictionary endpoint and retry with the exact returned value. |
400 cursor_filter_mismatch | Explain that the filter changed and restart pagination from page one. |
401 | Refresh the token silently and retry once; if it fails again, stop and report. |
402 exhausted | Stop. Tell the user the search-token allowance is used up and when it resets. |
422 pagination_depth_exceeded | Narrow the filter (add a location or headcount range) and restart. |
429 | Back off for Retry-After seconds and retry; do not tell the user unless it persists. |
Updated 2 days ago
Did this page help you?

