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

> ## Agent Instructions
> For the complete API reference (every endpoint, query parameter and response field), fetch https://api.thestatsapi.com/llms.txt. Only use endpoints, parameters and fields listed there.
> Base URL: https://api.thestatsapi.com/api. Auth header: Authorization: Bearer YOUR_API_KEY. Keep the key in server-side code only.

# Get pre-match, live and player-prop odds

> Get pre-match odds with opening and latest prices, in-play odds and player-prop odds for a match, filter by bookmaker, and check odds coverage per season.

Use this page to get betting odds for a match: before kickoff, in play, and for player props.

<Tip>
  **Fastest way: ask your AI.** Set up your coding tool once with [Build with AI](/docs/build-with-ai), then paste:

  ```text Prompt wrap theme={null}
  Using TheStatsAPI (reference: https://api.thestatsapi.com/llms.txt), build a server route that takes a match_id, checks odds_available on the match, and returns the match result odds (home, draw, away) from each bookmaker with opening and latest prices. Keep the API key server-side.
  ```
</Tip>

## Bookmakers

| Bookmaker | `bookmaker` slug |
| - | - |
| Bet365 | `bet365` |
| Paddy Power | `paddy-power` |
| BetMGM UK | `betmgm-uk` |
| Pinnacle | `pinnacle` |
| Betfair Exchange | `betfair-exchange` |

On pre-match and player-prop odds, pass one or more slugs, comma-separated, to filter (`?bookmaker=bet365,pinnacle`). Leave it out to get every bookmaker. An unknown slug returns `400`. Live odds come from Bet365, Paddy Power, BetMGM UK and Betfair Exchange.

Prices are decimal odds only; convert them yourself if you need fractional or American. Pre-match and live prices are strings such as `"1.380"`; player-prop prices are numbers.

## Check the flags first

| Flag | On | Meaning |
| - | - | - |
| `odds_available` | Match | The match has pre-match odds. Always `false` for postponed and cancelled matches. |
| `live_odds_available` | Match | The match has in-play odds right now. |
| `odds_available` | Competition | The competition's matches have odds. |
| `live_odds_available` | Competition | At least one match in the competition has in-play odds right now. |

`/odds` and `/odds/live` return `404` when the match has no odds of that kind.

The JavaScript examples run on your server and read your key from the `THESTATSAPI_API_KEY` environment variable.

## Pre-match odds

Each selection has an `opening` price (the first price seen before kickoff, or `null` if none was recorded) and a `last_seen` price (the latest one).

<CodeGroup>
  ```bash curl theme={null}
  curl "https://api.thestatsapi.com/api/football/matches/mt_200199332/odds?bookmaker=bet365,pinnacle" \
    -H "Authorization: Bearer YOUR_API_KEY"
  ```

  ```javascript JavaScript theme={null}
  const res = await fetch(
    "https://api.thestatsapi.com/api/football/matches/mt_200199332/odds?bookmaker=bet365,pinnacle",
    { headers: { Authorization: `Bearer ${process.env.THESTATSAPI_API_KEY}` } }
  );
  const { data } = await res.json();
  for (const b of data.bookmakers) {
    const { home, draw, away } = b.markets.match_odds ?? {};
    console.log(b.bookmaker, home?.last_seen, draw?.last_seen, away?.last_seen);
  }
  ```
</CodeGroup>

Response (Arsenal v Leeds United, trimmed):

```json Response theme={null}
{
  "data": {
    "match_id": "mt_200199332",
    "bookmakers": [
      {
        "bookmaker": "Bet365",
        "markets": {
          "match_odds": {
            "home": { "opening": "1.380", "last_seen": "1.380" },
            "draw": { "opening": "4.500", "last_seen": "5.000" },
            "away": { "opening": "7.500", "last_seen": "7.500" }
          },
          "btts": {
            "yes": { "opening": "2.000", "last_seen": "2.050" },
            "no": { "opening": "1.750", "last_seen": "1.700" }
          },
          "total_goals": {
            "2.5": {
              "over": { "opening": "1.725", "last_seen": "1.800" },
              "under": { "opening": "2.075", "last_seen": "2.000" }
            }
          }
        }
      },
      {
        "bookmaker": "Pinnacle",
        "markets": {
          "match_odds": {
            "home": { "opening": "1.377", "last_seen": "1.413" },
            "draw": { "opening": "4.910", "last_seen": "4.870" },
            "away": { "opening": "7.620", "last_seen": "7.760" }
          }
        }
      }
    ]
  }
}
```

Markets include match result (full time and half time), both teams to score, goals, corners and cards lines, Asian and European handicaps, team totals, shots, correct score, to qualify and penalty specials. A market only appears when that bookmaker prices it, so check that a key exists before you read it. The endpoint works for upcoming and finished matches.

## Live (in-play) odds

Poll this during the match when `live_odds_available` is `true`. Bookmakers and markets come and go as books suspend and reopen.

<CodeGroup>
  ```bash curl theme={null}
  curl "https://api.thestatsapi.com/api/football/matches/mt_899703080/odds/live" \
    -H "Authorization: Bearer YOUR_API_KEY"
  ```

  ```javascript JavaScript theme={null}
  const res = await fetch(
    "https://api.thestatsapi.com/api/football/matches/mt_899703080/odds/live",
    { headers: { Authorization: `Bearer ${process.env.THESTATSAPI_API_KEY}` } }
  );
  if (res.status === 404) {
    console.log("No live odds for this match");
  } else {
    const { data } = await res.json();
    for (const b of data.bookmakers) console.log(b.bookmaker, b.markets.match_odds?.home?.live);
  }
  ```
</CodeGroup>

Response (West Ham United v Queens Park Rangers, in play, trimmed):

```json Response theme={null}
{
  "data": {
    "match_id": "mt_899703080",
    "bookmakers": [
      {
        "bookmaker": "Bet365",
        "markets": {
          "match_odds": {
            "home": { "live": "3.400" },
            "draw": { "live": "3.100" },
            "away": { "live": "2.250" }
          }
        }
      },
      {
        "bookmaker": "Betfair Exchange",
        "markets": {
          "match_odds": {
            "home": {
              "live": "3.650",
              "available_to_back": [{ "price": 3.65, "size": 1209.44 }, { "price": 3.6, "size": 1795.66 }],
              "available_to_lay": [{ "price": 3.7, "size": 480.78 }, { "price": 3.75, "size": 2184.81 }]
            }
          }
        }
      }
    ]
  }
}
```

Each price has a single `live` value. Betfair Exchange also returns the order book: up to 3 levels of `available_to_back` and `available_to_lay`, best price first. After full time this endpoint returns `404` ("Match is already completed"). See [Live matches](/docs/guides/live-matches) for polling tips.

## Player-prop odds

Use the v2 endpoint. It returns the latest prices grouped by bookmaker (Bet365 first), then by market.

<CodeGroup>
  ```bash curl theme={null}
  curl "https://api.thestatsapi.com/api/v2/football/matches/mt_200199332/odds/players?bookmaker=bet365" \
    -H "Authorization: Bearer YOUR_API_KEY"
  ```

  ```javascript JavaScript theme={null}
  const res = await fetch(
    "https://api.thestatsapi.com/api/v2/football/matches/mt_200199332/odds/players?bookmaker=bet365",
    { headers: { Authorization: `Bearer ${process.env.THESTATSAPI_API_KEY}` } }
  );
  const { data } = await res.json();
  const bet365 = data.bookmakers[0];
  const anytime = bet365?.markets.find((m) => m.name === "anytime_goalscorer");
  console.log(anytime?.players.slice(0, 3));
  ```
</CodeGroup>

Response (trimmed):

```json Response theme={null}
{
  "data": {
    "match_id": "mt_200199332",
    "home_team": { "id": "tm_9145", "name": "Arsenal" },
    "away_team": { "id": "tm_0256", "name": "Leeds United" },
    "kickoff_at": "2026-10-10T11:30:00.000Z",
    "bookmakers": [
      {
        "bookmaker": "Bet365",
        "markets": [
          {
            "name": "anytime_goalscorer",
            "players": [
              { "id": "pl_45857110", "name": "Kai Havertz", "odd": 2.4 },
              { "id": "pl_84500047", "name": "Viktor Gyokeres", "odd": 2.4 }
            ]
          },
          {
            "name": "player_shots_on_target",
            "players": [
              { "id": "pl_45126714", "name": "Bukayo Saka", "line": 0.5, "market_type": "Over", "odd": 1.2857 }
            ]
          }
        ]
      }
    ]
  }
}
```

* Markets cover goalscorers, shots, assists, cards, tackles, fouls, passes, goalkeeper saves and player of the match. Which ones you get depends on the bookmaker and the match.
* Line markets (such as `player_shots_on_target` or `player_passes`) have one entry per player, line and direction, with `line` and `market_type`. Other markets have neither field.
* Join players to other endpoints on `id`, not `name`: names can be spelled differently (here "Viktor Gyokeres", but "Viktor Gyökeres" in `/football/players`). `id` can be `null` when the player can't be matched to one ID; fall back to `name` then.

<Warning>
  `/football/matches/{match_id}/odds/players` (v1, Bet365 only, 5 markets) is deprecated. Use `/v2/football/matches/{match_id}/odds/players`.
</Warning>

## Check odds coverage before you build

Odds history varies by competition and season. Use the coverage endpoints to see what each season has. `opening_odds` and `closing_odds` are separate data types.

<CodeGroup>
  ```bash curl theme={null}
  curl "https://api.thestatsapi.com/api/coverage/leagues/comp_3039" \
    -H "Authorization: Bearer YOUR_API_KEY"
  ```

  ```javascript JavaScript theme={null}
  const res = await fetch("https://api.thestatsapi.com/api/coverage/leagues/comp_3039", {
    headers: { Authorization: `Bearer ${process.env.THESTATSAPI_API_KEY}` },
  });
  const { data } = await res.json();
  for (const s of data.seasons) {
    console.log(s.year, s.data_types.opening_odds.available, s.data_types.closing_odds.available);
  }
  ```
</CodeGroup>

Response (two seasons, trimmed):

```json Response theme={null}
{
  "data": {
    "id": "comp_3039",
    "name": "Premier League",
    "seasons": [
      {
        "id": "sn_8406098",
        "year": "26/27",
        "status": "in_progress",
        "events": { "finished": 50, "total": 100 },
        "data_types": {
          "odds": { "available": true, "covered_events": 50, "coverage_pct": 100 },
          "opening_odds": { "available": true, "covered_events": 50, "coverage_pct": 100 },
          "closing_odds": { "available": true, "covered_events": 50, "coverage_pct": 100 }
        }
      },
      {
        "id": "sn_6125938",
        "year": "25/26",
        "status": "complete",
        "events": { "finished": 380, "total": 380 },
        "data_types": {
          "odds": { "available": true, "covered_events": 380, "coverage_pct": 100 },
          "opening_odds": { "available": false, "covered_events": 0, "coverage_pct": 0 },
          "closing_odds": { "available": true, "covered_events": 380, "coverage_pct": 100 }
        }
      }
    ]
  }
}
```

So for the Premier League, 26/27 has opening and closing prices, while 25/26 has closing prices only. Older matches mostly have Bet365 closing prices only: `opening` is `null` and `last_seen` holds the closing price. Counts only include finished matches. See [Odds history](/docs/concepts/coverage#odds-history) for more.

To list every competition with a given odds data type, use `GET /coverage/leagues?data_type=closing_odds` (or `odds`, `opening_odds`). See [Coverage](/docs/concepts/coverage).

## API reference

* [Get match odds](/docs/api-reference/matches/odds)
* [Get live match odds](/docs/api-reference/matches/live-odds)
* [Get player-prop odds](/docs/api-reference/matches/player-odds)
* [Get coverage for a competition](/docs/api-reference/coverage/league) and [List coverage by competition](/docs/api-reference/coverage/leagues)


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