> ## 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.

# API conventions

> Shared REST response conventions, WebSocket versioning, error codes, time formats, pagination, parameter names, coverage signals, and capabilities.

Use the REST envelope and pagination rules below for market-data reads. WebSocket messages use their [channel schemas](/websocket/schema), with the versioning and error codes described on this page.

Changes to this contract are additive. Existing fields, types, and status codes keep working for existing clients. The few changes that cannot be additive are opt-in through a dated version, described under [Versioning](#versioning).

## Response envelope

The shared REST response envelope has three keys:

```json theme={"theme":"github-dark"}
{
  "success": true,
  "data": [
    {
      "symbol": "BTC",
      "side": "B",
      "price": "82782",
      "size": "0.00025",
      "timestamp": "2026-09-28T14:55:17.295Z"
    }
  ],
  "meta": {
    "count": 1,
    "has_more": true,
    "next_cursor": "1790607317295_494699715524397",
    "symbol": "BTC",
    "venue": "hyperliquid",
    "request_id": "ea17ef99-bca1-4d06-9461-0e920e66a2c8"
  }
}
```

`data` is the payload: an array for lists and history, an object for a single snapshot. `meta` describes the response. Records are not required to repeat the symbol or venue, so read both from `meta`.

| `meta` field | When present | Meaning |
| - | - | - |
| `request_id` | Every enveloped response | Identifier for this request. Log it with every page and quote it to support |
| `count` | List payloads | Number of records in this response, not the total available |
| `has_more` | Cursor-paged routes | `true` when another page exists. See [Pagination](#pagination) |
| `next_cursor` | Exactly when `has_more` is `true` | Opaque string to send back as `cursor` |
| `symbol` | Per-symbol routes | The canonical public symbol for the venue, for example `BTC`, `km:US500`, `#0`, or `HYPE-USDC` |
| `venue` | Per-symbol routes | One of `hyperliquid`, `hip3`, `hip4`, `spot`, `lighter`, `rh-lighter` |
| `coverage_from`, `notice` | Empty responses whose window ends before the symbol's coverage | Where coverage starts and why the page is empty. See [Coverage signals](#coverage-signals) |
| `finalized_through` | Lighter and Lighter on Robinhood Chain trades | The latest finalized trade time. History is canonical up to this point |
| `requested_end`, `clamped_to` | Lighter trade history when `end` is later than `finalized_through` | The `end` you sent and the finalized time the range was clamped to |
| `preliminary_row_count` | Lighter `/recent` trades | Rows in the response that are preliminary and not yet finalized |

A few catalog and status routes (data quality, `/v1/status/coverage`, and `/v1/symbols`) return their own body shape by default, with `success: true` and `meta.request_id` added. With the version header they return the standard envelope, where `data` holds the body (the symbol array for `/v1/symbols`).

Health checks use a direct response body. `GET /health` returns `{"service":"0xarchive-api","status":"ok"}`, including when the version header is sent. Its request identifier is in the `X-Request-Id` response header. See the [health check schema](/schemas/operations/health-check).

## Errors

Every error response is JSON with the same shape, including authentication failures and unknown routes:

```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"
}
```

`code` is the HTTP status. `error_code` is a stable, machine-readable name: branch on it, not on the message text. `param` and `valid_values` appear when one parameter caused the error. The full list of codes, their statuses, and what to do about each is on [Errors](/errors). WebSocket `error` messages carry the same `error_code`.

## Versioning

Send `0xArchive-Version: 2026-10-01` on REST requests, and `version=2026-10-01` in the WebSocket connection URL, to receive the current contract. Without it, responses keep their earlier shape, so existing integrations keep working unchanged. The official SDKs, CLI, and hosted MCP send it for you.

```bash theme={"theme":"github-dark"}
curl "https://api.0xarchive.io/v1/hyperliquid/trades/BTC?limit=10" \
  -H "X-API-Key: $OXARCHIVE_API_KEY" \
  -H "0xArchive-Version: 2026-10-01"
```

```text theme={"theme":"github-dark"}
wss://api.0xarchive.io/ws?version=2026-10-01
```

Authenticate the WebSocket as usual, with `Authorization: Bearer $OXARCHIVE_API_KEY` in the opening handshake; see [WebSocket connection](/websocket/connection).

A response shaped by the version echoes it in the `0xArchive-Version` response header, and WebSocket `subscribed` and `replay_started` messages include `"version": "2026-10-01"`. A later dated value is read as the newest version the API supports. A value that is not a supported date is ignored and the default shape is returned. Responses carry `Vary: 0xArchive-Version`, so caches keep the two shapes apart.

What the version changes:

| Area | Without the version | With `2026-10-01` |
| - | - | - |
| Error codes | Four earlier names: `invalid_query_params`, `invalid_path_params`, `history_window_exceeded`, `request_range_exceeded` | `invalid_parameter`, `invalid_parameter`, `historical_depth_exceeded`, `historical_range_exceeded` |
| A `start`, `end`, or `timestamp` that cannot be parsed | `invalid_query_params` | `invalid_time_range` |
| Time fields on a few payloads | Integer milliseconds in `timestamp` or `snapshot_ts` | RFC 3339 string, plus an integer `timestamp_ms` or `snapshot_ts_ms`. Applies to L4 snapshot resting orders (an unknown queue time becomes `null`), cumulative volume delta buckets, HIP-3 oracle prices and discovery bounds, Lighter and Lighter on Robinhood Chain liquidations and liquidation volume, and liquidation-level and trigger-level snapshots |
| Data quality, `/v1/status/coverage`, `/v1/symbols` | Route-specific body plus `success` and `meta.request_id` | Standard `{ success, data, meta }` envelope |
| Lighter and Lighter on Robinhood Chain WebSocket replay | Stored row shapes | The same message shapes as the live channels |

We recommend sending the version on every request in new code. Pin the exact date rather than computing it, so a future version never changes your parser without a code change.

## Time

Requests accept either form for `start`, `end`, `timestamp`, and `at`:

* Unix milliseconds, for example `1790553600000`.
* RFC 3339, for example `2026-09-28T00:00:00Z` or `2026-09-28T02:00:00+02:00`. URL-encode `+` as `%2B`; a literal `+` is also accepted.

REST response times are RFC 3339 UTC strings, with milliseconds where the source has them, for example `2026-09-28T14:55:17.295Z`. Integer milliseconds appear only in fields whose names end in `_ms`. The few payloads that still carry integer times without the version header are listed in the [Versioning](#versioning) table. Store times in UTC and convert only for display.

Point-in-time reads take `timestamp`. The levels routes also accept `at` as a synonym.

## Pagination

Every cursor-paged route sets `meta.has_more`. `meta.next_cursor` is present exactly when `has_more` is `true`.

1. Send the first request with `start`, `end`, `limit`, and any filters.
2. While `meta.has_more` is `true`, send the same request again with `cursor` set to `meta.next_cursor`. Keep every other parameter unchanged.
3. Stop when `meta.has_more` is `false`.

The cursor is an opaque string. Do not parse, build, or modify it. A page can hold fewer rows than `limit` and still have more to come, and the last page can be empty when the previous page was exactly full. Stop on `has_more`, never on a short page. The maximum `limit` for each route family is published as `page_limit` in [capabilities](/capabilities). Details and examples are on [Pagination](/rest-api/pagination).

## Parameter names

| Name | Meaning |
| - | - |
| `symbol` | The market, in paths, query parameters, and `meta`. Each venue has its own symbol style: `BTC`, `HYPE-USDC`, `km:US500`, `#0`. Some routes also accept the older `coin` |
| `interval` | Bucket width on aggregated series such as candles, funding, open interest, cumulative volume delta, and order flow. Order flow also accepts `granularity` as an alias. On Lighter order book history, `granularity` is a different setting: the history resolution |
| `start`, `end` | The time window. See [Time](#time) |
| `limit`, `cursor` | Page size and continuation. See [Pagination](#pagination) |
| `side` | On every trades route, including `/recent`: `buy` or `sell`, filtered before paging, so a full page holds `limit` matching trades. Response rows keep the venue code, `B` or `A` |
| `triggered` | On Hyperliquid, HIP-3, and HIP-4 order history: `true` or `false` |
| `depth` | Price levels per side on order book snapshots and history, including full-depth L2 history. The accepted maximum depends on the route |

Every documented parameter changes the result. A value outside the accepted set is rejected with `400` and names the parameter, rather than being silently ignored.

## Coverage signals

Each data type has a first served row on each venue, published as `available_from` in [capabilities](/capabilities). Per-symbol dates are in `/v1/symbols`.

* A range that starts before the first row and ends after it is served from the first row. You do not need to trim `start`.
* A range that ends before a symbol's coverage begins returns an empty `data` array with `meta.coverage_from` and `meta.notice`, so an empty page is never mistaken for a quiet market.
* A range that ends before a data type's policy floor (for example Hyperliquid candles before 2025-03-01) returns `400` with `error_code` `range_before_coverage`.

```json theme={"theme":"github-dark"}
{
  "success": true,
  "data": [],
  "meta": {
    "count": 0,
    "has_more": false,
    "symbol": "km:US500",
    "venue": "hip3",
    "coverage_from": "2026-01-12T00:00:00Z",
    "notice": "No data in the requested range. HIP-3 trades coverage for km:US500 begins 2026-01-12 (UTC); the requested window ends before coverage starts. See /v1/symbols for per-symbol coverage dates.",
    "request_id": "26157aa1-a118-4676-a8a0-99fee73fa049"
  }
}
```

## Unsupported combinations and unknown routes

A route that asks a venue for a data type it does not offer, such as order flow on Hyperliquid Spot, returns `404` with `error_code` `unsupported_for_venue`. The message and the `available_on` list name the venues and routes that do serve it. Any other unknown path returns `404` with `error_code` `route_not_found`. Neither is ever an empty or plain-text response.

## Deprecated root routes

The unprefixed routes `/v1/trades/{symbol}`, `/v1/orderbook/{symbol}`, `/v1/funding/{symbol}`, `/v1/openinterest/{symbol}`, and `/v1/instruments` are aliases for Hyperliquid. They keep working, and every response carries `Deprecation: true` and a `Link` header with `rel="successor-version"` that points at `/v1/hyperliquid/`. Use the venue-prefixed routes in new code. No removal date has been set.

## Capabilities

`GET /v1/capabilities` lists what each venue serves: one row per venue and data type, with its REST routes, WebSocket channels, whether live streaming and replay are available, the first served time, the cadence, the page limit, and the accepted intervals. It is public, needs no API key, and costs no credits. Use it to check a combination before you call it, and to drive venue and channel choices in your own code. The rendered table is on [Capabilities](/capabilities).

## Related pages

<CardGroup cols={2}>
  <Card title="Errors" icon="triangle-alert" href="/errors">
    Every `error_code`, its HTTP status, and what to do next.
  </Card>

  <Card title="Capabilities" icon="table-properties" href="/capabilities">
    Venue and data type matrix with live, replay, and history start.
  </Card>

  <Card title="Pagination" icon="list-ordered" href="/rest-api/pagination">
    Follow `has_more` and `next_cursor` through long histories.
  </Card>

  <Card title="Data conventions" icon="binary" href="/rest-api/conventions">
    Decimal strings, numeric fields, and HIP-4 probabilities.
  </Card>
</CardGroup>


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