> For the complete documentation index, see [llms.txt](https://www.boxhero.io/docs/llms.txt). Every page is available as Markdown by appending `.md` to its URL; this page is [Markdown](https://www.boxhero.io/docs/developers/api/errors.md).

# Errors

> Understand the error envelope the BoxHero API returns and how to handle errors in your code.

When a request fails, the BoxHero API responds with an HTTP error status and a single JSON error envelope:

```json
{
  "id": "ex_8f5c0c8e0e0a4a3c9b3f4f2c4f6c8d2a",
  "type": "/errors/not-found",
  "title": "No item with id 12345 found in this team.",
  "correlationID": "rq_01abf3c2b8e44a59be2a9c0f1e7d6a40",
  "instance": "/items/12345"
}
```

## Fields

| Field | Description |
| --- | --- |
| `id` | Unique ID of the error: `ex_` followed by 32 lowercase hex characters. Include it when you contact support. |
| `type` | Stable, machine-readable error code. Branch on this in your code, not on `title`. |
| `title` | Human-readable summary, in English. The wording can change. |
| `correlationID` | ID of the request: `rq_` followed by 32 lowercase hex characters, identical to the `X-Correlation-Id` response header. We use it to find your request in our logs. |
| `instance` | The resource that failed, for example `/items/12345`. The path has no `/v1` prefix. |
| `code` | Sub-reason for the error, for example `tx-modify-revision-mismatch`. Not always present. Branch on `type` first, then on `code` for finer handling. |
| `errors` | Field-level details, present on `/errors/invalid-request` (`400`) responses. Each entry has a `path` that locates the invalid field and a human-readable `message`. |

Some errors also include the id of the resource involved, such as `item_id` or `order_id`, as extra top-level fields.

> **Note**
>
> You can send your own `X-Correlation-Id` request header to connect your traces with ours. The same value comes back in the response and in `correlationID`.

## Common status codes

| Status | Meaning | What to do |
| --- | --- | --- |
| `400` | The request is invalid, or the team's mode does not support this endpoint | Fix the request — `errors` lists the invalid fields. Don't retry it unchanged. |
| `401` | The API token is missing or invalid | Check the `Authorization` header. See [Authentication](https://www.boxhero.io/docs/developers/api/authentication). |
| `403` | BoxHero refused the change — for example, it breaks an inventory rule or the `revision` you sent is out of date | Check `code` to see why. Fix the request, or fetch the latest data, before you retry. |
| `404` | The resource does not exist in this team, or was deleted | Check the id. Don't retry it unchanged. |
| `429` | Too many requests | Wait and retry. See [Rate limiting](https://www.boxhero.io/docs/developers/api/rate-limiting). |

The error types each endpoint can return are listed with it in the [API reference](https://www.boxhero.io/docs/developers/api/reference).

## Handling a revision conflict

To [update](https://www.boxhero.io/docs/developers/api/reference/transactions/update-transaction) or [delete](https://www.boxhero.io/docs/developers/api/reference/transactions/delete-transaction) a transaction, send the latest `revision` you have seen. If someone else changed the transaction in the meantime, the API rejects the request with a `403` and `code` set to `tx-modify-revision-mismatch`. Branch on `code`: fetch the transaction again, check the change, and retry with the new `revision`.

```js
const res = await fetch(`https://rest.boxhero-app.com/v1/transactions/${id}`, {
  method: "PUT",
  headers: {
    Authorization: `Bearer ${process.env.BOXHERO_API_TOKEN}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ revision, memo: "Recounted" }),
});

if (res.status === 403) {
  const error = await res.json();
  if (error.code === "tx-modify-revision-mismatch") {
    // Fetch the transaction again, check the change, then retry with its new revision.
  }
}
```
