vike
API EndpointsHyperliquid

/archive/datasets

The index of the Hyperliquid Parquet file archive — every UTC day that has a fills or positions file, with rows, bytes and the snapshot count, the column schema of both datasets, and the entry for the 5-minute latest positions file.

GET https://data.vike.io/v1/hyperliquid/archive/datasets

The index of the Hyperliquid file archive: every UTC day that has a file, per dataset, with the file's row count and size, the column schema of both datasets, and the entry for the latest positions file. It is the only way to see what exists. There is no folder to browse and no file has a URL of its own: a file is obtained from /archive/url, which answers with a temporary link.

Two datasets, one Parquet file per UTC day each, from 2026-05-01:

DatasetWhat one file holdsFirst day
fillsEvery fill of every wallet that day, sorted by asset, fill_ts, trade_id, wallet.2026-05-01
positionsEvery 5-minute snapshot of every open position that day, sorted by asset, wallet, snapshot_ts.2026-05-08, a partial day

Positions start on 2026-05-08 because that is the first day the 5-minute snapshots exist. A third file, latest/positions.parquet, holds the current open positions of every asset and is replaced every 5 minutes. How to download and read all three is in Download the Hyperliquid file archive.

cURL
# what the archive holds: every day with its rows and bytes, the schema of both datasets, and the latest positions file
curl -s "https://data.vike.io/v1/hyperliquid/archive/datasets" \
  -H "X-API-KEY: $VIKE_API_KEY"

# the newest day that has a positions file, with its snapshot count
curl -s "https://data.vike.io/v1/hyperliquid/archive/datasets" \
  -H "X-API-KEY: $VIKE_API_KEY" \
  | jq '[.dates[] | select(.streams.positions)][0]'

# the days whose positions file holds fewer than 250 snapshots: the source has them, the file is not padded
curl -s "https://data.vike.io/v1/hyperliquid/archive/datasets" \
  -H "X-API-KEY: $VIKE_API_KEY" \
  | jq -r '.dates[] | select(.streams.positions) | select(.streams.positions.snapshots < 250) | "\(.date) \(.streams.positions.snapshots)"'

# how fresh the latest positions file is, and how big
curl -s "https://data.vike.io/v1/hyperliquid/archive/datasets" \
  -H "X-API-KEY: $VIKE_API_KEY" \
  | jq '.latest.positions | {snapshot_ts, generated_at, rows, bytes}'

The route takes no parameters. This is the capture of the index, cut for the page: dates held 173 entries, so the newest two are kept, and each dataset's schema list is cut to its first two columns (the full lists are under The columns). The envelope and the latest entry are complete.

Example response
{
  "dates": [
    {
      "date": "2026-10-20",
      "streams": {
        "fills": {
          "rows": 13405172,
          "bytes": 401098335
        }
      }
    },
    {
      "date": "2026-10-19",
      "streams": {
        "fills": {
          "rows": 12022655,
          "bytes": 358509915
        },
        "positions": {
          "rows": 102738790,
          "bytes": 1639446104,
          "snapshots": 253
        }
      }
    }
  ],
  "schema": {
    "fills": [
      {
        "name": "fill_ts",
        "type": "DateTime64(3, 'UTC')",
        "meaning": "Execution time of the fill, UTC, millisecond precision."
      },
      {
        "name": "wallet",
        "type": "String",
        "meaning": "Trader address, lowercase 0x-hex."
      }
    ],
    "positions": [
      {
        "name": "snapshot_ts",
        "type": "DateTime('UTC')",
        "meaning": "Snapshot instant, UTC, whole minutes: the START of the ingestion cycle that wrote the row, not the instant of the node state it reads (typically 5-10 minutes earlier). Cycles are usually 5-7 minutes apart and irregular; a source outage leaves a longer gap. The day's `snapshots` count in the manifest says how many there are."
      },
      {
        "name": "wallet",
        "type": "String",
        "meaning": "Trader address, lowercase 0x-hex."
      }
    ]
  },
  "url_endpoint": "/v1/hyperliquid/archive/url",
  "latest": {
    "positions": {
      "snapshot_ts": "2026-10-21T10:13:00Z",
      "generated_at": "2026-10-21T10:17:15Z",
      "rows": 427884,
      "bytes": 29578173,
      "assets": 341,
      "note": "The current open positions of every asset, one row per (wallet, asset, direction), refreshed about every 5 minutes. The columns are those of the daily `positions` file (meanings under `schema.positions`). `snapshot_ts` is per row: the ingestion cycle that last wrote the position. A position that closed within the last 15 minutes can still be present with an older `snapshot_ts`, the same rule as /v1/hyperliquid/positions; keep the rows at the file's `snapshot_ts` for the newest cycle only. There is no `opened_at`: /v1/hyperliquid/positions fills it per page, and joining it here costs 3x the rest of the run. Sorted by (asset, wallet, direction) in row groups of about 65,000 rows with min/max statistics (one asset is 1-2 of them). The file is REPLACED every ~5 minutes: download it whole (about 30 MB); a ranged read can straddle a replacement and fail, so retry it.",
      "url_endpoint": "/v1/hyperliquid/archive/url?dataset=positions&date=latest"
    }
  }
}

Reading the index

  • dates is newest first. Each entry has the day and a streams object with one key per dataset that has a file that day. rows is the number of rows in the file and bytes its size, so you can budget a download before asking for the link.
  • snapshots appears on positions only: the number of distinct snapshot_ts values in that day's file, counted from the file itself. Read it before you aggregate. A day holds roughly 250 to 290 snapshots, and some hold far fewer because the source has fewer (see the callout on this page).
  • A day appears once it is complete. Yesterday's files are published in the early UTC morning; the newest day can therefore carry a fills file before its positions file, as the capture shows for 2026-10-20.
  • latest.positions is present while that file exists. snapshot_ts is the newest ingestion cycle in it and generated_at is when the file was written; rows, bytes and assets describe the file as of that moment. The file is replaced about every 5 minutes, so these values move: ask the index again rather than caching them.
  • url_endpoint is where a file is asked for. The index carries no URL for any file, because none exists.

Fewer than 250 snapshots means a gap in the source, not a missing piece of the file

A positions file is never padded. Eleven days hold fewer than 250 snapshots: 2026-05-08 (71, a partial first day), 2026-06-08 (226), 2026-06-26 to 2026-06-29 (124 to 134 each), 2026-06-30 (248), 2026-08-12, 2026-08-13 and 2026-08-17 (236 to 238) and 2026-09-28 (248). The source did not capture the rest. The snapshots field is how a client tells a thin day from a normal one without opening the file; the download guide lists the other facts worth knowing about the data.

The columns

Both lists are the schema key of the response, in file order.

fills

ColumnTypeMeaning
fill_tsDateTime64(3, 'UTC')Execution time of the fill, UTC, millisecond precision.
walletStringTrader address, lowercase 0x-hex.
assetStringInstrument as Hyperliquid names it: BTC on the main dex, dex:NAME (e.g. xyz:SP500) for a builder-deployed perp.
sideStringbuy or sell: the direction of THIS wallet's order.
size_tokenFloat64Fill size in base-asset units, unsigned (the direction is side).
priceFloat64Execution price, USD.
size_usdFloat64Notional of the fill, size_token * price, USD.
feeFloat64Fee charged in fee_token; negative is a maker rebate.
fee_tokenStringToken the fee is denominated in, e.g. USDC.
is_makerBoolTrue when this wallet's order was resting on the book.
order_idUInt64Hyperliquid order id (oid) of this wallet's order.
trade_idUInt64Hyperliquid trade id (tid). Both counterparties of one trade carry the same value; a fill is identified by (wallet, fill_ts, trade_id).
crossedBoolTrue when this fill crossed the book (the taker side).
closed_pnlFloat64Realized PnL in USD the node booked on this fill; 0 for a fill that opens or adds to a position.
dex_nameStringPerp dex the asset trades on: HL for the main dex, else the builder dex (e.g. XYZ).
start_positionFloat64 (nullable)Signed position in the asset immediately BEFORE this fill (negative is short). NULL for fills before 2026-09-29, when the column was added; 0.0 is a real value (flat before the fill).

positions

ColumnTypeMeaning
snapshot_tsDateTime('UTC')Snapshot instant, UTC, whole minutes: the START of the ingestion cycle that wrote the row, not the instant of the node state it reads (typically 5-10 minutes earlier). Cycles are usually 5-7 minutes apart and irregular; a source outage leaves a longer gap. The day's snapshots count in the manifest says how many there are.
walletStringTrader address, lowercase 0x-hex.
assetStringInstrument as Hyperliquid names it: BTC on the main dex, dex:NAME (e.g. xyz:SP500) for a builder-deployed perp. Called symbol in /v1/hyperliquid/positions. The prefix is authoritative: judge the dex by it, not by dex_name.
directionInt81 long, -1 short. The only place the side is stored: size_token and size_usd are never negative.
size_tokenFloat64Position size in base-asset units, unsigned (the side is direction).
size_usdFloat64Notional of the position at mark_price, size_token * mark_price, USD, unsigned.
entry_priceFloat64Average entry price of the position, USD.
mark_priceFloat64Mark price when the row was written, USD.
liquidation_priceFloat64Liquidation price, USD; 0 when the position has none (e.g. a well-collateralised cross-margin position).
unrealized_pnlFloat64Unrealized PnL in USD, direction * (mark_price - entry_price) * size_token.
leverageFloat32Leverage of the position as a multiple (10 = 10x). 0 when none was recorded, which happens on cross-margin rows.
margin_usedFloat64Margin the position ties up, USD: size_usd / leverage, or size_usd itself where leverage is 0.
size_cohortStringAccount-value size tier of the wallet WHEN THE ROW WAS WRITTEN (shrimp, 2x shrimp, fish, ... up to 4x whale: 12 absolute-dollar thresholds assigned at ingestion), as stored: a point-in-time label, not today's grading. The same field and vocabulary as size_cohort in /v1/hyperliquid/positions.
leverage_typeStringcross or isolated.
dex_nameStringPerp dex the asset trades on: HL for the main dex, else the builder dex (e.g. XYZ). Rows written while a clearinghouse was not yet registered hold the literal clsN (e.g. cls10) and keep it; the asset prefix is authoritative.
state_tsDateTime('UTC')The instant the state-derived columns (size, entry, mark, unrealized_pnl, leverage, margin_used, direction) describe, read from the node's state file; snapshot_ts is the WRITE time of the ingestion cycle, typically 5-10 minutes later (liquidation_price is re-read from the node at write time and belongs to snapshot_ts). 1970-01-01 00:00:00 means the row came from no state file (the per-wallet API fallback) or was written before 2026-08-22, when the column was added. Do not anchor a projection of the row on it: use snapshot_ts.
liq_progressFloat64How far the mark has moved from entry toward liquidation, clamped to 0..1: 0 at or in profit versus entry (or no liquidation price), 1 at or through the liquidation price. When a cross-margin liquidation price has drifted past entry it falls back to liquidation_price / mark_price (long) or mark_price / liquidation_price (short). The same SQL as liq_progress in /v1/hyperliquid/positions.

opened_at, which /v1/hyperliquid/positions fills in per page, is not in these files. The latest file has the same 17 columns.

Example response
{  "dates": [    {      "date": "2026-10-20",      "streams": {        "fills": {          "rows": 13405172,          "bytes": 401098335        }      }    },    {      "date": "2026-10-19",      "streams": {        "fills": {          "rows": 12022655,          "bytes": 358509915        },        "positions": {          "rows": 102738790,          "bytes": 1639446104,          "snapshots": 253        }      }    }  ],  "schema": {    "fills": [      {        "name": "fill_ts",        "type": "DateTime64(3, 'UTC')",        "meaning": "Execution time of the fill, UTC, millisecond precision."      },      {        "name": "wallet",        "type": "String",        "meaning": "Trader address, lowercase 0x-hex."      }    ],    "positions": [      {        "name": "snapshot_ts",        "type": "DateTime('UTC')",        "meaning": "Snapshot instant, UTC, whole minutes: the START of the ingestion cycle that wrote the row, not the instant of the node state it reads (typically 5-10 minutes earlier). Cycles are usually 5-7 minutes apart and irregular; a source outage leaves a longer gap. The day's `snapshots` count in the manifest says how many there are."      },      {        "name": "wallet",        "type": "String",        "meaning": "Trader address, lowercase 0x-hex."      }    ]  },  "url_endpoint": "/v1/hyperliquid/archive/url",  "latest": {    "positions": {      "snapshot_ts": "2026-10-21T10:13:00Z",      "generated_at": "2026-10-21T10:17:15Z",      "rows": 427884,      "bytes": 29578173,      "assets": 341,      "note": "The current open positions of every asset, one row per (wallet, asset, direction), refreshed about every 5 minutes. The columns are those of the daily `positions` file (meanings under `schema.positions`). `snapshot_ts` is per row: the ingestion cycle that last wrote the position. A position that closed within the last 15 minutes can still be present with an older `snapshot_ts`, the same rule as /v1/hyperliquid/positions; keep the rows at the file's `snapshot_ts` for the newest cycle only. There is no `opened_at`: /v1/hyperliquid/positions fills it per page, and joining it here costs 3x the rest of the run. Sorted by (asset, wallet, direction) in row groups of about 65,000 rows with min/max statistics (one asset is 1-2 of them). The file is REPLACED every ~5 minutes: download it whole (about 30 MB); a ranged read can straddle a replacement and fail, so retry it.",      "url_endpoint": "/v1/hyperliquid/archive/url?dataset=positions&date=latest"    }  }}