Canonical Market Key (aggKey)
Fetch every venue's row for the same contract with one deterministic key
aggKey is a deterministic key AGG computes for a market at discovery time, from that venue's own
native data. Where a market is canonicalizable, it gives you one equality token you can use to fetch
every venue's row for the same contract in a single call.
aggKey is not the cross-venue join key. Linking the same event across venues is done by
AGG's matching pipeline, and its result is already on the response —
matchedVenueMarkets[], venues[], venueCount. aggKey is one deterministic input to that
pipeline and a convenient fetch filter; it is null for a substantial share of rows, and two
members of the same cluster can carry different keys. Grouping by aggKey in app code will
under-group relative to the cluster AGG already built for you.
What it is
The key is computed from each venue's own data, so how far it converges across venues depends on the market family.
It is guaranteed identical across venues for the families where every venue exposes the same
normalizable inputs: sports head-to-head (canonical league and team codes plus the game date)
and crypto up/down markets. For those, two rows from different venues sharing a non-null
aggKey are the same market.
Other families — dated outcomes such as elections, "by when" questions, and token launches — are derived from whatever the venue publishes: most venues expose a human-readable slug, while a venue with no slug derives from its ticker, and the date segment comes from that venue's own resolution timestamp. Two venues listing the same question can therefore produce different keys. Use the matched cluster for those, not the key.
It appears on both objects in API responses:
VenueEvent.aggKey— the event (e.g. a game).VenueMarket.aggKey— a specific market within the event (e.g. a spread line).
When it's null
Not every market is canonicalizable. null means "no canonical key" — it is not an error, and it
does not mean the market is unmatched. Those rows still carry their cross-venue counterparts on
matchedVenueMarkets[], so read the matched cluster instead of
falling back to your own title matching.
- Events: free-form prose markets and some long-tail events return
aggKey: null. - Markets: a market carries a key only when the key fully identifies the
contract — moneylines, spreads and totals (the line is part of the key), and the
single market of a one-market event. Markets whose terms are not encoded in a
key — player props, exact-score / both-teams-to-score style markets, individual
strikes of a multi-strike ladder — return
aggKey: nulleven when their parent event has a key.
The useful direction is this: when two markets from different venues share a non-null
aggKey, they are the same contract — same line, same period, same window — not merely
markets of the same event. The converse does not hold: the same contract can carry
different keys on different venues, or no key at all, which is why linkage comes from the
matched cluster rather than from key equality.
Using it
Read aggKey off any market or event, then fetch every venue's row for it. Pass your
app id with the x-app-id header, the same as every other discovery call.
The aggKey param accepts a single key or several, and combines with the other
filters (venue, status, …):
| Resource | API Reference |
|---|---|
Event-level keys, such as agg_nba_nyk_sas_260610 | List Venue Events |
Market-level keys, such as agg_nba_nyk_sas_260610_sp_nyk_10p5 | List Venue Markets |
Use the API Reference for request parameters, response schemas, and try-it-out examples.
Integration notes
- Use event-level keys when you want every venue's version of the same event.
- Use market-level keys when you need the exact same contract, including line, period, and window.
- Treat
nullas normal. Some free-form or long-tail markets cannot be keyed confidently. - Match on equality only. Do not parse the string to infer teams, assets, lines, or dates in app code.
- Grouping a spread/total line ladder is the one supported structural use. Every line of one
family (a match total, a specific team's total, corners, …) shares the same market key except
the line token (
_<line>, decimals asp— e.g._2p5,_10p5). To render one ladder with a line selector, group markets by their aggKey with that token removed; the resulting family key is identical across venues, unlike the market's question or subtype. Still treat everything else as opaque — do not read the line's numeric value, teams, or dates out of the key. - Apply your normal app filters. Venue and category visibility still determine which rows your app can show.
Format
A key is the agg_ prefix followed by _-joined segments. Dates are YYMMDD
(sports local date; daily markets) or a compact UTC instant (sub-daily intraday
markets). Decimals use p (e.g. 2p5 = 2.5).
| Family | Format | Example |
|---|---|---|
| Sports head-to-head | agg_{league}_{teamA}_{teamB}_{YYMMDD}[_{mkt}] — teams sorted, canonical per-league codes (NA-league tricodes, soccer country codes, provider codes or folded names/surnames for other leagues — tennis, esports, NPB/KBO/CFL/NWSL and more; some competitions collapse to one canonical league token, e.g. FIBA regional qualifiers → fibaq, T20 cricket comps → t20); moneyline → no suffix, spread → sp_{favored}_{line}, total → tot_{subject?}{line}; non-full scopes carry a period token — trailing for spread/total (…_sp_nyk_10p5_1h), prefixed for moneyline (…_1h_ml) | agg_nba_nyk_sas_260610, agg_nba_nyk_sas_260610_sp_nyk_10p5, agg_fifwc_bih_che_260618 (soccer), agg_wta_eala_paolini_260706 (tennis) |
| Crypto up/down | agg_ud_{asset}_{interval}_{startUTC} — sub-daily intervals carry the window-start instant; daily (1d) keys carry the day only | agg_ud_btc_1h_260610T1500, agg_ud_btc_1d_260610 |
| Crypto price / threshold | agg_px_{asset}_{kind}_{instantUTC} | agg_px_btc_15m_260610T0600 |
| FX over/under | agg_fx_{pair}_{kind}_{instantUTC} | see live responses |
| Index / equity threshold | agg_idx_{symbol}_{kind}_{instantUTC} | see live responses |
| Dated outcome | agg_{normalized-subject}_{resolutionDate} | agg_us-recession-2026_261231 |
Treat aggKey as an opaque equality token. Match on equality; do not parse the
segments to infer semantics (teams, assets, dates, or a line's value). The one
exception is grouping a spread/total ladder — you may strip the line token
(_<line>, e.g. _2p5) to build a per-family key, since all lines of a family
differ only by that token. Keys for the same market are stable over time, and the
segment grammar may evolve within a key version. A future format revision will use
a new prefix (e.g. aggk2_), so the agg_ prefix is your version guard.
FAQ
What problem does aggKey solve?
Prediction markets are fragmented across venues, and each venue uses its own identifiers and market
format. aggKey gives apps one equality token they can pass back to the API to fetch every venue's
row for a contract they already hold, without inspecting venue-specific identifiers.
Should I use aggKey or the matched cluster?
Use the matched cluster for identity: which rows are the same event,
which markets are counterparts, and which id to persist. Use aggKey as a fetch filter when you
already hold a key and want the other venues' rows for it.
Should I use the event key or the market key?
Use VenueEvent.aggKey to fetch other venues' rows for the same event. Use VenueMarket.aggKey
when you need the same tradable contract, such as a specific spread, total, crypto window, or
threshold. In both cases the result is a fetch, not a grouping rule — group by the cluster.
Can I parse an aggKey?
Treat it as opaque for semantics — never read teams, assets, dates, or a line's numeric value out of
the string. The one supported structural operation, besides exact-equality matching, is grouping a
spread/total line ladder: group markets by their aggKey with the line token (_<line>, e.g.
_2p5) removed, so all lines of one family (a match total, a team's total, corners, …) fall into a
single card with a line selector. The family key is stable across venues; the market's question and
marketSubtype are not.