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

# Errors

> Handle 0xArchive API and WebSocket errors with stable codes, HTTP statuses, retry guidance, versioned names, and request IDs.

Decide what to do after a failed call. The HTTP status gives the class of failure, `error_code` gives the reason, and `request_id` lets support find the exact request later.

## Response shape

Every error response is JSON with the same top-level fields, on every route, including authentication failures, rate limits, and unknown paths:

```json theme={"theme":"github-dark"}
{
  "success": false,
  "code": 400,
  "error_code": "invalid_interval",
  "error": "Invalid interval '7m'. Use one of: 1m, 5m, 15m, 30m, 1h, 4h, 1d, 1w.",
  "param": "interval",
  "valid_values": ["1m", "5m", "15m", "30m", "1h", "4h", "1d", "1w"],
  "request_id": "0216f592-981b-4457-824c-b3753bc044f9"
}
```

| Field | Meaning |
| - | - |
| `success` | Always present. Always `false` on an error |
| `code` | Always present. The HTTP status, repeated in the body |
| `error_code` | Always present. Stable lowercase reason. Branch on this, never on the message text |
| `error` | Always present. Human-readable message. Wording can change |
| `request_id` | Always present. Identifier for this request, at the top level of error bodies. Quote it to support |
| `param` | Present when one parameter caused the error. The parameter to fix |
| `valid_values` | Present when the accepted set is small. The values that parameter accepts |

Some routes add their own fields, such as `available_on` on `unsupported_for_venue`. Ignore fields you do not recognize. If a response has no `error_code`, fall back to the HTTP status.

## Error codes

| `error_code` | Status, meaning, and what to do |
| - | - |
| `invalid_parameter` | `400`. A parameter failed to parse or has a value the route does not accept. `param` names it. Fix the parameter; do not retry unchanged |
| `invalid_symbol` | `400`. The symbol does not exist on this venue. Look it up on the venue's instruments route or `/v1/symbols`, and check the venue namespace and symbol style |
| `invalid_interval` | `400`. The `interval` value is not accepted by this route. Use a value from `valid_values`, or from `intervals` in [capabilities](/capabilities) |
| `invalid_cursor` | `400`. The `cursor` is malformed or was not issued for this query. Pass `meta.next_cursor` back unchanged with the same filters, or restart from the first page |
| `invalid_time_range` | `400`. `start` is after `end`, or a time could not be parsed. Send Unix milliseconds or RFC 3339, with `start` at or before `end` |
| `range_before_coverage` | `400`. The whole range ends before the data type's first served time. Move the window to `available_from` in [capabilities](/capabilities) or later. A range that straddles it is served from that point |
| `historical_range_exceeded` | `403`. The span from `start` to `end` is longer than your plan allows in one request. Split the range into smaller windows |
| `historical_depth_exceeded` | `403`. The window reaches further back than your plan's history window. Move the window forward; see [Free tier](/core-concepts/free-tier) for the rolling history window |
| `unsupported_for_venue` | `404`. The venue does not offer this data type, or the channel does not offer this mode (live, replay, seek). Use a venue listed in `available_on` or named in the message; check [capabilities](/capabilities) |
| `route_not_found` | `404` or `405`. No route matches the path, or the method is not allowed. Check the path and method against the [Endpoint reference](/api-reference) or `/v1/capabilities` |
| `not_found` | `404`. A resource identifier in the path is unknown. Check the identifier, for example an outcome or question id |
| `unauthorized` | `401`. The API key is missing or invalid. Send a valid `X-API-Key`; see [REST authentication](/rest-api/authentication) |
| `forbidden` | `403` on REST, or an `error` message on WebSocket. The key or account is not allowed to make this request. Check the key status and the account in the dashboard. On the WebSocket, it also answers a `mempool` subscribe on a plan without the [mempool channel](/websocket/mempool), which comes with Pro, Scale and Enterprise |
| `insufficient_credits` | `429`. The account has no credits left for this period. Stop the job until credits reset or the plan changes; a retry cannot succeed. See [When you reach a limit](/rate-limits#when-you-reach-a-limit) |
| `rate_limited` | `429` on REST, or an `error` message on the WebSocket. The request rate, concurrency, or WebSocket subscription limit was reached. On REST, retry within a budget: after `retry_after` seconds for the request rate, or when an in-flight request finishes for concurrency. For the subscription limit, unsubscribe from something first; a retry of the same subscribe fails the same way. When the unfiltered `mempool` stream is at capacity, subscribe with a symbol or try again later. See [When you reach a limit](/rate-limits#when-you-reach-a-limit) |
| `conflict` | `409`. The request conflicts with the current state, for example a replay already running on the connection. Finish or stop the other operation first |
| `upstream_unavailable` | `503`. A data store or upstream source did not answer in time. Wait the seconds in the `Retry-After` header, then retry with backoff; check [Status monitoring](/status-monitoring) if it persists. On WebSocket, it also answers a `mempool` subscribe while that channel is temporarily unavailable; retry with capped backoff |
| `internal_error` | `500`. An unexpected server error. Retry within a bounded budget; report the `request_id` if it persists |
| `endpoint_unsupported` | WebSocket only. This WebSocket endpoint does not serve the channel or operation. For example, `stream.0xarchive.io` serves a subset of live Hyperliquid channels, and it is the only endpoint for `mempool`. Connect to the endpoint named in the message: `wss://stream.0xarchive.io/ws` for `mempool`, and usually `wss://api.0xarchive.io/ws` otherwise |
| `slow_consumer` | WebSocket only. The connection fell behind a stream, and messages were dropped or the subscription was stopped. Read faster or subscribe to less, then re-subscribe or restart the replay to resync. On `mempool`, the connection is closed, and transactions sent while you were behind cannot be fetched later |

A few routes use their own codes for conditions that only they have, such as `positions_unavailable` on account position routes. Treat a code you do not recognize as a generic error of its HTTP status.

## Versioned and earlier names

Four codes predate this list. They are still sent to clients that do not send the version header, so existing integrations keep working. With `0xArchive-Version: 2026-10-01` (see [Versioning](/conventions#versioning)), you get the current names:

| Without the version header | With `0xArchive-Version: 2026-10-01` |
| - | - |
| `invalid_query_params` | `invalid_parameter`, or `invalid_time_range` for a time that cannot be parsed |
| `invalid_path_params` | `invalid_parameter` |
| `history_window_exceeded` | `historical_depth_exceeded` |
| `request_range_exceeded` | `historical_range_exceeded` |

Handle both spellings if your client runs without the header. With the version header, an inverted or malformed window returns `invalid_time_range` and a malformed `cursor` returns `invalid_cursor`. Without it, some routes return an empty page for an inverted window, and trades routes read a malformed cursor as no cursor. Never edit or construct a cursor.

## Parameter validation errors

A parameter that fails to parse, or carries a value the route does not accept, returns `400` with `param` naming it. Where the accepted set is small, `valid_values` lists it.

```json theme={"theme":"github-dark"}
{
  "success": false,
  "code": 400,
  "error_code": "invalid_parameter",
  "error": "Invalid side 'long'. Use buy or sell.",
  "param": "side",
  "valid_values": ["buy", "sell"],
  "request_id": "ec63b7a2-438d-4cf0-8ebf-a94d61697ff8"
}
```

A value that does not parse at all, such as `?limit=abc`, returns the same shape with the parse error in `error`:

```json theme={"theme":"github-dark"}
{
  "success": false,
  "code": 400,
  "error_code": "invalid_parameter",
  "error": "Failed to deserialize query string: limit: invalid digit found in string",
  "param": "limit",
  "request_id": "01e650d0-bd8d-425d-8653-53ff66cdbeaa"
}
```

Without the version header, the same request returns `error_code` `invalid_query_params`. Handle all of these the same way: fail fast, log `request_id` plus `error_code` and `param`, correct the parameter, and do not retry the request unchanged.

## Unsupported venue and unknown route

A request for a data type that the venue does not offer returns `404` with `unsupported_for_venue`. The body names the data type and the routes where it is available:

```json theme={"theme":"github-dark"}
{
  "success": false,
  "code": 404,
  "error_code": "unsupported_for_venue",
  "error": "Order flow is not offered on Hyperliquid spot. It is available on Hyperliquid (/v1/hyperliquid/orders/{symbol}/flow), HIP-3 (/v1/hyperliquid/hip3/orders/{symbol}/flow) and HIP-4 (/v1/hyperliquid/hip4/orders/{symbol}/flow).",
  "venue": "spot",
  "datatype": "order_flow",
  "available_on": [
    { "venue": "hyperliquid", "route": "/v1/hyperliquid/orders/{symbol}/flow" },
    { "venue": "hip3", "route": "/v1/hyperliquid/hip3/orders/{symbol}/flow" },
    { "venue": "hip4", "route": "/v1/hyperliquid/hip4/orders/{symbol}/flow" }
  ],
  "request_id": "82f3b1e4-ed54-42ea-b005-85e8e01d0ecc"
}
```

Any other unknown path returns `404` with `route_not_found`, and a known path called with the wrong method returns `405` with the same code:

```json theme={"theme":"github-dark"}
{
  "success": false,
  "code": 404,
  "error_code": "route_not_found",
  "error": "No route matches GET /v1/hyperliquid/nosuchthing. GET /v1/capabilities lists the routes each venue serves.",
  "request_id": "6d6cb51c-3d6c-4889-b349-dc54ae1d976d"
}
```

Neither is worth retrying unchanged. Correct the venue namespace or path first; many apparent 404s are market-family mistakes, covered in [Venue coverage](/venue-coverage).

## WebSocket errors

WebSocket errors arrive as messages on the open connection, with the same `error_code` values:

```json theme={"theme":"github-dark"}
{"type": "error", "message": "Channel ticker does not support historical replay", "error_code": "unsupported_for_venue"}
```

The connection stays open after an error message unless the message says it was closed. `slow_consumer` and `endpoint_unsupported` occur only on WebSocket. A connection that is refused before it opens, for example because the key is invalid or the connection limit is reached, is an HTTP response to the upgrade request, not an `error` message. See [WebSocket connection](/websocket/connection).

## Status handling

| Status | Meaning and client action |
| - | - |
| `400` | Invalid parameter, symbol, interval, cursor, or time range, or a range before coverage. Fix the request before retrying; `error_code` and `param` say what to change |
| `401` | Missing or invalid API key. Check `X-API-Key` and key status with [REST authentication](/rest-api/authentication) |
| `403` | The plan's request window or span was exceeded, or the key or account was refused. Use `error_code` to tell `historical_range_exceeded` and `historical_depth_exceeded` apart from `forbidden`. Plans govern capacity and request windows, not route access, so a `403` does not mean a route needs a higher plan |
| `404` | Unknown route, unsupported venue and data type, or unknown resource. Check the venue namespace, path, and identifier; `unsupported_for_venue` names where the data type is available |
| `409` | Conflicting operation. Finish or stop the other operation |
| `429` | Rate, concurrency, or credit limit reached. Retry `rate_limited` within a budget; stop on `insufficient_credits`. See [When you reach a limit](/rate-limits#when-you-reach-a-limit) |
| `5xx` | Server or upstream issue. Retry with jitter, then check [Status monitoring](/status-monitoring) and [Data quality](/data-quality) |

## Retry policy

<Tabs>
  <Tab title="Retry">
    Retry a REST `rate_limited`, transient `5xx`, and network timeouts within a bounded budget, waiting the `retry_after` seconds or the `Retry-After` header when the response gives one, and capped exponential backoff with jitter when it does not. Do not retry `insufficient_credits`, and do not resend a WebSocket subscribe refused with `rate_limited`: unsubscribe from something first. [When you reach a limit](/rate-limits#when-you-reach-a-limit) has the rule for each limit.
  </Tab>

  <Tab title="Do not retry unchanged">
    Do not retry malformed requests, invalid symbols, missing auth, refused requests, or unsupported parameters without changing the request or key.
  </Tab>
</Tabs>

## Next-call routing

Do not treat every failed request as a reason to rerun the same call faster. Route the next call by error class.

| Error class | Next call |
| - | - |
| Missing or invalid auth | Stop the job, fix `X-API-Key`, then retry one small authenticated market-data route |
| Wrong venue or symbol family (`invalid_symbol`, `unsupported_for_venue`) | Confirm which market the user meant. If the symbol belongs to another namespace, such as an `xyz:` HIP-3 symbol sent to a core route, fix the path. If the data type does not exist for that market, stop and report that; never answer with another venue's data. [Venue coverage](/venue-coverage) and [capabilities](/capabilities) list what exists where |
| `rate_limited` on high-volume raw events | Wait the `retry_after` seconds, or for an in-flight request to finish, reduce concurrency, and retry a smaller window |
| Repeated liquidation raw-event pressure | Use `/v1/hyperliquid/liquidations/{symbol}/volume` or the matching HIP-3 `/volume` route when the workflow only needs [liquidation aggregates](/rest-api/liquidations) |
| Malformed parameter or invalid time range | Fix the request shape before retrying; unchanged retries should stay blocked |
| `range_before_coverage` or an empty page with `meta.coverage_from` | Move the window to the first served time before retrying |

## Log enough to act on

Treat request IDs as part of your application log schema. Store `meta.request_id` for each successful REST pull, including the coverage and freshness calls that set up a replay, and the top-level `request_id` from the error body for each failed attempt. When a route returns a resource-specific body, such as some data-quality routes, store the route path, parameters, returned status fields, and the `x-request-id` response header or the client wrapper's request handle. When a job spans pagination windows, keep the request ID per page instead of only the final one.

For each failure, log the method, full path, query parameters, venue family, symbol, HTTP status, `error_code`, `param` when present, attempt count, backoff delay, and whether the output was skipped, delayed, marked incomplete, or safely continued. A generated client or coding agent should expose the request ID on the returned object or exception; a retry wrapper that hides the original response body makes production failures hard to diagnose. If the final retry succeeds, keep both the successful request ID and the failed attempt IDs.

When a failure needs support, send that context plus the affected workflow, and never the API key. For a data-quality issue, add the observed timestamp, the freshness tolerance you expected, and whether the route feeds a backtest, alert, dashboard, export, or model input.

## Next step

Size retries and concurrency to your plan with [Rate limits](/rate-limits).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.