AGG is currently in alpha. APIs, components, and docs may change.
Agg.market — Prediction Market Aggregator logo

Real-Time Orderbook

Stream a live aggregated orderbook with the SDK, hooks, or UI components

The AGG WebSocket delivers a full aggregated orderbook snapshot on subscribe, then incremental deltas as the book changes. Each outcome has its own orderbook — there is no complement derivation. Each level includes per-venue attribution so you can render both the aggregated depth and the venue breakdown from the same stream.

Orderbook subscriptions are keyed by venueMarketOutcomeId — the outcomes[].id on REST market responses — not by venueMarketId. Subscribing with a venueMarketId never resolves a book and the gateway replies with a Snapshot unavailable error. (Only the REST GET /orderbooks endpoint and the arb streams use market-level ids.)

Full control over the WebSocket connection and local orderbook state.

1. Connect and subscribe

import { createAggClient } from "@agg-build/sdk";

const client = createAggClient({
  baseUrl: "https://api.agg.market",
  appId: "your-app-id",
  wsUrl: "wss://ws.agg.market/ws",
});

let book = null;

const ws = client.createWebSocket({
  onSnapshot: (_outcomeId, nextBook) => {
    book = nextBook;
    renderOrderbook(book);
  },
  onDelta: (_outcomeId, nextBook) => {
    book = nextBook;
    renderOrderbook(book);
  },
  onError: (msg) => {
    console.error(msg.message);
  },
});

ws.subscribe("your-outcome-id", "orderbook");

The SDK applies snapshots and deltas for you, tracks seq, validates checksum (XOR of per-level CRC32), drops stale deltas where seq <= current.seq, and requests a fresh snapshot when integrity checks fail. The gateway is a stateless fan-out — all orderbook recovery is handled client-side by the SDK.

2. Read the orderbook

The OrderbookState passed to callbacks uses object-shaped levels:

interface OrderbookState {
  outcomeId: string;
  bids: Array<{ price: number; size: number; venues: Record<string, number> }>;
  asks: Array<{ price: number; size: number; venues: Record<string, number> }>;
  venueOrderbooks: Record<
    string,
    {
      bids: Array<{ price: number; size: number }>;
      asks: Array<{ price: number; size: number }>;
    }
  >;
  venues: Record<string, { bestBid: number | null; bestAsk: number | null }>;
  midpoint: number | null;
  spread: number | null;
  seq: number;
  checksum: number;
  timestamp: number; // seconds
}

3. Per-venue orderbooks

Per-venue depth is available on the same object:

const ws = client.createWebSocket({
  onSnapshot: (_outcomeId, book) => {
    console.log(book.venueOrderbooks.predict?.bids);
    console.log(book.venueOrderbooks.polymarket?.asks);
  },
});

4. REST fallback

For one-time fetches without a live socket:

const response = await client.getOrderbooks({
  venueMarketIds: ["your-market-id"],
  depth: 20,
});

const book = response.data[0];
if (book?.status !== "ok") {
  throw new Error(book?.error?.message ?? "No live orderbook available");
}

// book.venueOrderbooks — per-venue depth keyed by venue
// book.matchedMarkets  — venue markets considered for the requested market
// book.requestedMarket — lifecycle metadata for the requested market

Integrity

The SDK verifies seq and checksum automatically and requests a fresh snapshot when the local book drifts. If you are implementing the wire protocol yourself, use the WebSocket Protocol page for the snapshot/delta formats and resnapshot flow.

WebSocket Protocol

Wire format, sequencing, resnapshot requests, and heartbeat behavior.

Real-Time Charts

Build live candles from the same orderbook and trade streams.

User Notifications

Authenticated order and balance events on the same WebSocket connection.