Are you an LLM? Read llms.txt for a summary of the docs, or llms-full.txt for the full context.
Skip to content

WebSocket

Real-time market data and user event streaming via WebSocket.

Subscription Types

TypeDataAuth
tradesReal-time tradesNo
l2BookOrder book updates (set fast: true for the 5-level low-latency feed)No
bboBest bid/offerNo
candleCandlestick updatesNo
allMidsAll mid pricesNo
activeAssetCtxAsset context (funding, OI); accepts fast: trueNo
fastAssetCtxsLow-latency mark/mid for every assetNo
userEventsUser fills, liquidationsYes
userFillsUser trade fillsYes
userFundingsUser funding paymentsYes
orderUpdatesOrder status changesYes
notificationSystem notificationsYes
webData2Extended web dataYes
activeAssetDataUser asset data (leverage, margin)Yes
clearinghouseStateUser margin/positions on a single dexYes
allDexsClearinghouseStateUser margin/positions across every dexYes
openOrdersUser open orders on a single dexYes
spotStateUser spot balances + holdsYes

Protocol Details

Connection

wss://api.hyperliquid.xyz/ws     (mainnet)
wss://api.hyperliquid-testnet.xyz/ws  (testnet)

Ping/Pong

Hyperliquid uses app-level ping/pong (not WebSocket protocol-level):

  • Server sends: Ping (plain text)
  • Client must respond: {"method":"pong"}
  • Timeout: ~30 seconds without pong → disconnect

Subscribe

{"method":"subscribe","subscription":{"type":"trades","coin":"BTC"}}
{"method":"subscribe","subscription":{"type":"l2Book","coin":"BTC","fast":true}}
{"method":"subscribe","subscription":{"type":"spotState","user":"0x..."}}

Unsubscribe

{"method":"unsubscribe","subscription":{"type":"trades","coin":"BTC"}}

Message Format

All messages arrive as JSON with a channel wrapper:

{"channel":"trades","data":[{"coin":"BTC","side":"B","px":"97432.5","sz":"0.1","time":1234567890}]}

The SDK's ws_types.extractData() strips the outer wrapper — decode functions receive the data value directly.

SDK Usage

const Ws = hlz.hypercore.ws;
 
// The WS module provides subscription type definitions
// Actual WebSocket connection is managed by the terminal/CLI layer
// using websocket.zig for the transport

Thread Safety

  • WebSocket reads are blocking — run in a dedicated thread
  • Use shutdown(fd) to break out of a blocking read (for coin/interval switches)
  • Do not use SO_RCVTIMEO with TLS on macOS (causes segfaults)
  • Parse messages outside the lock, apply results under the lock