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

# Error codes

> Chronicle API error response shape and common HTTP status codes.

## Error format

Chronicle API errors return a consistent shape.

| Field           | Type   | Description                                        |
| --------------- | ------ | -------------------------------------------------- |
| `error`         | object | Error payload.                                     |
| `error.code`    | string | Machine-readable error code.                       |
| `error.message` | string | Human-readable error message.                      |
| `error.status`  | number | HTTP status, mirrored in the body for convenience. |

```json theme={null}
{
  "error": {
    "code": "BAD_REQUEST",
    "message": "template_id is required",
    "status": 400
  }
}
```

***

## Common status codes

<AccordionGroup>
  <Accordion title="400 Bad Request">
    The request is malformed or missing required fields. `error.code` is one of `BAD_REQUEST` or `WORKSPACE_ID_REQUIRED` (MCP/JWT path with no `workspace_id` in body or query).

    Common causes:

    * Missing required fields
    * Invalid JSON
    * Invalid parameter values
    * Missing `workspace_id` on JWT-authenticated MCP requests
  </Accordion>

  <Accordion title="401 Unauthorized">
    Authentication failed. `error.code` is one of `API_KEY_INVALID`, `API_KEY_EXPIRED`, `API_KEY_REVOKED`, `UNAUTHORIZED` (missing/malformed header), `JWT_INVALID`, `JWT_EXPIRED`, `JWT_WRONG_AUDIENCE`, or `JWT_SIGNATURE_INVALID`. The `JWT_*` codes apply on the MCP/JWT auth path.

    Common causes:

    * Missing API key
    * Invalid API key
    * Expired API key
    * Revoked API key
    * Malformed auth header
    * Expired or invalid MCP JWT — reconnect via the OAuth flow to refresh
  </Accordion>

  <Accordion title="402 Payment Required">
    Workspace usage limits hit. `error.code` is one of `PRICING_REMIX_OVER_LIMIT` or `PRICING_DOCUMENT_LIMIT_REACHED`.

    Surface a clear billing/upgrade message to the user — retrying will not help until the limit is lifted.
  </Accordion>

  {" "}

  <Accordion title="403 Forbidden">
    The API key or JWT is valid, but the resource is outside the caller's reach. `error.code` is one of `INSUFFICIENT_PRIVILEGES` (chr\_\* key targeting a different workspace), `WORKSPACE_ACCESS_DENIED` (JWT user lacks workspace membership), or `MCP_NOT_ENABLED` (user not in the MCP feature allowlist; only `list_workspaces` is usable in this state).
  </Accordion>

  <Accordion title="404 Not Found">
    The requested resource does not exist or is not accessible to the workspace. `error.code` is one of `DOCUMENT_NOT_FOUND`, `TEMPLATE_NOT_FOUND`, `WORKSPACE_NOT_FOUND`, or `NOT_FOUND` (unknown generation job).

    Common causes:

    * Unknown template ID
    * Unknown presentation ID
    * Unknown generation job ID
  </Accordion>

  {" "}

  <Accordion title="429 Too Many Requests">
    The request exceeded the per-API-key rate limit. `error.code` is
    `API_KEY_RATE_LIMITED`. Back off and retry.
  </Accordion>

  <Accordion title="500, 502, 503, 504">
    A temporary server-side or upstream failure occurred. `error.code` is `INTERNAL_ERROR` or `UNKNOWN_INTERNAL_ERROR`.
  </Accordion>
</AccordionGroup>

***

## Retry guidance

<Columns cols={2}>
  <Column>
    Retry these cases:

    * `429 Too Many Requests`
    * `500 Internal Server Error`
    * `502 Bad Gateway`
    * `503 Service Unavailable`
    * `504 Gateway Timeout`
  </Column>

  <Column>
    Do not blindly retry these cases:

    * `400 Bad Request`
    * `401 Unauthorized`
    * `402 Payment Required`
    * `403 Forbidden`
    * `404 Not Found`

    Surface these to the user — retrying without changing the request will not help.
  </Column>
</Columns>

***

## Exponential backoff

Use exponential backoff with jitter when retrying.

Pseudo-logic:

```text theme={null}
attempt 1: wait 1s
attempt 2: wait 2s
attempt 3: wait 4s
attempt 4: wait 8s
```

***

## Related posts

* [API scope and rate limits](/api-scope-rate-limits)
* [Authentication](/authentication)
* [Troubleshooting](/troubleshooting)
