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

# Handle API errors

> Separate invalid requests, missing access, conflicts, and temporary failures so your integration takes the right next step.

A failed API call should lead to a specific decision. Fix the request when its fields are invalid, fix access when the credential cannot perform the operation, and retry only when the failure is temporary.

Check both the HTTP status and the JSON envelope. Successful responses use `ok: true` and place their payload in `data`. Errors use this shape:

```json theme={null}
{
	"ok": false,
	"error": {
		"code": "CONFLICT",
		"message": "offer is used by rotators",
		"details": {
			"blocked": ["OFFER_ID"]
		}
	},
	"requestId": "REQUEST_ID_IF_AVAILABLE"
}
```

The example represents a blocked bulk archive. `details` and `requestId` are optional. Use `error.code` for machine handling and `error.message` to explain the failure. Preserve any details that identify affected entities.

## Choose the next action by failure type

| Status         | Typical cause                                                             | Next action                                                     |
| -------------- | ------------------------------------------------------------------------- | --------------------------------------------------------------- |
| `400`          | Invalid JSON, missing dates, unsupported fields, or invalid filter syntax | Correct the request using the endpoint contract                 |
| `401`          | Missing, invalid, expired, or revoked token                               | Verify the key with [whoami](/api-reference/endpoints/who-am-i) |
| `402`          | Public API subscription access is unavailable                             | Check **Subscription**                                          |
| `403`          | Read scope used for a write, or a forbidden request origin                | Use the appropriate server-side request and scope               |
| `404`          | Missing entity, wrong workspace, or route outside the public surface      | Check the ID, workspace, method, and path                       |
| `409`          | An entity is still referenced or cannot be published                      | Resolve the reported dependency before retrying                 |
| `413`          | Request body exceeds the endpoint limit                                   | Reduce the payload                                              |
| `429`          | Request rate or query budget is exceeded                                  | Back off or narrow the query, depending on the error code       |
| `500` or `503` | A server dependency or service is unavailable                             | Retry a read with backoff and keep diagnostic context           |

For example, retrying an offer archive will not solve `offer is used by rotators`. Remove or replace the offer in the relevant rotator pools first, then repeat the archive. See [Archive and restore](/api-reference/archive-and-restore).

## Retry temporary failures deliberately

For `RATE_LIMITED`, honor `Retry-After` when supplied and reduce request concurrency. If no retry delay is provided, use a bounded backoff rather than a tight loop.

An event query can return `SCROLL_BUDGET_EXCEEDED` when it cannot advance within its scan budget. Shorten the date range or narrow the campaign and event type. Repeating the same broad query faster does not reduce the work it requires.

A `BAD_CURSOR` needs a new event query without the old cursor. Keep the original dates and filters for a continued scroll. Changing the query while reusing its cursor invalidates that continuation.

For a timeout or temporary failure during a write, first check whether the intended change already exists. A lost response does not prove that the server rejected the operation. Avoid blindly resending a create request and producing a duplicate entity.

## Capture enough context to investigate

Log the HTTP method, public endpoint path, status, error code, request ID when present, and the relevant non-secret entity IDs. For report issues, include the date range and timezone.

Keep Authorization headers and credentials out of logs. Raw event responses can contain request-level visitor data, so store only the fields needed for the investigation.

If `whoami` succeeds and a small report query succeeds, expand the request one choice at a time. Add the desired dimensions, then filters, then a larger date range. The first change that fails gives you a concrete request to correct or report.
