Contents

Live event stream

Server-Sent Events (text/event-stream) with every radar event as soon as it is stored, in the webhook envelope. One connection counts as one request against the per-minute limit.

GET/api/v1/streamAPI Pro · 2 streams

Connect

One long-lived GET. Each event arrives as one data: line with the webhook envelope.

Open the stream
curl -N -H "Authorization: Bearer $BLOCKMETRIC_API_KEY" \
  "https://api.blockmetric.io/v1/stream?kinds=big_liquidation,liq_cascade&minSeverity=2"

Parameters

Stream parameters
ParameterDescription
kindsstringComma-separated event kinds (whale_open, whale_close, whale_liquidated, whale_near_liq, big_liquidation, liq_cascade, funding_extreme, funding_flip, oi_spike, record, smart_money, hack, depeg, tvl_drop, cex_outflow, hl_market_change, hl_manipulation, hl_adl, oracle_deviation, vault_drawdown, liq_extreme, protocol_outflow, incident, big_transfer, stablecoin_mint, stablecoin_burn, dex_whale_trade, risk_wallet_move, risk_wallet_listed); default all.
minSeverityinteger1 info, 2 notable, 3 major, 4 critical; default 1.
coinstringOne coin or up to 20 comma-separated (BTC,ETH,kPEPE); case-insensitive. Events without a coin are then not sent.
lastEventIdintegerAlternative to the Last-Event-ID header (resume after this event id).

Or send the Last-Event-ID header; browsers' EventSource does it for you on reconnect.

What arrives

Stream frames
FrameLinesMeaning
message (no event: line)id: <radar event id, integer> data: <envelope JSON, one line>One radar event. The SSE id is the numeric event id; the envelope id is "evt_" + id.
readydata: { plan, filter: { kinds, minSeverity, coins }, resumedFrom, backlog, heartbeatSec, maxDurationSec }Sent once after connecting (no id).
gapdata: { lastEventId, message }Some events after Last-Event-ID were outside the resume window; backfill with GET /api/v1/radar/events.
byedata: { reason: "max_duration" | "plan" | "key_revoked" | "error" | "slow_consumer", reconnect }The server closes the connection. Reconnect after max_duration / error / slow_consumer (the client read too slowly, so resume with Last-Event-ID); not after plan / key_revoked (also sent when the key expired or the address left its IP allowlist).
(comment): ping <ISO time>Heartbeat every 15 s (keeps proxies from closing idle connections).
On the wire
retry: 3000
: connected

event: ready
data: {"plan":"api_pro","filter":{"kinds":null,"minSeverity":1,"coins":null},"resumedFrom":null,"backlog":0,"heartbeatSec":15,"maxDurationSec":3600}

id: 5468
data: {"id":"evt_5468","type":"funding_extreme","created":1793106660,"createdAt":"2026-10-27T13:11:00.000Z","data":{"id":5468,"ts":"2026-10-27T13:11:00.282Z","kind":"funding_extreme","severity":1,"coin":"xyz:PURRDAT","title":"xyz:PURRDAT funding at +128% APR on Hyperliquid","body":"Hourly rate +0.0146% (longs pay shorts) · open interest $11.6M · mark $9.2451.","data":{"venue":"hyperliquid","fundingApr":1.28301588,"fundingHourly":0.000146463,"openInterestUsd":11556929.71,"mark":9.2451},"source":"hyperliquid"}}

: ping <ISO time>

Reconnect and resume

Send Last-Event-ID (EventSource does this automatically on reconnect; "evt_<id>" is accepted too) to receive what you missed: events stored in the last 15 minutes after that id, at most 500. Without it the stream starts with new events only.

A reconnecting client in Node.js
let lastId = null
for (;;) {
  const res = await fetch('https://api.blockmetric.io/v1/stream?minSeverity=2', {
    headers: { Authorization: `Bearer ${process.env.BLOCKMETRIC_API_KEY}`, ...(lastId ? { 'Last-Event-ID': lastId } : {}) },
  }).catch(() => null)
  if (res && (res.status === 401 || res.status === 403)) throw new Error(`stream refused: HTTP ${res.status}`)
  if (res?.ok) {
    let buf = ''
    try {
      for await (const chunk of res.body.pipeThrough(new TextDecoderStream())) {
        buf += chunk
        let i
        while ((i = buf.indexOf('\n\n')) >= 0) {
          const frame = buf.slice(0, i)
          buf = buf.slice(i + 2)
          const id = /^id: (.*)$/m.exec(frame)?.[1]
          const data = /^data: (.*)$/m.exec(frame)?.[1]
          if (id && data) {
            lastId = id // events without "event:" carry an id; ready / gap / bye do not
            const ev = JSON.parse(data)
            console.log(ev.type, ev.data.severity, ev.data.title)
          }
        }
      }
    } catch {
      /* connection dropped: reconnect below */
    }
  }
  await new Promise((r) => setTimeout(r, 3000))
}
Limits
At most 2 open streams per account (429 stream_limit otherwise; a dropped connection frees its slot within 45 s). Connections close after 60 minutes with event: bye; retry: 3000 tells clients to reconnect after 3 s. A heartbeat comment arrives every 15 s.
Headers
Cache-Control: no-cache, no-transform · X-Accel-Buffering: no · X-RateLimit-Limit / -Remaining / -Reset · X-RateLimit-*-Day, RateLimit-Policy, RateLimit · X-Blockmetric-Api-Version
Errors
Before the stream starts the usual JSON errors apply: 400 invalid_param, 401 unauthorized, 403 plan_required (not API Pro), 429 rate_limited / stream_limit.
Gaps
Missed more than the resume window? Backfill from GET /radar/events. The ids are the same.

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 4sOperationalHyperliquid positions & whales 4sOperationalLiquidation heatmap & levels 6sOperationalLighter markets & liquidations 12sOperationalLighter positions & heatmap 5sOperationalLighter RH positions & heatmap 8sOperationalBinance markets 33sOperationalBybit markets 3sOperationalBinance liquidations 12sOperationalBybit liquidations 12sOperationaldYdX positions & heatmap 5sOperationalGMX positions & heatmap 8sOperationalLong/short & open interest history 2mOperationalOrder books & trade flow 3sOperationalOn-chain transfers 4sOperationalSecurity monitor 42sOperationalBlockmetric Sentiment 9mOperationalOfficial news 7mOperationalAlert delivery 5sOperational10:06:30 UTCData: Blockmetric Research · Binance · Bybit