Skip to main content
The WebSocket gateway delivers a full orderbook snapshot immediately when you subscribe — no REST call needed. After the initial snapshot, incremental deltas keep your local book in sync.

Connect and Subscribe

const ws = new WebSocket(`wss://ws.agg.market/ws?appId=${appId}`);

ws.onopen = () => {
  ws.send(JSON.stringify({
    action: "subscribe",
    marketIds: ["market-123"],
  }));
};
After subscribing, you receive these messages in order:
  1. { type: "subscribed", marketIds: ["market-123"] } — confirmation
  2. { type: "orderbook_snapshot", ... } — full book, sent immediately
Then ongoing:
  1. { type: "orderbook_delta", ... } — incremental updates as the book changes

Handle Snapshots and Deltas

let localBook = { bids: [], asks: [] };

ws.onmessage = (event) => {
  const msg = JSON.parse(event.data);

  switch (msg.type) {
    case "orderbook_snapshot":
      // Full book replacement — this is your initial state
      localBook = { bids: msg.bids, asks: msg.asks };
      break;

    case "orderbook_delta":
      // Incremental update — apply changes to local book
      applyDelta(localBook, msg);
      break;
  }

  renderOrderbook(localBook);
};

Delta Application Logic

Deltas tell you which price levels changed. A level with size: 0 means remove it.
function applyDelta(book, delta) {
  if (delta.bids) {
    for (const level of delta.bids) {
      if (level.size === 0) {
        book.bids = book.bids.filter((b) => b.price !== level.price);
      } else {
        const existing = book.bids.find((b) => b.price === level.price);
        if (existing) {
          existing.size = level.size;
        } else {
          book.bids.push(level);
        }
      }
    }
    book.bids.sort((a, b) => b.price - a.price); // descending
  }

  if (delta.asks) {
    for (const level of delta.asks) {
      if (level.size === 0) {
        book.asks = book.asks.filter((a) => a.price !== level.price);
      } else {
        const existing = book.asks.find((a) => a.price === level.price);
        if (existing) {
          existing.size = level.size;
        } else {
          book.asks.push(level);
        }
      }
    }
    book.asks.sort((a, b) => a.price - b.price); // ascending
  }
}

Sequence Gaps

The gateway tracks sequence numbers per client. If your client misses a delta (e.g. due to network lag), the gateway automatically sends a full snapshot instead of the delta. You don’t need to handle sequence gaps — just handle both orderbook_snapshot and orderbook_delta as shown above.

Reconnection

If your WebSocket disconnects, reconnect and resubscribe. The gateway sends a fresh snapshot on subscribe, so you’ll always start with a consistent state:
function connect() {
  const ws = new WebSocket(`wss://ws.agg.market/ws?appId=${appId}`);

  ws.onopen = () => {
    ws.send(JSON.stringify({
      action: "subscribe",
      marketIds: ["market-123"],
    }));
  };

  ws.onclose = () => {
    setTimeout(connect, 1000); // reconnect after 1s
  };

  ws.onmessage = handleMessage;
}
You can also request a fresh snapshot without reconnecting:
ws.send(JSON.stringify({ action: "resnapshot", marketIds: ["market-123"] }));

REST Orderbook (Optional)

If you need a one-time orderbook fetch without maintaining a WebSocket connection, use the REST endpoint:
const book = await client.getAggregatedOrderbook({ marketId: "market-123" });
This returns the same data as the WebSocket snapshot but as a single request.