# Errors

The API returns conventional HTTP status codes and a JSON body for every
non-2xx response.

## Response shape


```json
{
  "statusCode": 404,
  "message": "Customer not found",
  "code": "NOT_FOUND",
  "timestamp": "2026-05-07T08:30:00.000Z",
  "path": "/customers/999"
}
```

Selected error responses include extra fields tailored for AI agents and
tooling that act on errors without prior context:

| Field | When it appears |
|  --- | --- |
| `code` | Always. Stable machine-readable classifier (e.g. `INVALID_CURSOR`, `PLAN_UPGRADE_REQUIRED`, `INVALID_EXPAND`). |
| `hint` | When the fix is non-obvious from the message alone — e.g. `INVALID_CURSOR` includes `"Restart pagination by omitting the 'after' parameter."`. |
| `did_you_mean` | On `INVALID_EXPAND` when the bad value is close to a supported one (edit distance ≤ 2 or shared prefix ≥ 4 chars). |


## Status codes you'll encounter

| Code | When | What to do |
|  --- | --- | --- |
| `400` | Malformed request — bad parameter type, malformed booking ID, unknown `expand` value. | Fix the request; don't retry as-is. Common codes: `INVALID_BOOKING_ID`, `INVALID_CURSOR_FORMAT`, `INVALID_EXPAND` (with `did_you_mean` when applicable). |
| `401` | Missing or invalid `X-API-KEY`. | Check the [authentication guide](/guides/authentication). |
| `403` | API key is valid but the client's plan doesn't include API access. | Upgrade the plan. Body includes `code: "PLAN_UPGRADE_REQUIRED"`. |
| `404` | The resource doesn't exist. | Don't retry; the ID is wrong. |
| `422` | Invalid pagination cursor — the `after` ID points to a resource that doesn't exist. | Restart pagination by omitting the `after` parameter. The response body's `code` is `INVALID_CURSOR` and `hint` repeats this guidance for agent tooling. |
| `429` | Rate limit exceeded. | Back off for the duration in the `Retry-After` header. See [rate limiting](/guides/rate-limiting). |
| `5xx` | Transient server error. | Retry with exponential backoff. |