Data: historical, node and explorer
The API keeps only recent history; a full record needs pagination, archived node data or your own node, and each trade counted once by its trade id.
The info endpoint forgets. userFills returns only your 2000 most recent fills (other caps in the numbers), and no public stream carries every user’s fills: the trades feed gives each coin’s trades with both counterparties, but no fees or builder codes.
Counting rows correctly matters as much as finding them. Say a taker buys 10,000 USDC of a perp from one maker. You get two fill rows of 10,000 USDC notional, a taker row and a maker row, sharing one tid. Sum every row and you count 20,000 USDC; count one notional per tid and you get 10,000.
Miscounting like this (two rows per match, shared hashes, outcome fills that never touched the book) is why public volume numbers disagree.
Where each kind of history lives
Section titled “Where each kind of history lives”| Source | Holds | Limits |
|---|---|---|
| Info endpoint | per-user fills, orders, funding, ledger; per-market trades and candles | see the caps below; time-range responses paginate |
S3 bucket hyperliquid-archive |
L2 book snapshots (market_data) and asset contexts (asset_ctxs) |
uploaded about monthly; no guarantee of timeliness; data may be missing; no candles or spot asset data; the requester pays transfer costs |
S3 bucket hl-mainnet-node-data |
fills by block, older fills and trades, explorer blocks, L1 transactions, non-trade events | the requester pays transfer costs |
| Your own node | everything the node writes under ~/hl/data |
about 100 GB of logs per day |
Explorer userDetails |
one address’s L1 actions, typed, with an error field |
the 300 most recent |
Inside hl-mainnet-node-data:
| Prefix | Holds |
|---|---|
node_fills_by_block |
current fills, written by a node run with --write-fills --batch-by-block |
node_fills |
older fills, in the API format |
node_trades |
older trades, not in the API format |
explorer_blocks, replica_cmds |
historical blocks and L1 transactions |
misc_events_by_block |
transfers, staking and funding |
Paginating the info endpoint
Section titled “Paginating the info endpoint”Time-range requests return at most 500 elements or distinct blocks; use the last timestamp returned as the next startTime.
{"type": "userFillsByTime", "user": "0x0000000000000000000000000000000000000000", "startTime": 1681222254710, "aggregateByTime": false}startTimeand optionalendTimeare inclusive milliseconds, so pages overlap at the boundary: deduplicate.- History requests cost extra IP weight per 20 items returned (rate limits).
- Query with the account’s own address; an API wallet’s address returns nothing.
Fills: one row per side, counted by tid
Section titled “Fills: one row per side, counted by tid”A fill carries coin, px, sz, side, time, startPosition, dir, closedPnl, oid, feeToken and:
| Field | Meaning |
|---|---|
crossed |
true for the taker |
fee |
negative is a rebate |
builderFee |
optional, already included in fee |
hash |
the L1 transaction hash, shared by every partial fill of one transaction: never a fill key |
tid |
the trade id, the key to deduplicate on. The docs define it as a 50-bit hash of the buyer’s and seller’s order ids, and use (block_time, coin, tid) as the globally unique trade id |
aggregateByTime: true merges one crossing order’s partial fills into fewer rows; don’t mix pulls with and without it.
Coin names differ by market (asset ids):
| Market | coin |
|---|---|
| Validator-operated perps | plain name |
| HIP-3 perps | dex:COIN |
| Spot pairs | @N or PURR/USDC |
| Outcome sides | #N |
Node data schemas
Section titled “Node data schemas”A node writes hourly files. A node_trades record holds both sides: side_info[0] is the buyer, side_info[1] the seller:
{ "coin": "COMP", "side": "B", "time": "2024-07-26T08:26:25.899", "px": "51.367", "sz": "0.31", "hash": "0xad8e0566e813bdf98176040e6d51bd011100efa789e89430cdf17964235f55d8", "trade_dir_override": "Na", "side_info": [ {"user": "0xc64cc00b46101bd40aa1c3121195e85c0b0918d8", "start_pos": "996.67", "oid": 12212201265, "twap_id": null, "cloid": null}, {"user": "0x768484f7e2ebb675c57838366c02ae99ba2a9b08", "start_pos": "-996.7", "oid": 12212198275, "twap_id": null, "cloid": null} ]}Output under ~/hl/data |
Contents |
|---|---|
replica_cmds/{start_time}/{date}/{height} |
blocks parsed as transactions |
periodic_abci_states/{date}/{height}.rmp |
state snapshots every 10,000 blocks |
node_trades/hourly/{date}/{hour} |
trades, both sides per record |
node_order_statuses/hourly/{date}/{hour} |
every order status change, with the full order |
node_raw_book_diffs/hourly/{date}/{hour} |
book changes: new {sz}, update {origSz, newSz}, or remove |
misc_events/hourly/{date}/{hour} |
staking deposits, delegations and withdrawals, validator rewards, funding, ledger updates |
Ledger updates cover withdrawals and deposits (the Arbitrum bridge), vault flows, liquidations, InternalTransfer (a perp USDC transfer), sub-account and spot transfers, spot genesis, RewardsClaim (builder and referrer fees), AccountActivationGas, PerpDexClassTransfer and DeployGasAuction. A funding event carries coin, usdc, szi, fundingRate and nSamples.
From an abci state snapshot a node can compute an L4 book (every resting order at every level, in time order, trigger orders last); applying the order status stream keeps it live. Priority fee records in node data are listed on priority fees.
The explorer: what the chain did with your action
Section titled “The explorer: what the chain did with your action”POST https://rpc.hyperliquid.xyz/explorer{"type": "userDetails", "user": "0x..."}It shows what the chain recorded for an action whose reply you never saw, or one sent through CoreWriter, which never reports back to the HyperEVM. A CoreWriter action HyperCore understood appears typed; one it did not appears nowhere. EVM transactions appear as evmRawTx.
The type name tells the two routes apart; recorded on testnet from one account:
CoreWriter action 15 {"type":"SystemBoleAction","operation":"supply","token":0,"wei":1000000000000}HTTP borrowLend {"type":"borrowLend","operation":"supply","token":0,"amount":"5"}CoreWriter send-asset actions, such as a contract’s transfer back to the HyperEVM, appear as SystemSendAssetAction. Explorer requests cannot go over the WebSocket.
The numbers
Section titled “The numbers”| Cap | Value |
|---|---|
userFills |
2000 most recent |
userFillsByTime |
2000 per response; 10,000 most recent reachable |
historicalOrders, userTwapSliceFills |
2000 most recent |
candleSnapshot |
5000 most recent candles |
| Time-range responses | 500 elements or distinct blocks |
Explorer userDetails |
300 most recent actions |
| Explorer request weight | 40 |
| Node state snapshots | every 10,000 blocks |
| Node output | about 100 GB per day |
Keeping a complete record
Section titled “Keeping a complete record”For a complete tax or accounting record, record fills as they happen or export them before they pass the caps above.
- Record from day one: subscribe to
userFills, persist every fill keyed ontid, backfill gaps withuserFillsByTimepages (WebSocket). - For venue-wide data, read the node bucket or run a node.
- Use the explorer for forensics, not bookkeeping: one Safe sent 278 actions in half an hour, so its 300-action window reached back barely further.
- Build funding, transfer and staking histories from
misc_events, not balance changes.
Where volume counts go wrong
Section titled “Where volume counts go wrong”- Outcome markets produce structural fills with
dirSplit Outcome, Merge Outcome, Negate Outcome, Merge Question and Settlement; only Buy and Sell crossed the book. Structural fills were about a fifth of all outcome fills, and settlement fills never carry a builder code. - On outcome markets
dayNtlVlmis per side and the two sides sum todayBaseVlm; adding both sides’dayNtlVlmdouble counts. - The node archive can hold one side of a trade only: from 2 to 15 May, only 33.3 per cent of 874k archived trades had both sides. Volume from single-sided archives needs a stated correction.
For the source of the deepest data, see Running a node. For reading the error field the explorer returns, see Error responses.