> ## Documentation Index
> Fetch the complete documentation index at: https://docs.odds-api.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Odds Summary

> Best, average, median, worst and fair odds for every market line across bookmakers in one call. Built for odds comparison pages.

## What it returns

`GET /v3/odds/summary` answers "what is the market paying?" for an event. For each market line and outcome you get:

* **`best`** and **`bestBookmakers`**: the highest price and every bookmaker offering it, up to 5.
* **`average`**: the market average.
* **`median`**: the middle price, robust to a single unusual book.
* **`worst`**: the lowest price, so you can show how much shopping around saves.
* **`fair`**: the margin-free price.

Each line also has `books` (how many bookmakers priced it), `fairBooks` (how many fed the fair price) and `payout`.

<Note>
  The odds summary is available on **Growth plans and above**. Free, Solo and Starter plans receive a sample response so you can build against the shape before upgrading. It has fixed prices, `"demo": true` in the body and an `X-OddsAPI-Demo: true` header.
</Note>

## Request

```bash theme={null}
curl "https://api.odds-api.io/v3/odds/summary?apiKey=YOUR_API_KEY&eventId=73806028"
```

For up to 10 events at once, use `/v3/odds/summary/multi` with `eventIds`. It returns an array and counts as one request:

```bash theme={null}
curl "https://api.odds-api.io/v3/odds/summary/multi?apiKey=YOUR_API_KEY&eventIds=73806028,73806029"
```

| Parameter | Description |
| - | - |
| `eventId` | The event ID |
| `markets` | Comma-separated market names, case-insensitive. Default `ML,Spread,Totals`. Max 20 |
| `lines` | `main` (default) returns the main line of Spread and Totals markets. `all` returns every line priced by at least 3 bookmakers, with `main: true` on the main one |
| `bookmakers` | Limit the summary to some of your selected bookmakers, for example your partner books |
| `includeExchanges` | `true` adds an `exchanges` block with the best exchange and prediction-market back price per outcome, and the stake available at that price |

## Response

```json theme={null}
{
  "eventId": "73806028",
  "home": "Gorilla FC",
  "away": "Rayon Sports FC",
  "date": "2026-10-09T17:00:00Z",
  "status": "pending",
  "computedAt": "2026-10-09T15:20:11Z",
  "markets": [
    {
      "name": "ML",
      "lines": [
        {
          "hdp": null,
          "main": true,
          "books": 23,
          "fairBooks": 21,
          "outcomes": {
            "home": { "best": 3.9, "bestBookmakers": ["Bet365"], "average": 3.38, "median": 3.3, "worst": 3.05, "fair": 3.65 },
            "away": { "best": 2.2, "bestBookmakers": ["Betway"], "average": 2.08, "median": 2.1, "worst": 1.85, "fair": 2.3 },
            "draw": { "best": 3.2, "bestBookmakers": ["Betsson", "Kambi"], "average": 3.04, "median": 3.05, "worst": 2.8, "fair": 3.45 }
          },
          "payout": { "best": 0.977, "average": 0.905 }
        }
      ]
    }
  ]
}
```

Outcome keys follow the market: `home`/`draw`/`away`, `over`/`under` or `yes`/`no`. Prices are decimal numbers.

## How the numbers are calculated

* **Average** is calculated in probability space: `average = n / sum(1 / price)`. A plain mean of decimal odds is pulled up by one long price. This is not.
* **Fair** removes the margin. Each bookmaker that prices every outcome of the line is de-vigged, each outcome takes its median probability, and the result is normalized to 100%. It needs at least 3 bookmakers that can be de-vigged. `fairBooks` says how many were used. A bookmaker priced at no margin still counts for best, average and worst.
* **sharpFair** appears only if you have ON Sharp selected. It is ON Sharp's price with its fixed margin removed.
* **Payout** is `1 / sum(1 / price)` over the outcomes. `payout.best` uses the best prices, so a value above 1 means the best prices across different bookmakers add up to more than 100% return. `payout.average` is the market's typical payout.
* **Main line** is the most balanced line, where the two sides are closest to even, among the lines priced by at least half as many bookmakers as the most-priced line.

## What is included

* **One vote per bookmaker.** A bookmaker and its clones, or its latency variants, count once.
* **Only bookmakers that are updating.** A bookmaker counts only if its prices changed within the last 5 minutes before kickoff, or the last 60 seconds once the event is live. A feed that stops updating drops out. The check is per bookmaker: a price that has not moved for hours still counts while the bookmaker's feed keeps updating other prices.
* **No outliers in best, worst or average.** If any price in a bookmaker's row is far from the line's median, as with a wrong-match or wrong-side row, the whole row is left out of `best`, `worst` and `average` and counted in `excluded`. The `median` still uses every bookmaker. A line needs at least 3 bookmakers without an outlier, otherwise it is not returned.
* **At least 3 bookmakers.** Lines priced by fewer are not returned.
* **Exchanges are separate.** Exchange and prediction-market prices are before commission, so they never count towards `best`, `average`, `median` or `worst`. Use `includeExchanges=true` to see them in their own block.
* **Two-way moneylines in sports that also run three-way are skipped.** In ice hockey, futsal, bandy and similar sports, a home/away moneyline cannot be told apart from a three-way one missing its draw, so only three-way moneylines are summarized there. Spreads and totals are unaffected.

## Exchange liquidity

Each exchange quote carries `liquidity`: the stake you can place at that price.

| Venue | `liquidity` | `currency` |
| - | - | - |
| Polymarket, Kalshi, NoVig, ProphetX | Stake in US dollars. Kalshi's contract count is converted at the contract price | `USD` |
| Betfair Exchange | Stake in Betfair's own currency | not set |

The best exchange price can carry a small stake, so check `liquidity` before showing it as the headline.

## Example: average odds on a fixtures list

```javascript theme={null}
const ids = events.slice(0, 10).map((e) => e.id).join(',')
const res = await fetch(
  `https://api.odds-api.io/v3/odds/summary/multi?apiKey=${API_KEY}&eventIds=${ids}&markets=ML`
)
const summaries = await res.json()

for (const s of summaries) {
  const ml = s.markets.find((m) => m.name === 'ML')?.lines[0]
  if (!ml) continue
  console.log(`${s.home} v ${s.away}`, ml.outcomes.home.average, ml.outcomes.draw?.average, ml.outcomes.away.average)
}
```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.