Sports Odds API Coverage

One API key, one JSON shape, every sport we carry. Pick a sport to see what the board holds right now.

735Tournaments with fixtures on the boardacross the sports below
8,739Fixtures, next 9 daysone window per sport
579Market familiesfrom /v4/markets

Measured live at 2026-09-09 21:53 UTC. This page is regenerated from the API, so the numbers move.

Get a free API key Read the docs

Sports

Quick start: sports and tournaments

Copy it as it stands. It was run against the live API before this page rendered.

import datetime as dt
import time

import requests

API_KEY = "YOUR_API_KEY"
BASE_URL = "https://api.oddspapi.io/v4"


def get(path, params):
    """The key is the query parameter apiKey, never a header.
    Read the status code first: a 429 body is valid JSON too."""
    query = dict(params, apiKey=API_KEY)
    for attempt in range(3):
        response = requests.get(f"{BASE_URL}/{path}", params=query, timeout=180)
        if response.status_code == 429:
            time.sleep(5 * (attempt + 1))
            continue
        if response.status_code == 404:
            return None
        response.raise_for_status()
        return response.json()
    raise RuntimeError("rate limited on /" + path)


# Every sport we carry, with the id the rest of the API keys on.
sports = get("sports", {})
print(len(sports), "sports")

# Tournaments for one sport. futureFixtures above zero proves a circuit is
# live. futureFixtures of zero proves nothing on its own, so confirm a
# circuit from /fixtures grouped on tournamentId.
tournaments = get("tournaments", {"sportId": 10})
live = [t for t in tournaments if t["futureFixtures"] > 0]
live.sort(key=lambda t: -t["futureFixtures"])
for tournament in live[:5]:
    print(tournament["tournamentId"], tournament["tournamentName"],
          tournament["categoryName"], tournament["futureFixtures"])

Run against the live API at 2026-09-09 21:53 UTC. First line of output: 69 sports

What each sport holds right now

Sport sportId Tournaments with fixtures Fixtures, next 9 days Market families Tournament pages
Football 10 548 5,936 152 Premier League, LaLiga, Bundesliga, Serie A, Ligue 1, UEFA Champions League, MLS, Brasileiro Serie A, Eredivisie, Saudi Pro League
Basketball 11 77 331 84 NBA, WNBA, Euroleague
Tennis 12 29 1,089 71 Tournaments run per event, so start from the sport page
Baseball 13 19 460 98 MLB
American Football 14 4 327 100 NFL, NCAA, Regular Season
Ice Hockey 15 40 496 145 NHL
MMA 20 5 18 5 Tournaments run per event, so start from the sport page
Esports 17, 18, 16 13 82 8 League of Legends, Counter-Strike 2

Every figure in this table was read from the API at 2026-09-09 21:53 UTC.

Questions developers ask

How do I list every sport?

GET /v4/sports with the key as the query parameter apiKey. Every other endpoint keys on the sportId it returns.

Is the free tier a different feed?

No. The free tier reads the same endpoints, the same fixture ids and the same JSON shape as a paid key. It differs on request volume.

Why do two bookmakers show the same price so often?

Because several distinct slugs ship one feed. cloneOf does not track all of it, so group on the price tuple before you average or count. Every board count on these pages carries both numbers, the count of bookmakers and the count of independent prices.

One key, every sport on this page

The same fixture id carries through /v4/fixtures, /v4/odds,
/v4/historical-odds, /v4/scores and /v4/settlements.

Get a free API key Read the docs