Contents

Liquidation heatmap over time

Liquidation heatmap over time from the tracked Hyperliquid positions (venue=lighter | lighter_rh: tracked Lighter / Lighter RH accounts with the liquidation price Lighter reports; venue=dydx | gmx: every open dYdX v4 / GMX v2 position read from the chain, with the liquidation price we compute from the chain state; venue=all: every enabled real layer added per column): one column per interval tf (times, UTC aligned), one row per price bucket (prices, ascending); cells[t][p] is the USD that would be liquidated in that bucket at that time (longCells / shortCells split by side), plus the mark per column.

GET/api/v1/heatmap/{coin}Every key

Description

A column shows the levels at its start: the first stored snapshot inside it (snapshotAt), never a sum of several; the running column shows the newest snapshot (live). 1m columns (and 5m for the top 20 coins) come from a fine layer (0.1 % buckets within ±10 %, a snapshot every minute), the rest from 0.5 % buckets within ±50 % (layer, bucketPct, rangePct). freshUsdShare / ageP50Sec per column say how much of the mapped USD was re-read within the cadence and how old it is. tf=1d (Hyperliquid): every day the daily history covers shows its snapshot of every open Hyperliquid position (shortly after 00:00 UTC, the same 0.5 % buckets), the tracked wallets only the days it does not cover yet (normally today); columnSource says which per column, the price rows span the lowest to the highest column mark ± 30 %, and the window reaches as far back as the plan history. Intraday tf (Hyperliquid): every value is measured, nothing is computed between snapshots (since 1.22.0). Live columns start on 2026-11-03 14:15 UTC; before that a column shows the newest daily snapshot of all positions before its end when it is at most 24 hours older (columnSource daily_fill, never across a missing day); after it a column without a live snapshot shows the same daily snapshot until the next live column. Columns reconstructed from fills (columnSource reconstructed, dataSource reconstructed_fills, the recon* fields) are no longer returned; the values stay in the schema. data.dataSource marks every column live or daily_snapshot; columns=live keeps only the live columns. Intervals per plan: free key and keyless 15m, 1h; Pro / API Dev add 5m, 4h, 12h, 1d; Desk / API Pro add 1m. Every coin on every plan; heatmap history (also for its layers): free key and keyless the last 24 hours, Pro / API Dev 1 year, Desk / API Pro 3 years.

Who can call it

Available with every key and keyless (X-Blockmetric-Access: public). Keys of Free accounts get free-tier data (real-time feeds, 30 days of history, heatmap over time for every coin over the last 24 hours, liquidation levels now for every coin, the same as the free web plan); Pro and Desk keys the data of their plan; API Dev / API Pro raise the limits.

No key
24 h
Free
30 days
Pro
365 days
Desk
1095 days
API Dev
365 days
API Pro
1095 days

History window per plan. Limits: Authentication & limits.

Parameters

Parameters of /heatmap/{coin}
ParameterDescription
coinstring · pathrequiredCoin name, e.g. BTC (case-insensitive).
tfstringColumn interval: 1m, 5m, 15m, 1h, 4h, 12h or 1d (UTC aligned: 4h at 00/04/…, 12h at 00/12, 1d at 00:00). An interval outside the plan answers 403 plan_required. 1m only for the top 20 coins by open interest (kept 30 days); a window without 1m data answers 400. Recommended: always pass tf (tf=15m gives the same columns as the default). Without tf the API behaves as before 1.12.0 (15-minute columns, coarsened automatically for long windows) and end is not available.one of 1m, 5m, 15m, 1h, 4h, 12h, 1d
hoursintegerWindow in hours (with tf). Default = the interval's default range (1m 6, 5m 24, 15m 24, 1h 336, 4h 720, 12h 4320, 1d 8760), clamped to the plan's heatmap history (free key and keyless the last 24 hours, Pro / API Dev 1 year, Desk / API Pro 3 years). More than the interval's column cap (1m 12 h, 5m 48 h, 15m 168 h, 1h 720 h, 4h 2160 h, 12h 8760 h, 1d 26280 h) or the heatmap history answers 400 invalid_param, never coarsened silently.1–26280
endstringEnd of the window (ISO 8601, default now; needs tf, without tf 400): page back in time, e.g. 1m columns three days ago. Clamped to now and to the plan's heatmap history (meta.warnings says so).ISO 8601, e.g. 2026-10-23T12:00:00Z
columnsstringall (default) | live: only the columns of the live collection (data.dataSource live); columns filled from the daily snapshot become gaps (zero cells, hasSnapshot false, mark null), like a window without a snapshot. Times and price rows stay the same.one of all, live · default all
clustersintegerAdd data.clusters: the N (1–20) price buckets with the most USD above and below the mark of the newest column with a snapshot (price, usd, longUsd, shortUsd, signed distance): the alert-bot view without reading cells.1–20
venuestringhyperliquid (default: the tracked Hyperliquid positions, the answer as before) | lighter | lighter_rh (tracked Lighter / Lighter RH accounts with the liquidation price Lighter reports) | dydx | gmx (every open dYdX v4 / GMX v2 position read from the chain, with the liquidation price we compute from the chain state) | all (every enabled DEX venue: the real per-venue layers added per column; data.venueColumns says which venue contributed a snapshot to which column, a venue without one adds nothing). Never an estimate for positions that are not public. A coin without a market on the venue answers 404; a switched-off venue 400.one of hyperliquid, lighter, lighter_rh, dydx, gmx, all · default hyperliquid
stepMinutesintegerdeprecatedDeprecated (API 1.12.0), use tf. Without tf: column width in minutes, default 15, clamped to 5–1440, coarsened automatically for long windows (≥ 60 beyond 14 days, at most 720 columns). Below 15 needs Pro, Desk or an API plan (403 plan_required, since 1.23.0). Together with tf: 400.5–1440
layerstringreal (default, the only layer: tracked positions of the venue). est / both were removed on 2026-10-23 (API 1.9.0) together with the estimated CEX layer (real data only); they now answer 400 invalid_param.one of real · default real

Response fields

Every success is { data, meta }; these are the fields of data. meta is the same on every endpoint.

Response fields of /heatmap/{coin}
FieldDescription
coinstringCoin name as on Hyperliquid (BTC, kPEPE, HIP-3 names like xyz:TSLA).
bucketSizenumberPrice step between rows (0 when there is no data).
times[]array of string (ISO 8601)Column times, oldest → newest.
prices[]array of numberLower edge of each price row, ascending.
cells[]array of arraycells[timeIndex][priceIndex]: USD that would be liquidated in that bucket at that time (long + short).
longCells[]array of arraySame shape, long positions (below the mark).
shortCells[]array of arraySame shape, short positions (above the mark).
mark[]array of numberMark price per column (null when no snapshot exists for that slot).
hasSnapshot[]array of booleanPer column: true when a stored snapshot fills the slot. false = gap (collector down): its cells are 0 only for the shape and are not data.
maxUsdnumberLargest cell value (USD).
updatedAtstring (ISO 8601) · nullableNewest snapshot.
tfstring (enum)Column interval (absent with the deprecated stepMinutes).
stepMinutesintegerColumn width in minutes.
layer"fine" | "wide"fine = 0.1 % buckets within ±10 % (every minute, top 20 coins); wide = 0.5 % buckets within ±50 %. One layer per response.
bucketPctnumberBucket width of the layer as a fraction of the mark (0.001 / 0.005). Deprecated: use bucketFraction (same value).
rangePctnumberRange of the layer around the mark as a fraction (0.1 / 0.5). Deprecated: use rangeFraction (same value).
bucketFractionnumberBucket width of the layer as a fraction of the mark (0.001 = 0.1 %).
rangeFractionnumberRange of the layer around the mark as a fraction (0.5 = ±50 %).
clustersobject · nullableWith ?clusters=N: the largest buckets above and below the mark of the newest column with a snapshot.
clusters.timestring (ISO 8601)Column the clusters are read from (the newest one with a snapshot).
clusters.marknumber · nullableMark of that column.
clusters.above[]array of objectsLargest buckets at or above the mark, largest first (short liquidations).
clusters.above[].pricenumberLower edge of the price bucket.
clusters.above[].usdnumberLong + short that would be liquidated in the bucket (USD).
clusters.above[].longUsdnumberLong positions (USD).
clusters.above[].shortUsdnumberShort positions (USD).
clusters.above[].distancenumber · nullableSigned distance from the mark, fraction (−0.03 = 3 % below).
clusters.below[]array of objectsLargest buckets below the mark, largest first (long liquidations).
clusters.below[].pricenumberLower edge of the price bucket.
clusters.below[].usdnumberLong + short that would be liquidated in the bucket (USD).
clusters.below[].longUsdnumberLong positions (USD).
clusters.below[].shortUsdnumberShort positions (USD).
clusters.below[].distancenumber · nullableSigned distance from the mark, fraction (−0.03 = 3 % below).
snapshotAt[]array of string (ISO 8601)Per column: exact time of the snapshot drawn (the first one inside the column; the newest one in a live column); null = gap.
livebooleanThe last column is still running and shows the newest snapshot.
freshUsdShare[]array of numberPer column: share (0–1) of the mapped USD whose wallet was re-read within the cadence before the snapshot (fine 1 min, wide 5 min); null = unknown.
ageP50Sec[]array of integerPer column: USD-weighted median age of the mapped positions in seconds; null = unknown.
venue"hyperliquid" | "lighter" | "lighter_rh" | "dydx" | "gmx" | "all"Venue layer of the answer (present with ?venue=lighter | lighter_rh | dydx | gmx | all; absent = Hyperliquid).
venueColumns[]array of objectsvenue=all: per venue, the columns it contributed a snapshot to (a venue without one adds nothing to that column).
venueColumns[].venue"hyperliquid" | "lighter" | "lighter_rh" | "dydx" | "gmx"Trading venue the row comes from.
venueColumns[].present[]array of booleanPer column: the venue contributed a snapshot.
columnSource[]array of "all_positions" | "daily_fill" | "reconstructed" | "tracked"With tf on Hyperliquid: per column, where its snapshot comes from. tracked = the live layer of the tracked wallets. tf=1d: all_positions = the daily history of every open Hyperliquid position (one snapshot shortly after 00:00 UTC), used for every day it covers; tracked only for days it does not cover yet (normally today). Intraday tf (1m to 12h): reconstructed (not returned since 1.22.0) = no live snapshot was stored in the column, so it shows the levels of all positions reconstructed from fills between two daily snapshots (snapshotAt = the 15-min reconstruction step at or before the column start; see reconBaseAt, reconSinceBaseSec, reconAssumedShare, reconQuality); daily_fill = no live snapshot and no reconstruction, so it shows the newest daily snapshot of all positions before the column end, at most 24 hours older than its start (snapshotAt = that snapshot). Neither has freshness figures; clusters use the newest tracked column. The sources differ in scale (all positions vs the tracked part); null = gap.
dataSource[]array of "live" | "reconstructed_fills" | "daily_snapshot"Per column, where its data comes from: live = a snapshot of the live collection (tracked wallets; also every column of venue=lighter / all and of the deprecated stepMinutes path); reconstructed_fills (not returned since 1.22.0) = reconstructed from fills between two daily snapshots of all positions; daily_snapshot = the daily snapshot of all positions (tf=1d history or an intraday daily fill); null = gap. ?columns=live keeps only the live columns.
reconBaseAt[]array of string (ISO 8601)Not returned since 1.22.0 (measured values only). Reconstructed columns only (null elsewhere; absent when the window has none): time of the real daily snapshot of all positions the reconstruction was replayed from (the nearer one).
reconSinceBaseSec[]array of integerNot returned since 1.22.0 (measured values only). Reconstructed columns only: seconds from reconBaseAt to the reconstruction step; negative = before that snapshot (replayed back in time from the next day's snapshot). |value| is at most about 12 hours.
reconAssumedShare[]array of numberNot returned since 1.22.0 (measured values only). Reconstructed columns only: share (0–1) of the mapped USD whose margin type or entry price had to be assumed (a position the fills opened without a known setting).
reconQuality[]array of "pass" | "warn" | "fail" | "unvalidated"Not returned since 1.22.0 (measured values only). Reconstructed columns only: how the reconstruction of this coin and day scored when replayed all the way to the other daily snapshot (worst case, 24 hours): pass = long and short USD within 10 %, bucket error at most 0.25, correlation at least 0.9 and closer than carrying the snapshot forward; warn = within 30 % and correlation at least 0.8; fail = worse (deposits, withdrawals and transfers between accounts are not in the fills); unvalidated = not checked yet.

Errors

Methodology

Code snippets in these docs are licensed under MIT-0: copy them into your own code without attribution. The SDKs, CLI and MCP server will be, once published, Apache-2.0; the name Blockmetric is not licensed (forks must be renamed). Data from the API is governed by the API terms; third-party exchange data by the exchange’s terms.

LiveHyperliquid markets 16sOperationalHyperliquid positions & whales 3sOperationalLiquidation heatmap & levels 3sOperationalLighter markets & liquidations 24sOperationalLighter positions & heatmap 3sOperationalLighter RH positions & heatmap 3sOperationalBinance markets 45sOperationalBybit markets 15sOperationalBinance liquidations 24sOperationalBybit liquidations 24sOperationaldYdX positions & heatmap 3sOperationalGMX positions & heatmap 6sOperationalLong/short & open interest history 7sOperationalOrder books & trade flow 5sOperationalOn-chain transfers 10sOperationalSecurity monitor 54sOperationalBlockmetric Sentiment 9mOperationalOfficial news 8mOperationalAlert delivery 3sOperational10:06:42 UTCData: Blockmetric Research · Binance · Bybit