aggKey
Optional fetch filter for rows whose key converges. Which id to store is on the Ids page.
aggKey is an optional fetch filter. sufwan-local-test computes it at discovery from that venue's own data, and
you pass the string back unchanged to fetch the rows that share it. Which id to store is
Ids.
It appears on both objects: VenueEvent.aggKey (the event, e.g. a game) and VenueMarket.aggKey
(a market within it, e.g. a spread line).
Using it
Read aggKey off a market or event, then pass it back as a filter. The parameter accepts one key or
several, and combines with the other filters (venue, status, …). Your app's venue and category
visibility still applies.
import { createAggClient } from "@agg-build/sdk";
const client = createAggClient({
baseUrl: "https://api.t.sufwankhalid.com",
appId: "YOUR_APP_ID",
});
const { data } = await client.getVenueEvents({
aggKey: "agg_nba_nyk_sas_260610",
});List venue events. A market key uses the same aggKey
parameter on List venue markets.
| 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_m10p5 | List Venue Markets |
Use the event key for every venue's version of the same event, the market key for the exact same contract including line, period and window.
What it converges
The key is computed from each venue's own data, so how far it converges depends on the family.
It is guaranteed identical across venues where every venue exposes the same normalizable inputs: sports head-to-head (canonical league and team codes plus the game date), crypto up/down, and central-bank rate decisions (institution code plus meeting day). Two rows from different venues sharing a non-null key in those families are the same contract — same line, same period, same window.
Dated outcomes — elections, "by when" questions, token launches — are derived from whatever the venue publishes: a human-readable slug where there is one, a ticker where there is not, and a date segment from that venue's own resolution timestamp. Two venues listing the same question routinely produce different keys, so use the matched cluster for that family.
| Family | Prefix | Venues emitting it | Converges? |
|---|---|---|---|
| Sports head-to-head | agg_{league}_… | kalshi, limitless, novig, polymarket, predict | Guaranteed |
| Crypto up/down | agg_ud_ | kalshi, limitless, polymarket, predict | Guaranteed |
| Central-bank rate decision | agg_cb- | hyperliquid, kalshi, limitless, myriad, polymarket, predict | Guaranteed |
| Crypto price / threshold | agg_px_ | hyperliquid, kalshi | Best-effort |
| Index / equity threshold | agg_idx_ | kalshi | Best-effort |
| FX over/under | agg_fx_ | kalshi | Best-effort |
| Dated outcome | agg_{subject}_{YYMMDD} | every slug-bearing venue | No |
A key carried by only one venue is usually not a convergence failure — most of the time only one venue lists that game or window. The guarantee is conditional: if two venues list the same contract, their keys agree.
When it's null
null means "no canonical key". It is not an error and does not mean the market is unmatched —
those rows still carry their counterparts on matchedVenueMarkets[].
A market is keyed only when the key fully identifies the contract; see
Sports market suffixes for exactly which do. Player props, individual
strikes of a multi-strike ladder, and long-tail venue-specific propositions return null even when
their parent event has a key. Expect null far more often on markets than on events, and design for
it rather than treating it as a gap.
Do you need to parse it?
Almost never. Every fact you might read out of the string is already a typed field, and those fields are the supported contract — the segment grammar is not.
| What you need | Read this | Parse? |
|---|---|---|
| Every venue's row for a contract you hold | pass aggKey back as a filter, verbatim | No |
| Which rows are the same event or market | matchedVenueEvents[], matchedVenueMarkets[] | No |
| Teams, league, kickoff | title, sport, gameStartTime | No |
| The line's numeric value | lineValue | No |
| The scope (half, quarter, set, innings) | period | No |
| Moneyline vs spread vs total vs prop | sportsMarketType | No |
| Which tab a market belongs in | marketGroup | No |
| Ordering within a tab | sectionRank, lineValue | No |
| One spread/total ladder card with a line selector | family key derived from aggKey | Yes — the only case |
Building a sports detail page takes exactly one parse: the ladder family key in Grouping a line ladder. If you are reaching into the key for anything else, the field you want already exists.
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 (2p5 = 2.5).
A future format revision will use a new prefix (e.g. aggk2_), so agg_ is your version guard.
| Family | Format | Example |
|---|---|---|
| Sports head-to-head | agg_{league}_{teamA}_{teamB}_{YYMMDD}[{suffix}] — teams sorted; canonical per-league codes (NA tricodes, soccer country codes, folded surnames for tennis/UFC/esports); some competitions collapse to one token, e.g. FIBA regional qualifiers → fibaq | agg_nba_nyk_sas_260610, agg_fifwc_bih_che_260618, agg_wta_eala_paolini_260706 |
| Crypto up/down | agg_ud_{asset}_{interval}_{startUTC} — sub-daily carries the window-start instant, daily (1d) 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 |
| Central-bank rate decision | agg_cb-{bank}_{YYMMDD} — the cb- namespace is deliberate: a bare agg_fed_{YYMMDD} would collide with the rate-level ladder already on that key | agg_cb-fed_260916 |
| Dated outcome | agg_{normalized-subject}_{resolutionDate} | agg_us-recession-2026_261231 |
Sports market suffixes
The market key is the event key plus a suffix. A full-game two-way moneyline carries no suffix — its market key is the event key. This is the complete set.
| Market | Suffix | Example |
|---|---|---|
| Moneyline — full game, 2-way single | none | agg_ncaaf_cha_cita_260905 |
| Moneyline — decomposed leg or draw | _ml_{team}, _ml_draw | agg_afl_ade_bul_260905_ml_ade |
| Moneyline — period scoped | _{period}_ml, _{period}_ml_{team}, _{period}_ml_draw | agg_bra2_juv_lon_260901_1h_ml_juv |
| Spread | _sp_{team}_{m|p}{line}[_{period}] | agg_arg_aae_cas_260904_sp_aae_m1p5 |
| Total — whole match | _tot_{line}[_{period}] | agg_arg_aae_cas_260904_tot_0p5_1h |
| Total — corners | _tot_corners_{line}[_{period}] | agg_arg_aae_cas_260904_tot_corners_10p5 |
| Total — one team | _tot_team_{team}_{line}[_{period}] | agg_arg_aae_cas_260904_tot_team_aae_0p5 |
| Total — one team's corners | _tot_team_{team}_corners_{line} | agg_arg_aae_cas_260904_tot_team_aae_corners_2p5 |
| Correct score | _cs_{teamA}{scoreA}_{teamB}{scoreB} — teams sorted, each followed by its own score | agg_arg_aae_cas_260904_cs_aae0_cas0 |
| Both teams to score | _btts[_{period}] | agg_arg_aae_cas_260904_btts_1h |
| Team to advance | _adv (2-outcome single), _adv_{team} (decomposed legs) | agg_lec_ame_mon_260902_adv |
| UFC — goes the distance | _dist | agg_ufc_acosta_blaydes_260912_dist |
| UFC — method of ending | _mend_{method} | agg_ufc_acosta_blaydes_260912_mend_kotko |
| UFC — method of victory | _mvic_{method}_{fighter} | agg_ufc_acosta_blaydes_260912_mvic_kotko_acosta |
| UFC — round of victory | _vicrnd_{round}_{fighter} | kalshi-only, so it groups rather than converges |
{method} is a closed set: kotko, sub, dec, draw.
Full-game and full-match scopes carry no period token. Every other scope is the period value with
non-alphanumeric characters removed (set_1 → set1, first_5_innings → first5innings), trailing
for spread/total/BTTS and prefixed for moneyline.
Spread lines carry a leg token: m{line} when the named team gives points, p{line} when it
receives them — _sp_cha_m19p5, not _sp_cha_19p5. The stored lineValue sign is a venue label,
not an orientation. Code that strips a line with a bare _\d+p\d+ pattern stops matching spread
keys — silently, producing one card per line instead of one ladder.
Marker tokens are not unique
A team code can be spelled exactly like a suffix marker. Tottenham is tot, Sporting is sp,
Malmö is ml, and all three are live:
| Key | What it is |
|---|---|
agg_epl_eve_tot_260912_ml_tot | Everton vs Tottenham — Tottenham's moneyline leg |
agg_atc_sp_wol_260906_sp_sp_m1p5 | Sporting vs Wolves — Sporting −1.5 |
agg_ptc_ml_vlm_260830_tot_team_ml_corners_2p5 | Malmö's corners total |
Never split on the first _sp_, _tot_ or _ml_. Splitting agg_atc_sp_wol_260906_sp_sp_m1p5 on
its first _sp_ yields agg_atc_sp — no opponent, no date — which collides with every other
Sporting fixture. Anchor on the _YYMMDD token: it ends every event key, and markers only ever
appear after it.
const DATE = /_\d{6}(?=_|$)/;
// Everything up to and including the date token — the event base.
const eventBase = (aggKey) => {
const m = DATE.exec(aggKey);
return m ? aggKey.slice(0, m.index + m[0].length) : aggKey;
};Grouping a line ladder
One card with a line selector, unioned across venues — the only supported structural read of the key.
Uses the eventBase helper above, and gates on sportsMarketType: neither rule is safe applied to
the other type.
const familyKey = (market) => {
const base = eventBase(market.aggKey);
// Both legs of one symmetric spread → one family. They name DIFFERENT teams
// (…_sp_arg_m1p5 and …_sp_che_p1p5 are the same line).
if (market.sportsMarketType === "spread") return `${base}_sp`;
// Drop the trailing line and optional period token. What remains keeps
// subjects apart: …_tot, …_tot_team_arg, …_tot_corners.
if (market.sportsMarketType === "total")
return base + market.aggKey.slice(base.length).replace(/_\d+(p\d+)?(_[a-z0-9]+)?$/, "");
return market.aggKey;
};Both rules drop the period, so take it from the period field and put it in your group key alongside
the family. Order totals by lineValue. Order spreads by |lineValue|, taking the side of the axis
from the m/p token — polymarket stores spreads negative while kalshi, novig and predict store
them positive, so sorting on the signed value interleaves the two halves of one ladder.
Related
Matched Clusters
Where cluster fields live on the event, market, and outcome.
Ids
Which id to store, and which id is only the anchor for this page.
Sports Market Detail
Compose discovery, orderbook and chart endpoints into a cross-venue game page.
Comparing Venue Prices
Fetch matched events and their midpoints to build a cross-venue price comparison.