Market data

Market-data API

Choose bootstrap, chart history, search mode, or the book id for a market-data read.

Market-data reads require x-app-id; a user access token is optional. Server-side clients can also send an API key to use its rate-limit budget. Keep API keys on your backend. See Server API keys.

DecisionUse thisNot this
First paint of an eventGET /venue-events/{id}/bootstrapGET /venue-events/{id} plus GET /venue-markets?venueEventId= when you need a filterable market page instead of the first slice
Chart historyGET /charts/history/manifest, then GET /charts/bars for the unfinished tailBars alone when a ready manifest already covers the prefix, or the manifest alone when history is not finalized through to
SearchGET /search?mode=instant for typeahead, mode=full for a submitted searchThe list endpoints, which are for ordinary filtered browsing
BooksOutcome id on GET /orderbooks/outcomes, GET /orderbook/outcome/{outcomeId}, and the orderbook socketMarket id on GET /orderbooks and GET /midpoints. There is no midpoint socket

Bootstrap

GET /venue-events/{id}/bootstrap is the first useful event view: event display fields, the first market slice, and the outcome ids to subscribe. Optional limit is an integer from 1 to 20. The slice is not the full event. Page the rest with List venue markets using the returned cursor. Rules, wallets, quotes, and offscreen pages are separate reads.

selectedOutcomeIds are outcome ids for chart history and the orderbook channel, not venue market ids. references points at the history manifest and that live channel. detailsDeferred is true: descriptions and rules may need a later read. freshness.assembledAt is when this response was assembled, in Unix milliseconds, not a venue timestamp.

The other way to open an event is Get venue event plus List venue markets. On both, cluster=true (the default) covers the matched cluster. cluster=false scopes counts and the market list to that one venue event. Only the strings true and false are accepted. The embedded venueMarkets array is not the market page. On a list it is a preview of up to three markets and is deprecated. Sibling venues are matchedVenueMarkets[], not extra rows inside the anchor's venueMarkets[]. Building that screen is Building market views.

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

const client = createAggClient({
  baseUrl: "https://api.t.sufwankhalid.com",
  appId: "YOUR_APP_ID",
});

const view = await client.getEventBootstrap("EVENT_ID");

Get the first useful event view.

Charts

Chart history is keyed by venueMarketOutcomeId. There is no /charts/candlesticks route.

GET /charts/history/manifest returns at most eight authorized chunk URLs, the effective resolution, the finalization boundary, and a delivery state. GET /charts/bars is the canonical bar route and the unfinished tail. Both take venueMarketOutcomeId, optional resolution, optional from, required to (Unix milliseconds), and optional countBack from 1 to 5,000. Wire resolutions are 1, 5, 60, and 1D. The SDK methods accept 1m, 5m, 1h, and 1d and map them to those wire values.

Use the resolution the manifest returns. It can be coarser than the one you asked for. Render the finalized prefix from the manifest, then request the remainder from /charts/bars when the finalization boundary is behind to. If the manifest is not ready, use a bounded /charts/bars read instead. Signed chunk URLs are temporary. Keep their query strings, do not put them in a public cache, and request a fresh manifest when they expire. loadImmutableHistory checks each chunk's SHA-256 before you draw it.

meta.state is ready, warming, unsupported, failed, or empty. ready still needs a look at completeness: ready with complete: false means cached bars that are refreshing in the background, so render them and refresh on your normal schedule. warming means keep the current view and retry within a budget using retryAfterMs. unsupported means stop polling that path. failed is an error, not an empty chart. empty means no bars for the range. An empty success body is not a healthy chart. semantics is venue-ohlcv-v1, polymarket-price-samples-v1, or kalshi-ohlcv-quote-fallback-v2. Do not draw sampled prices as venue trade candles, invent volume, or bridge a real gap.

Live overlay after that history is Real-time charts.

Get versioned chart history references. Get chart bars.

Catalog changes

To keep your own copy of events and markets current, do not poll the list routes. Subscribe to the catalog channel and catch up with GET /catalog/changes. See Catalog Sync.

GET /search requires q and type (events or markets). mode=instant is the bounded typeahead path. mode=full is the submitted search. Omitting mode is full. Instant and full share one read quota. Debounce input and abort the request you replaced. Page with the returned cursor. Use List venue events for ordinary filtered browsing, not search.

meta.complete describes whether this search finished its ranking work, not whether more pages exist. Read hasMore for pages. A search that misses its budget returns 503, not an empty page you can cache.

Search events or markets.

Order books

Outcome ids and market ids are not interchangeable. Which id to store is Ids.

You haveRead
venueMarketOutcomeIdGET /orderbooks/outcomes (up to 100 ids) or GET /orderbook/outcome/{outcomeId}. The orderbook socket takes outcome ids too.
venueMarketIdGET /orderbooks. Midpoints are GET /midpoints.

The two outcome routes share one quota, charged by distinct outcome id. A single-outcome read costs one unit. Duplicate ids in a batch count once. Switching from the batch route to the single route does not reset that budget. A missing outcome on the batch route is null, not a dropped row. A market-id orderbook row carries status and error. Do not treat an empty book as proof the market is healthy.

snapshotChecksum covers the depth-limited levels in that response. checksum is the full engine book. Do not recompute the full checksum from a truncated REST slice. REST timestamp is Unix milliseconds.

There is no midpoint WebSocket channel.

Read quotas

Market-data reads have per-group caps on top of the global limits. The current numbers are on Rate limits.

Browser Worker

Worker support is optional. createWorkerWebSocket is exported from @agg-build/sdk/browser. MarketDataEngine is exported from @agg-build/sdk/market-data. Your app supplies the Worker. The default @agg-build/sdk entry does not start one, and it stays usable in Node and React Native. Do not put an API key in the Worker asset. Keep one client and one Worker for the life of the page. If the Worker fails, close it and use the direct socket.

On this page