A sports game’s markets are spread across companion events (moneyline, spreads, totals, props)
and venues, all sharing one canonical game key (aggKey, e.g. agg_fifwc_bih_che_260618).
Build the detail page with three steps and no client-side matching.
Listing the games (one tile per game)
GET /venue-events?grouped=true returns one tile per game: a venue’s companion events
(… - More Markets, … - Exact Score, … : Spread) fold under their base, and cross-venue
siblings collapse to the cluster anchor. Each tile carries the game aggKey and
groupMarketCount (open markets across the whole game). Tap a tile, take its id, and load the
detail page below.
grouped is opt-in — only pass grouped=true once you have the game-detail page below,
because grouping hides the companion events from the listing and the detail page is what
re-surfaces their markets (spreads, exact score, props) via aggKey. Omit grouped (the
default) and companion events list as separate tiles.
1. Load the event
GET /venue-events/:id → read structureType (sport → render the game page) and aggKey
(the game handle). The response also carries venues[] and the event’s own markets.
2. Load each section lazily
The detail page is tab/section based. Load one section per call by the game aggKey plus the
normalized enums — do NOT fetch the whole game at once (a game can be hundreds of markets):
GET /venue-markets?aggKey={gameAggKey}&sportsMarketType=spread&period=full&limit=50&cursor=…
aggKey here is game-scoped: pass the event-level aggKey and you get every market of the
game across companion events + venues (moneyline, spreads, totals, props), deduped to one row
per logical market (cross-venue siblings on matchedVenueMarkets[]).
- Filter by the normalized enums to load one tab/section:
sportsMarketType ∈ moneyline / spread / total / prop / completion / other
(completion = match-completion propositions, e.g. tennis “will the match be completed”
rather than a winner market)
period ∈ full / 1h / 2h / q1..q4 / ot
- plus
lineValue (number) and sectionRank (order) on each market.
Prop tabs via marketCategory (deprecated — use marketGroup instead)
marketCategory is deprecated in favor of marketGroup (see the Fields reference below).
It remains populated for back-compat — the soccer-only prop tabs (corners, goals, assists,
shots) still appear there — but new code should filter by marketGroup.
Each market carries a normalized marketCategory — the subject grouping for the prop tabs,
orthogonal to sportsMarketType:
game_lines — moneyline / spreads / totals (sub-group with sportsMarketType + period)
exact_score, corners, goals, assists, shots — the dedicated prop tabs (soccer only)
other — recognized sports markets without a dedicated tab; null for non-sports markets
Load one prop tab the same way you load Game Lines:
GET /venue-markets?aggKey={gameAggKey}&marketCategory=corners&limit=50
As with every other enum, the API exposes the category; your UI owns the tab label.
- Compose your own tabs/labels from these enums — the API exposes data, not presentation. e.g.
“Game Lines” =
sportsMarketType ∈ {moneyline,spread,total}; “Halves” = period ∈ {1h,2h}.
- Paginate large sections with
cursor/limit.
3. Prices, order ticket, chart
- Live cross-venue prices / best price:
GET /orderbook/midpoints?venueMarketIds=… (the list
returns last-known DB prices; midpoints are live).
- Order ticket / smart routing (split across venues):
GET /orderbook/{venueMarketOutcomeId}/route?maxSpend=…&compareVenues=true → per-venue fills[] + venueSoloQuotes[].
- Price chart:
GET /charts/bars?venueMarketOutcomeId=…&resolution=5.
Tab labels and grouping are yours to define. The API gives you normalized enums
(sportsMarketType, marketGroup, period, lineValue, sectionRank); map them to whatever
tabs your UI needs. The reference mapping lives in our demo app.
Fields reference
The following fields are available on /venue-events and /venue-markets for sports content.
sport (on VenueEvent)
Normalized cross-venue sport classification. null for non-sports events.
Closed vocabulary:
| Value | Description |
|---|
soccer | Association football |
basketball | Basketball (NBA, WNBA, college, international) |
baseball | Baseball (MLB, international) |
american_football | American football (NFL, college) |
hockey | Ice hockey (NHL, international) |
tennis | Tennis (ATP, WTA, Grand Slams) |
cricket | Cricket (Test, ODI, T20) |
golf | Golf (PGA, LIV, majors) |
mma | Mixed martial arts (UFC, Bellator, etc.) |
boxing | Boxing |
motorsport | Racing (F1, NASCAR, IndyCar, etc.) |
esports | Competitive gaming (CS2, Dota 2, LoL, Valorant, Honor of Kings, etc.) |
table_tennis | Table tennis / ping pong |
rugby | Rugby (union & league — Top 14, NRL, Six Nations, etc.) |
volleyball | Volleyball |
pickleball | Pickleball (MLP, PPA) |
lacrosse | Lacrosse (PLL, NLL) |
aussie_rules | Australian rules football (AFL/AFLW) |
other_sport | Any sport not in the list above |
marketGroup (on VenueMarket)
Sport-aware FE grouping. Use this to build per-sport tab sets. Supersedes marketCategory
for sports tabs (see note above). The marketGroup query parameter on /venue-markets accepts
any value from this set.
Closed vocabulary:
| Value | Description |
|---|
game_lines | Full-game moneyline / winner markets |
spreads | Handicap / point-spread markets |
totals | Over/under total-points or total-goals markets |
period_lines | Intra-game moneyline, spread, or total scoped to a period (quarter, half, inning, set, map) |
exact_score | Exact final score markets |
team_props | Team-level proposition markets (NRFI, first-5-innings winner, both-teams-to-score, etc.) |
player_props | Player-level proposition markets (points, rebounds, strikeouts, etc.) |
specials | Novelty / event-level specials (toss winner, method of victory, championship outright, etc.) |
completion | ”Will this match complete?” propositions (tennis, cricket) |
other | Sports markets that don’t fit the groups above |
marketSubtype (on VenueMarket)
Lossless raw venue market type string preserved from discovery. Examples:
cricket_toss_winner, nrfi, tennis_set_winner, cs2_odd_even_total_kills,
baseball_team_first_five_winner, soccer_halftime_result, map_handicap.
Use marketSubtype to label or disambiguate rows within a marketGroup (e.g. render the
nrfi row with its proper label rather than a generic “Team Props” heading). null when the
venue supplies no subtype.
period (on VenueMarket)
Temporal scope of the market. Expanded from the original set to cover all sports:
| Tokens | Description |
|---|
full | Full game / match |
match | Alias for full match (tennis, cricket) |
series | Multi-game series result |
1h / 2h | First / second half (soccer, basketball, american_football) |
q1 / q2 / q3 / q4 | Quarters (basketball, american_football) |
period_1 / period_2 / period_3 | Periods (hockey) |
inning_1 … inning_9 | Individual innings (baseball) |
first_5_innings | First-five-innings scope (baseball) |
set_1 … set_5 | Individual sets (tennis) |
map_1 … map_5 | Individual maps (esports — CS2, Dota 2, etc.) |
game_1 … game_5 | Individual games within a series (esports, some tennis) |
ot | Overtime / extra time |
Per-sport tab matrix
Use this table as the starting point for building per-sport tab UIs. Render only the
marketGroup values that appear for a given sport; hide empty tabs.
Coverage reflects what venues currently list. other and other_sport are catch-alls. The set
is venue-driven and grows as new market types are listed.
| Sport | marketGroups present | Notable subtypes / periods |
|---|
soccer | game_lines, spreads, totals, period_lines, exact_score, team_props | soccer_halftime_result (periods 1h/2h), soccer_exact_score, both_teams_to_score; legacy corners/goals/assists/shots via marketCategory |
basketball | game_lines, spreads, totals, period_lines, player_props | quarters q1–q4; player points / rebounds / assists props |
baseball | game_lines, spreads, totals, team_props, player_props | nrfi (inning_1), baseball_team_first_five_winner (first_5_innings), strikeout / home-run player props |
american_football | game_lines, spreads, totals, period_lines | quarters q1–q4, halves 1h/2h |
hockey | game_lines, spreads, totals, period_lines | period_1–period_3 |
tennis | game_lines, totals, spreads, completion | tennis_set_winner (set_1–set_5), tennis_first_set_totals (set_1), tennis_match_totals (match), tennis_completed_match |
cricket | game_lines, totals, team_props, player_props, specials, completion | cricket_toss_winner (specials), cricket_team_top_batter / cricket_most_sixes (player_props), cricket_completed_match |
golf | game_lines, specials | Outright winner, matchup markets, MVP / championship specials |
mma | game_lines, specials | Fight winner, method-of-victory / round specials |
boxing | game_lines, specials | Fight winner, method / round specials |
motorsport | game_lines, specials | Race winner, podium specials |
esports | game_lines, spreads, totals, player_props, specials | map_handicap (spreads), cs2_odd_even_total_kills / kill_over_under_game (player_props), first_blood_game / dota2_rampage (specials); periods map_1–map_5 / game_1–game_5 |
rugby | game_lines, totals, specials | Match winner, draw, handicap; mostly moneyline today |
volleyball | game_lines, totals, specials | Match/set winner, set totals |
pickleball | game_lines, specials | Match winner; mostly moneyline today |
lacrosse | game_lines, spreads, totals | Moneyline / spread / total |
aussie_rules | game_lines, spreads, totals | Moneyline / line / total (AFL) |
sport is resolved from the venue’s league code first, then its tags (which carry a clean
sport name like “Rugby” or “Volleyball”), then the title. Sports a venue lists but that aren’t yet
in the vocabulary fall to other_sport (still classified into marketGroups) until added.
Filter examples
Baseball — team props for a specific game
GET /venue-markets?aggKey=agg_mlb_nyy_bos_260618&marketGroup=team_props
Returns the team-prop markets for that game: NRFI (nrfi, period=inning_1), first-5-innings
winner (baseball_team_first_five_winner, period=first_5_innings), and any other team-level
propositions available across venues. Each row’s matchedVenueMarkets[] contains the cross-venue
pairings so you can show the best price without a second request.
Tennis — set and match totals
GET /venue-markets?aggKey=agg_atp_djokovic_sinner_260618&marketGroup=totals
Returns all over/under totals for the match: per-set totals (period=set_1, period=set_2, …)
and full-match totals (period=match). Use marketSubtype to distinguish the rendering:
tennis_first_set_totals gets a “First Set” label; tennis_match_totals gets “Match Total”.