Skip to main content

Order Book Channel

Subscribe to public order book updates including order placements and cancellations.

Channel Names

  • Global tape: tape - Receive updates for all markets
  • Market-specific: {marketId} - Receive updates only for a specific market (UUID)
When subscribing to a specific market, you will receive initial book messages containing the current order book state. When subscribing to the global tape (tape), you will not receive these initial order book state messages—only subsequent updates.

Subscription

// Subscribe to all markets
ws.send(JSON.stringify({
  event: 'subscribe',
  data: 'tape'
}));

Event Types

The order book channel broadcasts two types of events:
  • PLACE - A new order has been placed or an existing order has been partially filled
  • CANCEL - An order has been explicitly cancelled
Implicit cancellations (e.g., when a market closes) are not broadcast on this channel. Use the Market Lifecycle Channel to handle those events.

Message Format

{
  "event": "book",
  "data": {
    "type": "PLACE",
    "order": {
      "price": 0.667,
      "qty": 110,
      "originalQty": 110,
      "outcomeId": "123e4567-e89b-12d3-a456-426614174000"
    },
    "fills": [
      {
        "id": "fill-123",
        "orderId": "order-456",
        "price": 0.667,
        "qty": 50,
        "isWash": false,
        "isTaker": true,
        "marketId": "market-789",
        "outcomeId": "123e4567-e89b-12d3-a456-426614174000"
      }
    ],
    "market": {
      "id": "market-789",
      "description": "KC v BUF Total",
      "status": "OPEN",
      "type": "TOTAL",
      "strike": 26.5,
      "volume": 1000000
    }
  }
}

Order Fields

FieldTypeDescription
pricenumberThe price of the order in decimal probability (0-1, up to 3 decimal places)
qtynumberThe remaining quantity in Minimum Currency Units
originalQtynumberThe original quantity when the order was placed
outcomeIdstringUUID of the outcome for this order

Fill Fields

FieldTypeDescription
idstringUUID of the fill
orderIdstringUUID of the order that was filled
pricenumberThe execution price in decimal probability
qtynumberThe quantity filled
isWashbooleanWhether this is a wash trade
isTakerbooleanWhether this fill was the taker side
marketIdstringUUID of the market
outcomeIdstringUUID of the outcome

Example Implementation

import WebSocket from 'ws';

const ws = new WebSocket('wss://api.novig.us/tape', {
  headers: {
    'Authorization': `Bearer ${ACCESS_TOKEN}`
  }
});

ws.on('open', () => {
  // Subscribe to global tape
  ws.send(JSON.stringify({
    event: 'subscribe',
    data: 'tape'
  }));
});

ws.on('message', (data) => {
  const message = JSON.parse(data.toString());

  if (message.event === 'book') {
    const { type, order, fills, market } = message.data;

    console.log(`${type} event for market: ${market.description}`);
    console.log(`Order: ${order.qty} @ ${order.price}`);

    if (fills.length > 0) {
      console.log(`Fills: ${fills.length}`);
      fills.forEach(fill => {
        console.log(`  - ${fill.qty} @ ${fill.price}`);
      });
    }
  }
});

Unsubscribing

To stop receiving updates from a channel:
ws.send(JSON.stringify({
  event: 'unsubscribe',
  data: 'tape'
}));
You’ll receive a confirmation:
{
  "event": "unsubscribed",
  "data": {
    "channel": "tape"
  }
}