meta context that makes a result usable later. Exact types for each route come from OpenAPI and the Schemas pages; this page covers the handling every route shares.
Market-data routes return a JSON envelope with success, data, and meta. Data-quality, /v1/status/coverage, and /v1/symbols keep their own body shape by default, with success and meta.request_id added, and use the standard envelope when you send 0xArchive-Version: 2026-10-01. The rules shared by every route are on API conventions.
Parse a response
1
Check HTTP status
Decide retry, fail-fast, auth repair, or support escalation from the status class.
2
Check body success
Handle
success: false as an application error and preserve error_code and request_id.3
Handle empty pages
Treat
success: true plus empty data as a state to record, not as permission to fabricate records. Check meta.coverage_from and meta.notice first: present means the window predates coverage; absent usually means a quiet market, though windows past the end of a symbol’s coverage also return the plain envelope, so confirm coverage dates via /v1/symbols.4
Log request ID
Store
meta.request_id for envelope responses, for every page and every failed attempt. For resource-specific bodies, store x-request-id or the client wrapper’s request handle when available.5
Use the route schema
Parse
data from the endpoint-specific OpenAPI schema, not from a nearby example. Keep numeric-looking market fields decimal-safe until the application boundary.6
Keep venue context
Persist venue family and symbol style beside records so downstream joins do not mix Hyperliquid core, Spot, HIP-3, HIP-4, and Lighter.
Success envelope
Error envelope
code repeats the HTTP status, error_code is the stable identifier to branch on, error is the readable message, and request_id sits at the top level rather than under meta.
Treat HTTP status as the control signal and the JSON body as debugging context. Validation, auth, route, access, capacity, rate-limit, and upstream errors require different client behavior; Errors gives the retry model for each.
Empty success responses
Some historical requests returnsuccess: true with an empty data array. Before treating that as “no market activity,” check meta for coverage annotations. The two empty states mean different things, and a client that skips this check misreads pre-coverage windows as quiet markets.
A request to
/v1/hyperliquid/trades/{symbol} for a window that ends before the symbol’s coverage starts returns:
meta.coverage_from is the ISO 8601 start of recorded coverage for the requested symbol and data type. meta.notice is a human-readable explanation of why the page is empty. These fields appear on per-symbol time-series routes across venues, including trades, candles, order book history, L4 diffs and history, order history, funding, open interest, and liquidations, when the requested window ends before the symbol’s own coverage begins. A window that ends before a data type’s policy floor returns 400 with error_code range_before_coverage instead. A window that starts before the first served row and ends after it is served from that row. Quiet windows inside coverage return the plain envelope without annotations.
Do not turn an empty page into synthetic rows in either state. Store the route, query parameters, meta.count, meta.next_cursor, meta.request_id, and any coverage annotations, then decide whether the downstream job should move the window, continue, narrow the window, or mark the output incomplete.
Pagination
Cursor-paged routes setmeta.has_more, and meta.next_cursor is present exactly when it is true. Send the cursor back unchanged with the same filters, and stop when has_more is false; see Pagination. Keep request IDs per page, not just for the final result. A resumable job should store route family, route path, symbol, query parameters, cursor, request ID, output file, and data-quality decision. Confirm the route family, response shape, and freshness with a one-page request before widening a pagination loop.
Field dictionary
What the common fields mean, and the handling that keeps a backtest honest.Numbers and decimals
Types are not uniform across routes, so check the route before you bind a model.Timestamps
There are two clocks. Log both when you store a record.Order-book fields
Trade and liquidation fields
IDs to keep
Storemeta.request_id (or the x-request-id header) for support. Keep oid and trade_id for Hyperliquid L4 and fill joins, and keep order_index plus owner_account_index as numeric Lighter L3 fields. Do not use Lighter L3 indexes as wallet or raw-order identifiers.
Probability, not price
HIP-4mark_price and mid_price are implied probabilities in [0, 1], not USD. Spot symbols are pairs, and HIP-3 symbols can carry a builder prefix. Keep the venue family with every record so a later join stays inside one family.
Empty, null, and gap are different
An empty page is one of the two states under Empty success responses. A null or missing field means “not available for this record,” not zero. A coverage gap inside covered history is a third thing: confirm it against the data-quality coverage route rather than inferring it from an empty page.Data-quality responses
Data-quality routes answer whether a downstream job should trust a market-data result. A degraded status, incident, latency issue, or coverage gap does not always mean every route is unusable. It means the client must compare the state to the job tolerance and record that decision. For backtests, alerts, exports, dashboards, and model features, store both the quality response and the downstream data request ID. Coverage routes such as/v1/data-quality/coverage/{exchange}/{symbol} return a resource-specific body by default, with success and meta.request_id added; parse it from the REST reference. Send 0xArchive-Version: 2026-10-01 to receive the same body inside the standard data field.