---
title: "Canonical Market Key (aggKey)"
description: "Fetch every venue's row for the same contract with one deterministic key"
---

> **For AI agents:** the complete documentation index is at [llms.txt](/llms.txt). Append `.md` to any page URL for its markdown version.

`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.

<Warning>
  **`aggKey` is not the cross-venue join key.** Linking the same event across venues is done by
  AGG's [matching pipeline](/recipes/matched-clusters), 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.
</Warning>

## 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](/recipes/matched-clusters) 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](/recipes/matched-clusters) 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: null` even 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](/recipes/matched-clusters) 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](/api-reference/discovery/list-venue-events) |
| Market-level keys, such as `agg_nba_nyk_sas_260610_sp_nyk_10p5` | [List Venue Markets](/api-reference/discovery/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 `null` as 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 as `p` — 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` |

<Warning>
  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.
</Warning>

## 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](/recipes/matched-clusters) 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.

## Related

<Columns cols={2}>
  <Card title="Matched Clusters" icon="link" href="/recipes/matched-clusters">
    How AGG links the same event across venues, and which id to join on.
  </Card>
  <Card title="Building Market Views" icon="layer-group" href="/recipes/building-market-views">
    Compose discovery and orderbook endpoints into event grids and trading views.
  </Card>
  <Card title="Comparing Venue Prices" icon="scale-balanced" href="/recipes/comparing-venue-prices">
    Fetch matched events and their midpoints to build a cross-venue price comparison.
  </Card>
</Columns>
