---
updatedAt: 2026-09-08T13:38:47.000Z
agentTools:
  projectIndex: https://docs.cognism.com/llms.txt
---

# 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

```json
{
  "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](/docs/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](/docs/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](/docs/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](/docs/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`, log `message`.** Codes are stable; messages are for humans.
* **Cache the access token** and refresh it before it expires to avoid `401`s in the first place.
* **Validate filter values against the dictionaries** before sending them, so `400`s surface in development rather than production.
* **Never retry a `400` unchanged**, and never retry a `402 exhausted` in a tight loop.
* **Record `X-Rate-Results-*` and `RateLimit-*` 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.           |