Skip to content

Market channel

/ws/market streams the live book and tape. Use REST market data for the initial snapshot, then keep it current here. Market data is public: no Authenticate frame is required on this channel.

Six independent streams, each with its own subscribe verb and its own set of venues. A stream only accepts venues it can actually serve — asking for one it cannot is rejected as invalid_frame rather than accepted and left silent.

Stream Subscribe with Pushes Venues
Depth (aggregated levels) Subscribe-Depth Depth-Update hyperliquid, aster, lighter, polymarket, kalshi, massive, b3
Order book (per order, L3) Subscribe-Depth-L3 Order-Book-Update lighter, b3
Tape (trade prints) Subscribe-Tape Tape-Update hyperliquid, aster, massive, b3
Volume at price Subscribe-VAP VAP-Update hyperliquid, aster, massive, b3
Inside quote Subscribe-BBO BBO-Update hyperliquid, aster, lighter, polymarket, massive, b3
Candles Subscribe-Candles Candle-Update hyperliquid, aster, lighter, polymarket, kalshi, massive, b3

massive is the venue key for listed futures; the same key is what GET /api/v1/symbols/{venue} enumerates them under.

Each has a matching Unsubscribe-*; Unsubscribe-All drops the lot. Ping answers Pong, and every subscribe frame answers Result.

venue and symbol are separate fields — there is no venue:symbol string on the wire:

{ "type": "Subscribe-Depth", "venue": "hyperliquid", "symbol": "BTC" }

Subscribe-Candles and Unsubscribe-Candles additionally require interval, written as a count plus a unit — s, m, h, d, w, or M (1m, 15m, 4h, 1d, 1w). Custom resolutions are accepted and folded server-side from a finer base interval where the venue has no native bar. Each interval is its own subscription: unsubscribing 5m leaves 1h running.

Prices and sizes arrive as decimal strings, and every frame echoes venue and symbol so one socket can multiplex the whole set.

High-rate venues can print far faster than any UI can render. The tape is batched server-side into one frame per flush window: a single Tape-Update carries a trades array holding every print that landed in the window, in wire order. Iterate it; do not assume one frame equals one trade.

This matters most on futures venues, where an active session can produce hundreds of prints per second on one symbol.

Like the other channels, ?encoding=msgpack on the upgrade URL switches server→client frames to MessagePack. On a busy depth subscription this is the single cheapest performance win available to a client.

  1. Subscribe first.
  2. Then fetch the REST snapshot.
  3. Apply buffered updates on top.

Doing it the other way round leaves a hole between the snapshot and your first frame.