Skip to main content
This page explains the core concepts used throughout the Odds API: how IDs are constructed, how entities relate to each other, how timestamps are used, and how to design reliable client-side storage.

Language prefix

All endpoints are prefixed with a language code:
  • /en/...
  • /de/...
  • /fr/...
Translated fields (for example names) follow the prefix language when available. Identifiers (sportId, fixtureId, etc.) are language-independent.

Sports, tournaments, seasons

sportId

  • Integer.
  • The first two digits embedded into several downstream IDs.
  • Discover via /sports.

tournamentId

  • Integer.
  • Belongs to exactly one sport.
  • Discover via /tournaments.

seasonId

  • Integer.
  • Belongs to exactly one tournament.
  • Discover via /seasons.
See the full Sports Coverage table for every sportId and whether it’s available as fixtures, futures, or both.

Markets and outcomes

TL;DR — Every selection follows a fixed hierarchy: marketType → period → handicap → side, all baked into the outcomeId — so the same bet always resolves to the same marketId / outcomeId, addressed by coordinates rather than bookmaker name strings. The one part not in outcomeId is the player, carried by playerId. All outcomes of a market share its marketId, which equals the market’s first outcomeId.

How markets decompose (the deterministic hierarchy)

Every outcomeId comes from a single, deterministic decomposition — OddsPapi splits each market into a fixed hierarchy:
marketType → period → handicap (line value / specifier) → side (outcome)   [+ optional player]
So “total goals over 2.5, full time” always lands on the same marketId / outcomeId across bookmakers and fixtures.
LevelFieldMeaning
1marketTypeThe kind of market (1x2, totals, spreads, spreads-european, bothteamsscore, drawnobet, oddeven, …).
2periodThe segment the market applies to (fulltime, p1, p2).
3handicapThe line value / specifier (e.g. 2.5, -0.25). Each distinct line value is its own marketId. 0.0 for lineless markets like 1x2.
4outcomeNameThe side of the market (Over / Under, 1 / X / 2, Yes / No, …).
Key rule: because every line value gets its own marketId, “Over 2.5” and “Over 3.5” are different markets — not two outcomes of one market. Within a single marketId, the outcomes are only the sides of that exact line (e.g. Over 2.5 + Under 2.5).
A representative slice of the real soccer market map. Each marketId equals its first outcomeId, and each line value is its own market:
marketIdmarketNamemarketTypeperiodhandicapoutcomeIdoutcomeName
101Full Time Result1x2fulltime0.01011
101Full Time Result1x2fulltime0.0102X
101Full Time Result1x2fulltime0.01032
104Both Teams To Scorebothteamsscorefulltime0.0104Yes
104Both Teams To Scorebothteamsscorefulltime0.0105No
106Over Under Full Timetotalsfulltime0.5106Over
106Over Under Full Timetotalsfulltime0.5107Under
1010Over Under Full Timetotalsfulltime2.51010Over
1010Over Under Full Timetotalsfulltime2.51011Under
1068Asian Handicapspreadsfulltime-0.510681
1068Asian Handicapspreadsfulltime-0.510692
10122European Handicapspreads-europeanfulltime6.0101221
10122European Handicapspreads-europeanfulltime6.010123X
10122European Handicapspreads-europeanfulltime6.0101242
10208First Half Result1x2p10.0102081
10208First Half Result1x2p10.010209X
10208First Half Result1x2p10.0102102
10214Draw No Betdrawnobetfulltime0.0102141
10214Draw No Betdrawnobetfulltime0.0102152
10222Odd Even Full Timeoddevenfulltime0.010222Odd
10222Odd Even Full Timeoddevenfulltime0.010223Even
10224Over Under Team 1teamtotals-team1fulltime0.510224Over
10224Over Under Team 1teamtotals-team1fulltime0.510225Under
Reading the first row: marketType=1x2, period=fulltime, handicap=0.0, outcomeName=1 — the home side of the full-time match-result market.

Relationship between marketId and outcomeId

Markets and outcomes are tightly coupled by design:
  • A market represents a complete betting market (for example moneyline, 1x2, totals).
  • A market contains multiple outcomes.
  • All outcomes that belong to the same market share the same marketId.
  • The first outcomeId of a market is always equal to the marketId.
This makes it possible to determine which outcomes belong to which market without additional metadata.

ID structure

Both marketId and outcomeId are integers constructed as:
{sportId (2 digits)} + {incrementing number}
Examples:
  • 11xxxx → basketball market or outcome
  • 14xxxx → American football market or outcome
This design provides:
  • Unlimited markets and outcomes per sport
  • Fast grouping by sport
  • Immediate visibility of market relationships

Why marketId matters (arbitrage & modeling)

All outcomes under a single marketId together represent a complete probability space. This makes marketId especially useful for:
  • Arbitrage detection
  • Overround / margin calculations
  • Probability normalization
  • Market completeness checks
Recommendation: If you perform arbitrage or pricing logic, always group odds by marketId.

Participants and players

participantId

  • Integer.
  • Represents teams or competitors in fixtures.
  • Discover via /participants.

playerId

  • Integer.
  • Used for player proposition markets.
  • playerId = 0 typically represents a non-player market.
  • Discover via /players.

Fixture IDs

fixtureId structure

fixtureId is a string that encodes multiple pieces of information:
{providerSlug}{sportId}{tournamentId}{providerFixtureId}
Conceptual example:
id1100013262926199
Where:
  • id → provider identifier / short slug
  • 11 → sportId (2 digits)
  • 000132 → tournamentId (6 digits)
  • 62926199 → provider’s native fixture ID
From the fixtureId alone you can infer the sport, tournament, and upstream provider — handy for logging and cross-system correlation.

Future IDs

futureId structure

futureId follows a similar principle:
{providerSlug}{sportId}{seasonId}{marketId}
This encodes provider, sport, season, and market — globally unique and self-describing, like fixtureId.

Odds identifiers

TL;DR — A single price is uniquely keyed by {fixtureId}:{bookmaker}:{outcomeId}:{playerId} (fixtures) or {futureId}:{bookmaker}:{participantId} (futures). Use these oddsId strings as primary keys in your storage for clean dedup, updates, and reconciliation.

Fixture odds keys

For fixtures, a single price is uniquely identified by:
{fixtureId}:{bookmaker}:{outcomeId}:{playerId}
Example:
id1400003160574217:bet365:141:0
This combination uniquely defines one price. Drop the bookmaker and you have the selection itself — {fixtureId}:{outcomeId}:{playerId} — the bookmaker-independent key for grading / settlement, since a selection wins or loses the same way everywhere. No marketId is needed; the outcomeId already encodes the market.

Future odds IDs

For futures, odds are uniquely identified by:
{futureId}:{bookmaker}:{participantId}

Timestamps (seconds vs milliseconds)

This API intentionally uses both epoch seconds and epoch milliseconds, depending on context.

Epoch seconds (UTC)

Used for scheduled or coarse-grained time values:
  • startTime
  • startTimeFrom
  • startTimeTo

Epoch milliseconds (UTC)

Used for high-frequency price updates:
  • changedAt
  • Odds since filters for fixtures
  • Futures odds createdAt

Recommendation

  • Store timestamps as integers.
  • Do not assume milliseconds where seconds are documented (or vice versa).
  • Normalize internally only if needed.

Operating tips

Server Location Matters

To achieve the lowest latency for realtime updates:
  • The fastest delivery regions are Central Europe (recommended) and US East.
  • For best performance, deploy your backend in the same datacenters we use, such as:
  • If you’re building prediction markets or models sensitive to latency, consider:
    • Deploying in Austria (AT) via Netcup, or
    • Using AWS eu-west-1 (Ireland)
⚡ Servers colocated near our streaming infrastructure receive updates faster and with fewer hops.

Snapshot + realtime pattern

A reliable integration pattern:
1

Fetch HTTP snapshot

Pull the current state (fixtures, odds, or futures) over REST.
2

Subscribe to WebSocket

Stream realtime updates on top of the snapshot.
3

Re-snapshot on signal

If the WebSocket signals snapshot_required, re-fetch the HTTP snapshot and resume the realtime stream.

Efficient backfills

  • Use since parameters where available
  • Avoid full historical fetches unless required
  • Store odds keyed by their odds identifiers for deduplication

Rate limits

See Rate Limits for headers, per-endpoint limits, and 429 backoff handling.

Historical odds and CLV

The realtime WebSocket odds and oddsFutures channels deliver latest state — optimized for low-latency trading, they coalesce or drop intermediate updates under load and are not a tick ledger.
Use the live stream to trade, and the REST history endpoints to measure — CLV models, fill auditing, and backtests.
When you need the full price movement of an outcome, or its opening vs closing line, use the REST history endpoints. They share the same oddsId format ({fixtureId}:{bookmaker}:{outcomeId}:{playerId}) as the live odds channel, so you can join realtime fills directly to their historical and closing-line records.
PurposeFixturesFutures
Full price timelineGET /fixtures/odds/historicalGET /futures/odds/historical
Opening vs closing line (OLV/CLV)GET /fixtures/odds/clvGET /futures/odds/clv
Trading use cases:
  • CLV modelling — compare your fill price against the closing line to measure edge.
  • Fill auditing — reconcile traded prices with the recorded timeline to detect slippage.
  • Backtesting — replay the full historical timeline to test strategies against real line movement.
See the API → Reference section for full request parameters, response schemas, and an interactive playground for each of these endpoints.

Glossary

Quick definitions of the core terms used throughout the API. Identifiers & data model
  • sportId — Numeric sport identifier; the first two digits of downstream marketId, outcomeId, and fixtureId.
  • fixtureId — String key for a single match/event, encoding provider, sport, tournament, and provider fixture ID.
  • futureId — String key for a futures / outright market, encoding provider, sport, season, and market.
  • marketType — The kind of market (1x2, totals, spreads, bothteamsscore, …).
  • period — The segment a market applies to (fulltime, p1, p2).
  • handicap — The line value / specifier of a market; each distinct line value is its own marketId.
  • marketId — Integer grouping all outcomes of one market; equals the market’s first outcomeId.
  • outcomeId — Integer identifying one fully-decomposed selection: marketType + period + handicap (line) + side. It encodes everything except the player — that’s what playerId adds.
  • playerId — Ties an outcome to a player for player markets; playerId = 0 is a non-player market.
  • participantId — Integer identifying a team or competitor in a fixture.
  • oddsId — Composite price key. Fixtures: {fixtureId}:{bookmaker}:{outcomeId}:{playerId}. Futures: {futureId}:{bookmaker}:{participantId}.
Prices & trading
  • OLV — Opening line value: the outcome’s first recorded price.
  • CLV — Closing line value: the outcome’s last price before settlement; the reference for grading execution.
  • staleOdds — Flag indicating a bookmaker’s connectivity is degraded, so its odds may not be current.
  • settlement — Post-event endpoints returning per-outcome results (won / lost), final scores, and margins.
Streaming & delivery
  • serverEpoch + entryId — The per-channel cursor; a change in serverEpoch means the client must re-snapshot.
  • resume / replay — Reconnect and replay missed messages within resumeWindowMs (default 60000).
  • snapshot_required — Signal that the cursor is outside the resume window and a fresh REST snapshot is needed.