Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.agg.market/llms.txt

Use this file to discover all available pages before exploring further.

The same prediction market often trades on more than one venue at the same time, at different prices. AGG’s matching pipeline links those markets together as matchedVenueMarkets so you can build a cross-venue price comparison in three calls:
  1. List matched events — events confirmed on two or more venues.
  2. Walk every market and its matched siblings — collect each venueMarketId.
  3. Batch-fetch midpoints — one request returns the live Yes-side price per market.
The midpoint is the live orderbook’s headline mark on a 0–1 scale, where 0.55 means the market implies a 55% probability of “Yes”. Comparing midpoints across venues for the same matched event surfaces the spread an arbitrageur, smart router, or “best price” badge cares about.

1. Create the client

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

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

2. List matched events

getVenueEvents accepts matchStatus as an array. Pass ["matched", "verified"] to restrict the response to events confirmed across more than one venue — every market in the response includes its matchedVenueMarkets. Calls GET /venue-events.
const { data: events } = await client.getVenueEvents({
  status: ["open"],
  matchStatus: ["matched", "verified"],
  limit: 50,
});

3. Collect every venueMarketId

Walk the response and gather every market ID — the event’s own markets plus each matchedVenueMarkets[].id.
const ids = new Set<string>();
for (const event of events) {
  for (const market of event.venueMarkets ?? []) {
    ids.add(market.id);
    for (const matched of market.matchedVenueMarkets ?? []) {
      ids.add(matched.id);
    }
  }
}

4. Batch-fetch midpoints

getMidpoints accepts up to 200 IDs per call. Chunk and parallelize for larger universes. Calls GET /midpoints.
function chunk<T>(arr: T[], size: number): T[][] {
  const out: T[][] = [];
  for (let i = 0; i < arr.length; i += size) out.push(arr.slice(i, i + size));
  return out;
}

const batches = chunk([...ids], 200);
const responses = await Promise.all(
  batches.map((venueMarketIds) => client.getMidpoints({ venueMarketIds })),
);
const midpoints = responses.flatMap((r) => r.data);

5. Build the comparison

Index midpoints by venueMarketId, then for each market look up its own midpoint plus its siblings’.
const byId = new Map(midpoints.map((m) => [m.venueMarketId, m]));

for (const event of events) {
  for (const market of event.venueMarkets ?? []) {
    const own = byId.get(market.id);
    const siblings = (market.matchedVenueMarkets ?? [])
      .map((m) => byId.get(m.id))
      .filter((m): m is NonNullable<typeof m> => !!m);

    const usable = [own, ...siblings].filter(
      (m): m is NonNullable<typeof m> => !!m && m.midpoint !== null,
    );
    if (usable.length < 2) continue;

    const cheapest = usable.reduce((a, b) => (a.midpoint! < b.midpoint! ? a : b));
    const richest = usable.reduce((a, b) => (a.midpoint! > b.midpoint! ? a : b));

    console.log(event.id, {
      spread: richest.midpoint! - cheapest.midpoint!,
      cheapest: { venue: cheapest.venue, midpoint: cheapest.midpoint },
      richest: { venue: richest.venue, midpoint: richest.midpoint },
    });
  }
}

Live updates

/midpoints is a snapshot. For continuously updating prices, subscribe to the WebSocket orderbook channel with the outcome IDs you care about — every snapshot and delta carries the live midpoint per outcome with per-venue attribution. See Real-Time Orderbook.

Building Market Views

Compose discovery and orderbook endpoints into event grids and trading views.

Real-Time Orderbook

Stream live midpoints and depth via WebSocket.