> ## Documentation Index
> Fetch the complete documentation index at: https://docs.anycrm.anyreach.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Errors & Pagination

> The error body shape, HTTP status conventions, and how list endpoints paginate

## Error shape

This is a FastAPI service, so most errors come back as a plain JSON object:

```json theme={null}
{
  "detail": "Missing a CRM read scope"
}
```

`detail` is usually a human-readable string. The one exception is `422 Unprocessable Entity` — a request-body/query validation failure raised by FastAPI itself before your handler ever runs — where `detail` is an array of per-field problems instead:

```json theme={null}
{
  "detail": [
    {
      "type": "missing",
      "loc": ["body", "name"],
      "msg": "Field required",
      "input": {}
    }
  ]
}
```

### Status codes you'll see across this API

| Status                     | Meaning                                                                                                                                                                                                                                              |
| -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `400 Bad Request`          | Malformed input the handler validated itself (invalid enum value, no active organization on the token, unknown filter)                                                                                                                               |
| `401 Unauthorized`         | Missing/expired/invalid bearer token — see [Authentication](/authentication)                                                                                                                                                                         |
| `403 Forbidden`            | Valid token, insufficient [scope](/authentication#scopes)                                                                                                                                                                                            |
| `404 Not Found`            | The resource doesn't exist, or exists in a different organization than the token's (row-level security makes the two indistinguishable by design — a cross-org read looks exactly like a missing row, never a 403 that would confirm the row exists) |
| `409 Conflict`             | A uniqueness/state constraint (duplicate tag name, non-empty folder without `cascade=true`)                                                                                                                                                          |
| `422 Unprocessable Entity` | Request body/query failed Pydantic validation                                                                                                                                                                                                        |
| `502 Bad Gateway`          | The backend's own call to the database (PostgREST) or another upstream failed                                                                                                                                                                        |
| `503 Service Unavailable`  | A dependent feature isn't available in this deployment (e.g. report rendering, which needs the render-worker image)                                                                                                                                  |

## Pagination

List endpoints take `limit` and `offset` query parameters. There's **no single envelope shared across every resource** — it varies by endpoint, so check the specific page:

* **Header-based**: some list endpoints (e.g. `GET /contacts`) return a bare JSON array and put the total match count (ignoring `limit`/`offset`) in the `X-Total-Count` response header, so you can compute total pages without a second request.
* **Body-based**: others (e.g. `GET /files/list`) wrap the array in an object alongside the pagination params you sent: `{"files": [...], "limit": 50, "offset": 0}`.
* **Bare array, no total**: others (e.g. `GET /deals`) just return the page as a JSON array with no total-count signal at all — keep incrementing `offset` until you get back fewer rows than `limit`.

Each endpoint in the Core CRM API reference states which shape it uses. `limit` defaults and caps also vary per endpoint (commonly defaulting to 50–200 and capped at 200–500 server-side regardless of what you pass) — again, see the specific endpoint.
