The V2 API organizes sports data in a nested hierarchy. Understanding this structure is essential for parsing event responses, building odds screens, and processing delta updates.
Hierarchy Overview
Event
├── score # Live score, game clock, status
├── teams[] # Away team (index 0), Home team (index 1)
├── schedule # Season info, event name
└── markets[] # Array of market types
├── market_id # e.g., 1 = Moneyline, 2 = Spread, 3 = Total
├── period_id # 0 = full game, 1 = first half, etc.
└── participants[] # Teams, players, or result types
├── id # Participant identifier
├── type # TYPE_TEAM, TYPE_PLAYER, or TYPE_RESULT
└── lines[] # Available lines for this participant
├── id # 32-character hex line identifier
├── value # Line value (e.g., "-3.5") or empty for moneyline
└── prices # Map of affiliate_id → price object
{affiliate_id}:
├── id # Numeric string price identifier
├── price # American odds (e.g., -110, +150)
├── is_main_line # true if this is the consensus line
└── updated_at # ISO 8601 timestamp
Event Object
Each event represents a single game or match. Events are the top-level objects returned by /api/v2/sports/{sportID}/events/{date}.
| Field | Type | Description |
|---|
event_id | string | Canonical event identifier string. Use this value in V2 path params, filters, delta consumers, and cache keys. |
sport_id | integer | Sport identifier. See Sport IDs. |
event_uuid | string | Compatibility identifier retained for older integrations. Do not assume it matches event_id. |
event_date | string | Scheduled start time in ISO 8601 UTC |
rotation_number_away | integer | Away team rotation number (not used for soccer) |
rotation_number_home | integer | Home team rotation number (not used for soccer) |
score | object | Live score and game status. See Score Object below. |
teams | array | Two-element array: [away_team, home_team]. See Team Object below. |
schedule | object | Season metadata: season_type, season_year, event_name, league_name |
markets | array | Array of Market objects with odds data |
For V2 REST endpoints and WebSocket filters, pass the event_id value returned in event payloads. Do not substitute event_uuid.
Score Object
| Field | Type | Description |
|---|
event_status | string | Current status (e.g., STATUS_SCHEDULED, STATUS_IN_PROGRESS, STATUS_FINAL). See Event Statuses. |
score_away | integer | Away team score |
score_home | integer | Home team score |
score_away_by_period | array | Score breakdown by period |
score_home_by_period | array | Score breakdown by period |
venue_name | string | Arena or stadium name. May be an empty string when unavailable from the live feed. |
venue_location | string | City and state. May be an empty string when unavailable from the live feed. |
game_clock | integer | Game clock in seconds |
display_clock | string | Formatted clock display (e.g., “4:32”) |
game_period | integer | Current period number |
broadcast | string | TV broadcast network |
event_status_detail | string | Human-readable status (e.g., “3rd Quarter - 4:32”) |
updated_at | string | ISO 8601 timestamp of the last score update |
Treat score as best-effort live feed data. Fields such as venue_name, venue_location, broadcast, display_clock, and the period arrays may be empty strings, empty arrays, or 0 until the upstream source provides them. Use updated_at to judge freshness.
Team Object
| Field | Type | Description |
|---|
team_id | integer | Normalized team identifier (stable across seasons and endpoints) |
name | string | Full team name (e.g., “Cleveland Cavaliers”) |
mascot | string | Team mascot (e.g., “Cavaliers”) |
abbreviation | string | Short abbreviation (e.g., “CLE”) |
record | string | Current season record (e.g., “42-14”) |
is_away | boolean | true if this is the away team |
is_home | boolean | true if this is the home team |
Market Object
Each market represents a type of bet (moneyline, spread, total, player prop, etc.). Markets are nested inside events.
| Field | Type | Description |
|---|
id | integer | Instance identifier for this market on this event |
market_id | integer | Canonical market type ID. See Market IDs. |
period_id | integer | Period this market applies to. 0 = full game. See Period IDs. |
name | string | Display name (e.g., “Moneyline”, “Total Over/Under”) |
market_description | string | Human-readable description |
participants | array | Array of Participant objects |
Participant Object
Participants are the entities you can bet on within a market — teams, players, or result types (Over/Under).
| Field | Type | Description |
|---|
id | integer | Participant identifier (team ID, player ID, or 0/1 for result types) |
type | string | TYPE_TEAM, TYPE_PLAYER, or TYPE_RESULT |
name | string | Display name (e.g., “Cleveland Cavaliers”, “Donovan Mitchell”, “Over”) |
lines | array | Array of Line objects |
Line Object
A line represents a specific betting line for a participant. For spreads and totals, the value contains the line number. For moneylines, value is an empty string.
| Field | Type | Description |
|---|
id | string | 32-character hex identifier for this line |
value | string | Line value: "-3.5" for spread, "224.5" for total, "" for moneyline |
prices | object | Map of affiliate ID → Price object. Keyed by sportsbook. |
When a market definition has line_value_is_participant: true, the value field contains a participant name rather than a numeric value. This is common in player prop markets.
Price Object
A price is the odds offered by a single sportsbook for a specific line.
| Field | Type | Description |
|---|
id | string | Numeric string identifier for this price |
price | number | American odds (e.g., -110, +150). A value of 0.0001 means the line is off the board. See Sentinel Values. |
is_main_line | boolean | true if this is the primary/consensus line. Use main_line=true query param to filter to main lines only. |
updated_at | string | ISO 8601 timestamp of the last price update |
Fields that appear in delta/history responses:
| Field | Type | Description |
|---|
price_delta | number | Difference from the previous price (present in some delta responses) |
closed_at | string | ISO 8601 timestamp when the line was closed. Empty string if still active. |
Traversing the Data
Reading a moneyline price
event.markets[0].participants[0].lines[0].prices["19"].price
Gives you the DraftKings (affiliate 19) moneyline price for the first participant (away team).
Reading a spread value and price
event.markets[1].participants[0].lines[0].value → "-3.5"
event.markets[1].participants[0].lines[0].prices["19"].price → -110
Iterating all prices for an event
for market in event["markets"]:
for participant in market["participants"]:
for line in participant["lines"]:
for affiliate_id, price_obj in line["prices"].items():
print(f"{market['name']} | {participant['name']} | "
f"{line['value']} | {affiliate_id}: {price_obj['price']}")
Delta Responses
Delta endpoints return a different shape. Instead of the nested event → market → participant → line → price hierarchy, they return flat change records:
| Field | Description |
|---|
event_id | Which event changed |
market_id | Which market |
participant_id | Which participant |
affiliate_id | Which sportsbook |
line | Line value |
price | New price |
previous_price | Previous price (empty string if new) |
change_type | "new", "price_change", or "line_change" |
Use the event_id, market_id, participant_id, and affiliate_id to locate the correct entry in your local cache and replace the price. See the Efficient Polling guide for the full update pattern.