Markets and outcomes
How an odds line is structured — markets, outcomes, lines and prices.
An odds line answers one question about one proposition. Four fields locate it.
The shape
{
"market_id": "019f28da-10a5-744c-8281-6bc1f97f17d3",
"source": "eo_market",
"outcome_key": "away",
"label": "DONSTU",
"line": null,
"price": 13.39,
"captured_at": "2026-07-04T15:36:36.403882Z"
}market_id identifies the proposition — "who wins this match". Every outcome of the same
proposition shares it, so grouping a page of lines by market_id reconstructs whole markets.
outcome_key is the machine-readable side: home, away, over, under, and occasionally a
correct-score literal in a_b form — 2_1, 0_3 — with an underscore, not a hyphen.
label is the human name for the same thing (a team name). Switch on
outcome_key; display label.
line is the threshold that defines a market variant — 2.5 for a total, -1.5 for a
handicap. It is null on a moneyline, where there is no threshold. Two rows differing only by
line are genuinely different markets.
price is decimal odds, always. No American, no fractional, no implied-probability field.
Decimal odds
A decimal price is the total return per unit staked, so it converts to an implied probability by reciprocal:
implied probability = 1 / priceprice: 1.80 → 0.556. price: 13.39 → 0.075.
Because our published line is already de-vigged, the implied probabilities of a market's outcomes sum to almost exactly 1 — unlike a raw bookmaker price, where they sum to more. See the market line for what that means and why.
Guard the reciprocal
price is a float from real market data and can be large for a heavy underdog. It is never zero,
but defensive code should still avoid dividing without a check.
Participants
When an outcome is about a competitor, participant_type (team or player) and participant_id
point at it, so you can join to the entity without parsing label. Both are null on outcomes that
aren't about a competitor, such as a total.
Match markets and tournament markets
An odds line carries either match_id or tournament_id, never both. A tournament-scoped
line is an outright — "who wins the event" — rather than a fixture price. Check which is populated
before assuming you can join to a match.
What you won't find
There is no endpoint listing markets or market types. You get market_id on each line, which is
enough to group them; a market catalogue isn't exposed.
And no per-book prices, ever — not as a field, not as a source, not as an attribution. Every line
you receive is one of exactly two derived sources. That's a product decision, not an omission; see
the market line.