Skip to main content

Ticker Stream

Get 24-hour statistics updated every 200ms.
{
  "method": "subscribe",
  "subscription": [{
    "type": "ticker",
    "symbol": "BTC-USD"
  }]
}
Update Frequency: Every 200ms

Candles Stream

Real-time candlestick data with historical backfill.
{
  "method": "subscribe",
  "subscription": [{
    "type": "candle",
    "symbol": "BTC-USD",
    "interval": "1m"
  }]
}
Supported Intervals: 10s, 1m, 5m, 15m, 1h, 4h, 1d Initial Response: Up to 5000 historical candles Updates: Interval Based

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:
  • s: Symbol (market)
  • px: Price (execution price)
  • sz: Size (amount traded)
  • time: Timestamp (milliseconds)
  • side: true if taker bought, false if taker sold
  • maker: Maker public key (base58)
  • taker: Taker public key (base58)
  • liq: Liquidation 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

Incremental order book updates with sub-millisecond latency.
{
  "method": "subscribe",
  "subscription": [{
    "type": "l2Delta",
    "symbol": "BTC-USD"
  }]
}
Initial Response: Current book state (full snapshot, same format as l2Snapshot) Updates: Real-time on every price level change (delta format) Delta Format:
  • Initial response: Full order book snapshot (both sides populated, same as l2Snapshot)
  • Subsequent updates: Each delta update contains changes to a single price level
  • Only ONE side (bids or asks) will have levels per delta 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
Note: The initial snapshot provides the complete order book state. Subsequent updates are incremental deltas that modify your local book state.

Risk Metrics Stream

Subscribe to coin-based risk metrics including lambda surfaces, leverage curves, and power-law coefficients used for risk calculations.
{
  "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:
  • symbol: Market symbol
  • timestamp: Timestamp in milliseconds
  • regime: Risk regime index (-4 to 4)
  • leverage: Array of leverage knot points
  • lambdaBuy: Array of lambda values for buy side at each leverage point
  • lambdaSell: Array of lambda values for sell side at each leverage point
  • buyCoefA: Power-law coefficient a for buy side (lambda = a × leverage^b)
  • buyCoefB: Power-law coefficient b for buy side
  • sellCoefA: Power-law coefficient a for sell side
  • sellCoefB: Power-law coefficient b for sell side
Update Frequency: Event-driven - only updates when asset risk changes (not every tick)

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": "risk", "symbol": "BTC-USD"}
  ]
}
Response:
{
  "channel": "subscriptionResponse",
  "subscriptions_ids": [101, 102, 103, 104, 105]
}

Example Implementation

const WebSocket = require('ws');

const ws = new WebSocket('wss://exchange-wss.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' }
    ]
  }));
});

ws.on('message', (data) => {
  const message = JSON.parse(data);
  
  switch(message.channel) {
    case 'ticker':
      console.log('Ticker:', message.data);
      break;
    case 'trades':
      console.log('Trade:', message.data);
      break;
  }
});

ws.on('error', (error) => {
  console.error('WebSocket error:', error);
});