Sport events
A SportEvent is a match reported by one bookmaker. All variants share a common base; sport-specific fields appear after narrowing on sport.
Common fields
Section titled “Common fields”These appear on every SportEvent, regardless of sport:
| Field | Type | Notes |
|---|---|---|
id | SportEventId | Format vmid:<bookmaker>:<external_id>. |
kind | 'se:basketball_match' | 'se:football_match' | 'se:tennis_match' | Discriminator. |
sport | 'basketball' | 'football' | 'tennis' | Computed from kind. |
bookmaker | Bookmaker | Computed from id. |
competition | Competition | Format comp:<sport>.<league>. See examples below. |
sportRegion | string | undefined | Free-form region (e.g. 'USA'). Optional. |
startDate | DateTime | undefined | Luxon DateTime. Optional. |
matchUrl | string | undefined | Deep link to the bookmaker’s page. Optional. |
name | string | Computed display name. |
markets | ReadonlyMap<MarketId, Market> | All markets on this event. |
Methods: getMarket(id), getSelection(id).
BasketballMatch
Section titled “BasketballMatch”event.sport === 'basketball' · event.kind === 'se:basketball_match'
| Field | Type | Notes |
|---|---|---|
homeTeam | string | Full team name (e.g. "Los Angeles Lakers"). |
awayTeam | string |
name returns "<homeTeam> vs <awayTeam>".
if (event.sport === 'basketball') { console.log(`${event.homeTeam} hosts ${event.awayTeam}`)}FootballMatch
Section titled “FootballMatch”event.sport === 'football' · event.kind === 'se:football_match'
| Field | Type | Notes |
|---|---|---|
homeTeam | string | |
awayTeam | string |
name returns "<homeTeam> vs <awayTeam>".
TennisMatch
Section titled “TennisMatch”event.sport === 'tennis' · event.kind === 'se:tennis_match'
| Field | Type | Notes |
|---|---|---|
competitor1 | string | Full player name (e.g. "Carlos Alcaraz"). |
competitor2 | string |
name returns "<competitor1> vs <competitor2>". There is no inherent home/away in tennis — competitor1 / competitor2 reflect the bookmaker’s listed order.
Competition codes
Section titled “Competition codes”competition is a stable code, lowercase, formatted comp:<sport>.<league>. Examples you will see today:
| Code | Description |
|---|---|
comp:basketball.nba | NBA |
comp:basketball.euroleague | EuroLeague |
comp:football.premier_league | English Premier League |
comp:football.la_liga | La Liga |
comp:football.champions_league | UEFA Champions League |
comp:tennis.atp_us_open | US Open (ATP) |
comp:tennis.wta_us_open | US Open (WTA) |
The set of competitions in production grows as we extend coverage. The format is stable; new codes follow the same scheme.
ID format details
Section titled “ID format details”A SportEventId looks like vmid:<bookmaker>:<external_id>. The <external_id> portion is whatever the bookmaker assigns — opaque, but stable for the duration of the match. Examples:
| Bookmaker | Example id |
|---|---|
ps3838 | vmid:ps3838:1610547234 |
Don’t try to parse external_id — its shape varies per bookmaker. If you need the bookmaker, read event.bookmaker (computed).
Optional fields, in practice
Section titled “Optional fields, in practice”Some bookmakers reliably populate startDate and matchUrl; others occasionally omit them. Always handle the undefined case in user-facing code — the type system enforces it.
if (event.startDate) { const minutesUntilStart = event.startDate.diffNow('minutes').minutes}