Ticker Stream
Get 24-hour statistics updated every 200ms.
{
"method" : "subscribe" ,
"subscription" : [{
"type" : "ticker" ,
"symbol" : "BTC-USD"
}]
}
Update Frequency : Every 200ms
Ticker Fields :
Field Description priceChangeAbsolute price change over 24h priceChangePercentPercentage price change over 24h lastPriceLast traded price highPrice24h high lowPrice24h low volume24h base asset volume quoteVolume24h quote asset volume markPriceCurrent fair/mark price oraclePriceOracle-reported price openInterestTotal open interest fundingRateCurrent funding rate regimeMarket regime indicator (-1, 0, 1) regimeDtRegime duration in 10s intervals regimeVolRegime-adjusted volatility regimeMvRegime mean value fairBookPxFair price derived from order book fairVolFair volatility estimate fairBiasFair price bias timestampTimestamp (nanoseconds)
Candles Stream
Real-time candlestick data with historical backfill.
{
"method" : "subscribe" ,
"subscription" : [{
"type" : "candle" ,
"symbol" : "BTC-USD" ,
"interval" : "1m"
}]
}
Supported Intervals : 10s, 1m, 3m, 5m, 15m, 30m, 1h, 2h, 4h, 6h, 8h, 12h, 1d, 3d, 1w, 1M
Initial Response : Up to 5000 historical candles
Updates : Real-time (10s instant; larger intervals aggregated ~10–20s)
Candle Fields :
Field Description tOpen timestamp (milliseconds) TClose timestamp (milliseconds) oOpen price hHigh price lLow price cClose price vVolume nNumber of trades
Trades Stream
Real-time trades feed
{
"method" : "subscribe" ,
"subscription" : [{
"type" : "trades" ,
"symbol" : "BTC-USD"
}]
}
Initial Response : None (stateless)
Updates : Real-time on every fill
Trade Fields :
Field Description sSymbol (market) pxExecution price szSize traded timeTimestamp (milliseconds) sidetrue if taker bought, false if taker soldmakerMaker public key (base58) takerTaker public key (base58) reasonFill reason (optional; only present if not a normal trade, e.g. "liquidation", "adl") liqLiquidation flag (optional; only present if true)
L2 Snapshot Stream
Periodic full order book snapshots.
{
"method" : "subscribe" ,
"subscription" : [{
"type" : "l2Snapshot" ,
"symbol" : "BTC-USD" ,
"nlevels" : 10 ,
"aggregation" : 0.5
}]
}
Parameters :
nlevels (optional): Number of price levels per side
aggregation (optional): Price bucket size in quote currency
Update Frequency : Every 200ms
Structure : levels[0] = bids (descending), levels[1] = asks (ascending)
L2 Delta Stream
Real-time incremental order book updates with initial snapshot.
L2 Delta sends an initial snapshot (latest cached book state) on subscription, then real-time delta updates for every price level change.
Subscribe
Response
Delta (Bid Side)
Delta (Ask Side)
{
"method" : "subscribe" ,
"subscription" : [{
"type" : "l2Delta" ,
"symbol" : "BTC-USD"
}]
}
Initial Response : Latest cached book state (if available)
Updates : Real-time on every price level change
Delta Format :
Each delta update contains changes to a single price level
Only ONE side (bids or asks) will have levels per update (the other is empty [])
levels[0] = bids (highest to lowest)
levels[1] = asks (lowest to highest)
Each level: {px, sz, n} where n is always 0 for deltas
sz: 0 means remove the level
Risk Metrics Stream
Subscribe to risk metrics for a symbol. Risk metrics include maintenance-margin surfaces (buy/sell grids over notional and leverage) and asset correlations.
{
"method" : "subscribe" ,
"subscription" : [{
"type" : "risk" ,
"symbol" : "BTC-USD"
}]
}
Initial Response : Latest cached risk metrics (if available)
Updates : Event-driven (only when asset risk changes)
Risk Metrics Fields :
Field Description symbolMarket symbol timestampTimestamp in milliseconds regimeRisk regime index (-12 to 12) leverageArray of leverage knot points (e.g. 1.0 … 50.0) notionalsArray of notional knot points (e.g. 50000 … 10000000) buy2D array of risk points [notional_idx][leverage_idx] for buy side sell2D array of risk points [notional_idx][leverage_idx] for sell side corrsArray of [pair, correlation] tuples (e.g. ["BTC:ETH", 0.71])
Buy/sell point fields (each cell in the grid):
Field Description mmrOStart-of-regime maintenance margin ratio mmrEEnd-of-regime maintenance margin ratio pProbability of remaining in the regime
Surface indexing : To get the risk point for a given notional and leverage, find the notional bracket in notionals, the leverage bracket in leverage, then use buy[notional_idx][leverage_idx] or sell[notional_idx][leverage_idx]. Interpolate between surrounding grid points if needed.
Frontend Context Stream
Aggregated market context for all symbols. Ideal for dashboard views.
{
"method" : "subscribe" ,
"subscription" : [{
"type" : "frontendContext"
}]
}
Initial Response : Latest cached ticker data for all symbols
Updates : Every 2 seconds
Context Fields :
Field Description symbolMarket symbol volume24h trading volume (base currency) fundingCurrent funding rate oiOpen interest (base currency) lastPriceLast traded price priceChange24h price change (absolute) priceChangePercent24h price change (percentage)
Multiple Subscriptions
Subscribe to multiple streams at once:
{
"method" : "subscribe" ,
"subscription" : [
{ "type" : "ticker" , "symbol" : "BTC-USD" },
{ "type" : "trades" , "symbol" : "BTC-USD" },
{ "type" : "candle" , "symbol" : "BTC-USD" , "interval" : "1m" },
{ "type" : "l2Snapshot" , "symbol" : "BTC-USD" , "nlevels" : 20 },
{ "type" : "l2Delta" , "symbol" : "BTC-USD" },
{ "type" : "risk" , "symbol" : "BTC-USD" },
{ "type" : "frontendContext" }
]
}
Response :
{
"type" : "subscriptionResponse" ,
"topics" : [
"ticker.BTC-USD" ,
"trades.BTC-USD" ,
"candle.BTC-USD.1m" ,
"l2snapshot.BTC-USD" ,
"l2delta.BTC-USD" ,
"risk.BTC-USD" ,
"frontendContext"
]
}
Example Implementation
const WebSocket = require ( 'ws' );
const ws = new WebSocket ( 'wss://exchange-ws1.bulk.trade' );
ws . on ( 'open' , () => {
console . log ( 'Connected to Bulk Exchange' );
// Subscribe to multiple streams
ws . send ( JSON . stringify ({
method: 'subscribe' ,
subscription: [
{ type: 'ticker' , symbol: 'BTC-USD' },
{ type: 'trades' , symbol: 'BTC-USD' },
{ type: 'frontendContext' }
]
}));
});
ws . on ( 'message' , ( data ) => {
const message = JSON . parse ( data );
if ( message . type === 'subscriptionResponse' ) {
console . log ( 'Subscribed to:' , message . topics );
return ;
}
switch ( message . type ) {
case 'ticker' :
console . log ( 'Ticker:' , message . data . ticker );
break ;
case 'trades' :
console . log ( 'Trade:' , message . data . trades );
break ;
case 'frontendContext' :
console . log ( 'Context:' , message . data . ctx );
break ;
}
});
ws . on ( 'error' , ( error ) => {
console . error ( 'WebSocket error:' , error );
});