Odds API: Getting Started Guide

The Complete Guide


What you'll learn: How to authenticate with the OpticOdds API, discover available sports and markets, pull fixture data, retrieve real-time odds, stream live updates, monitor results, grade bets, and work with futures and player props. This guide covers every core (non-Copilot) endpoint in the OpticOdds v3 API.


What Is the OpticOdds API?

The OpticOdds API is a real-time sports odds aggregation platform that gives you access to odds from 100+ sportsbooks across 25+ sports — all through a single, unified API. Whether you're building a consumer-facing odds comparison tool, powering a trading desk, or feeding models for quantitative analysis, the API provides everything you need: fixtures, odds snapshots, live streaming, results, bet grading, futures, injuries, and more.

In plain terms: You query a single API and get back normalized odds from dozens of sportsbooks — in real time. No need to build and maintain individual integrations with each book.

What the API Gives You

  • Multi-sportsbook odds — Pull odds from up to 5 sportsbooks per request, across 100+ supported books
  • 25+ sports — Baseball, basketball, football, soccer, hockey, tennis, MMA, golf, and many more
  • Real-time streaming — SSE-based live odds and results streaming
  • Deep linking — Direct links into sportsbook apps (where available)
  • Bet grading — Automatic settlement (Won, Lost, Refunded, Half Won, Half Lost)
  • Futures markets — Season-long and tournament futures odds
  • Injuries data — Player injury reports filtered by sport, league, and team
  • Historical odds — Full price history with every movement tracked
  • Player props — Comprehensive player-level markets and results
  • Starting lineups — Pre-game lineup data for supported leagues
  • Limits data — Max stake information where available

How the API Works — The Big Picture

Here's the typical integration workflow:

1. Authenticate             → Use your API key via header or query param
2. Discover Resources       → Get available sports, leagues, sportsbooks, and markets
3. Pull Active Fixtures     → Find upcoming and live games with odds
4. Get Odds Snapshot        → Pull current odds for specific fixtures + sportsbooks
5. Stream Live Updates      → Listen for real-time odds changes via SSE
6. Monitor Results          → Stream live scores and game status changes
7. Grade Bets               → Settle bets using the grader endpoint

Step 1: Authentication

All API requests use your OpticOdds API license key. You can authenticate in two ways:

Option A: Header (recommended)

curl --location 'https://api.opticodds.com/api/v3/sports' \
  --header 'X-Api-Key: YOUR_API_KEY'

Option B: Query Parameter

curl 'https://api.opticodds.com/api/v3/sports?key=YOUR_API_KEY'

Base URL: https://api.opticodds.com/api/v3

Rate Limits

TierLimit
Standard endpoints2,500 requests / 15 seconds
Streaming endpoints250 requests / 15 seconds
Historical endpoints10 requests / 15 seconds

Step 2: Discover Your Resources

Before pulling odds, you need to know what's available. The API provides four discovery endpoints that return the full catalog of supported resources.


/sports — Get All Sports

Returns every sport OpticOdds supports, along with each sport's main markets.

GET https://api.opticodds.com/api/v3/sports

Example Response:

{
  "data": [
    {
      "id": "baseball",
      "name": "Baseball",
      "main_markets": [
        { "id": "moneyline", "name": "Moneyline", "numerical_id": 953 },
        { "id": "run_line", "name": "Run Line", "numerical_id": 1245 },
        { "id": "total_runs", "name": "Total Runs", "numerical_id": 1367 }
      ]
    },
    {
      "id": "basketball",
      "name": "Basketball",
      "main_markets": [
        { "id": "moneyline", "name": "Moneyline", "numerical_id": 953 },
        { "id": "point_spread", "name": "Point Spread", "numerical_id": 1172 },
        { "id": "total_points", "name": "Total Points", "numerical_id": 1358 }
      ]
    }
  ]
}

Currently supported sports include: Baseball, Basketball, Boxing, Cricket, Darts, eSports, Football (American), Golf, Hockey, Lacrosse, MMA, Motorsports, Rugby League, Rugby Union, Soccer, Table Tennis, Tennis, Volleyball, and more.


/leagues — Get All Leagues

Returns all leagues for a given sport, including region and gender information.

GET https://api.opticodds.com/api/v3/leagues?sport=basketball

Key fields in response:

  • id — League identifier (e.g., nba, ncaab, euroleague)
  • sport — Parent sport object
  • region — Geographic region (e.g., UNITED_STATES, INTERNATIONAL)
  • region_code — ISO region code (e.g., USA, INT)
  • gendermen or women

Example leagues for basketball: NBA, NCAAB, NCAAW, WNBA, Euroleague, Eurocup, NBA Summer League, and many international leagues.


/sportsbooks — Get All Sportsbooks

Returns every sportsbook OpticOdds has tracked, with active status and classification.

GET https://api.opticodds.com/api/v3/sportsbooks

Key fields in response:

  • id — Sportsbook identifier (e.g., draftkings, betmgm)
  • name — Display name
  • logo — URL to sportsbook logo
  • is_onshore — Whether the book is a licensed US/regulated sportsbook
  • is_active — Whether the sportsbook is currently being tracked

Major active sportsbooks include: bet365, BetMGM, BetRivers, Betsson, Betway, Bovada, bwin, Caesars, DraftKings, ESPN BET, Fanatics, BetMGM, Hard Rock, Novig, Betano, PrizePicks, Unibet, and 100+ more.


/markets — Get All Markets

Returns all available markets, filterable by sport, league, and sportsbook. This tells you exactly which prop and game-level markets are available and where.

GET https://api.opticodds.com/api/v3/markets?sport=football

Key fields in response:

  • id — Market identifier (e.g., moneyline, player_passing_yards)
  • name — Display name
  • numerical_id — Numeric identifier
  • sportsleaguessportsbooks — Nested hierarchy showing exactly which books offer this market in each league

Optional Parameters:

ParameterDescription
sportFilter by sport
leagueFilter by league
sportsbookFilter by sportsbook
markets_onlySet to true to return just market names without the nested hierarchy

Tip: Use /markets?sport=basketball&league=nba&markets_only=true to quickly see all available NBA markets.


/markets/active — Get Currently Active Markets

Returns only the markets that currently have live odds available.

GET https://api.opticodds.com/api/v3/markets/active?sport=basketball&league=nba

Step 3: Pull Active Fixtures

Once you know which sports and leagues you want, the next step is pulling fixtures (games).


/fixtures/active — Get Fixtures with Odds

Returns all fixtures that are currently active (not completed) and have or have had odds associated with them. This is the recommended starting point for most integrations.

GET https://api.opticodds.com/api/v3/fixtures/active?sport=football&league=nfl

Key difference from /fixtures: The /fixtures/active endpoint only returns fixtures that have ever had odds. The /fixtures endpoint returns all fixtures including those that may never have had odds (e.g., far-future scheduled games).


/fixtures — Get All Fixtures

Returns a paginated list of all fixtures. Supports historical lookback and future scheduling.

GET https://api.opticodds.com/api/v3/fixtures?league=nfl&start_date=2025-01-15

Important: You must pass at least one of: sport, league, id, or team_id.

Key Parameters:

ParameterDescription
sportSport ID or name
leagueLeague ID or name
idSpecific fixture ID(s)
team_idFilter by team
start_dateFixtures on this date (ISO 8601: YYYY-MM-DDTHH:MM:SSZ)
start_date_afterFixtures after this date
start_date_beforeFixtures before this date
statusFilter by status (unplayed, live, completed, cancelled)
is_liveSet to true for only live games
include_starting_lineupsSet to true to include lineup data
include_statsperform_idInclude StatsPerform IDs in source_ids
season_yearFilter by season year
season_weekFilter by season week
season_typeFilter by season type (e.g., Regular Season, Playoffs)
pagePage number for pagination

Date default: If you don't pass any date parameters, this endpoint defaults to fixtures from 3 days ago.

Example Response (NFL):

{
  "data": [
    {
      "id": "2025020987944BC9",
      "numerical_id": 142834,
      "game_id": "13602-17233-25-05",
      "start_date": "2025-02-09T23:30:00Z",
      "home_competitors": [
        {
          "id": "EDCC2866B795",
          "name": "Philadelphia Eagles",
          "abbreviation": "PHI",
          "logo": "https://cdn.opticodds.com/team-logos/football/106.png"
        }
      ],
      "away_competitors": [
        {
          "id": "2D71E5BA64A5",
          "name": "Kansas City Chiefs",
          "abbreviation": "KC",
          "logo": "https://cdn.opticodds.com/team-logos/football/96.png"
        }
      ],
      "status": "unplayed",
      "is_live": false,
      "sport": { "id": "football", "name": "Football" },
      "league": { "id": "nfl", "name": "NFL" },
      "has_odds": true,
      "venue_name": "Caesars Superdome",
      "venue_location": "New Orleans, LA, USA",
      "venue_neutral": true,
      "broadcast": "FOX | FOXD | TELE | TUBI",
      "result": null,
      "season_type": "Playoffs",
      "season_year": "2024",
      "season_week": "22"
    }
  ],
  "page": 1,
  "total_pages": 1
}

Key fields:

  • id — Unique fixture identifier (use this for odds requests)
  • game_id — Internal game reference
  • home_competitors / away_competitors — Team details with logos
  • statusunplayed, live, completed, cancelled
  • is_live — Boolean for live games
  • has_odds — Whether odds exist for this fixture
  • result — Score data (populated when game has started)
  • venue_name / venue_location / venue_neutral — Venue info
  • home_rotation_number / away_rotation_number — Rotation numbers
  • home_starter — Starting pitcher (baseball)
  • lineups — Starting lineups (when include_starting_lineups=true)

/fixtures/tournaments — Get Tournament Fixtures

For tournament-style competitions (e.g., golf, tennis Grand Slams), use this endpoint to retrieve fixtures grouped by tournament.


Step 4: Get an Odds Snapshot

With your fixture IDs in hand, pull the current odds across your chosen sportsbooks.

/fixtures/odds — Get Current Odds

GET https://api.opticodds.com/api/v3/fixtures/odds?fixture_id=BCE4E01B8D3D&sportsbook=DraftKings&sportsbook=BetMGM

Required Parameters:

  • At least one of: fixture_id, team_id, or player_id
  • At least 1 sportsbook (max 5 per request)

Optional Parameters:

ParameterDescription
marketFilter by market (e.g., moneyline, point_spread)
is_mainFilter for main lines only (true) or alternates only (false)
odds_formatAMERICAN (default), DECIMAL, PROBABILITY, MALAY, HONG_KONG, INDONESIAN
exclude_feesSet to true to exclude fee adjustments

Example Response:

{
  "data": [
    {
      "id": "BCE4E01B8D3D",
      "start_date": "2024-08-30T00:10:00Z",
      "home_competitors": [
        { "id": "4F11A5896C24", "name": "Houston Astros", "abbreviation": "HOU" }
      ],
      "away_competitors": [
        { "id": "E970E2EDDCAE", "name": "Kansas City Royals", "abbreviation": "KAN" }
      ],
      "status": "unplayed",
      "odds": [
        {
          "id": "60486-35183-2024-08-29-17:BetMGM:moneyline:houston_astros",
          "sportsbook": "BetMGM",
          "market": "Moneyline",
          "name": "Houston Astros",
          "is_main": true,
          "selection": "Houston Astros",
          "market_id": "moneyline",
          "selection_line": null,
          "player_id": null,
          "team_id": "4F11A5896C24",
          "price": -156,
          "timestamp": 1724865905.59815,
          "grouping_key": "default",
          "points": null,
          "deep_link": null,
          "limits": { "max": 500 }
        },
        {
          "id": "60486-35183-2024-08-29-17:BetMGM:moneyline:kansas_city_royals",
          "sportsbook": "BetMGM",
          "market": "Moneyline",
          "name": "Kansas City Royals",
          "is_main": true,
          "price": 132,
          "timestamp": 1724865905.59815,
          "limits": { "max": 500 }
        },
        {
          "id": "60486-35183-2024-08-29-17:BetMGM:run_line:houston_astros_-1_5",
          "sportsbook": "BetMGM",
          "market": "Run Line",
          "name": "Houston Astros -1.5",
          "is_main": true,
          "price": 140,
          "points": -1.5,
          "grouping_key": "default:-1.5"
        },
        {
          "id": "60486-35183-2024-08-29-17:BetMGM:total_runs:over_8",
          "sportsbook": "BetMGM",
          "market": "Total Runs",
          "name": "Over 8",
          "is_main": true,
          "selection_line": "over",
          "price": -110,
          "points": 8,
          "grouping_key": "default:8.0"
        }
      ]
    }
  ]
}

Key fields on each odd:

  • id — Unique odd identifier
  • sportsbook — Source sportsbook
  • market / market_id — Market name and ID
  • name — Full display name (e.g., "Houston Astros -1.5")
  • is_main — Whether this is the primary line
  • price — The odds value (format depends on odds_format)
  • points — The spread or total value (null for moneyline)
  • selection_lineover / under for totals
  • player_id — Player ID for player props
  • team_id — Team ID
  • timestamp — When this price was last updated
  • grouping_key — Groups related odds together (e.g., Over/Under pairs)
  • deep_link — Direct links into sportsbook apps (if enabled)
  • limits — Max stake information (where available)

Best Practice: Sportsbook Redundancy Use a basket of sportsbooks — not a single source — as the foundation of your data. Books experience their own downtime (maintenance, outages, etc.). A multi-book setup ensures individual source failures degrade gracefully rather than taking your system offline.


Step 5: Stream Live Odds Updates

Instead of polling /fixtures/odds repeatedly, use the SSE streaming endpoint to receive real-time odds updates passively.

/stream/odds/{sport} — Real-Time Odds Stream

GET https://api.opticodds.com/api/v3/stream/odds/basketball?sportsbook=DraftKings&sportsbook=BetMGM&league=NCAAB&market=Moneyline

Required Parameters:

  • {sport} — Path parameter (e.g., basketball, football)
  • sportsbook — At least one sportsbook (can pass multiple)

Optional Parameters:

ParameterDescription
leagueFilter by league(s)
fixture_idFilter by fixture(s)
marketFilter by market(s)
is_mainMain lines only
is_liveLive games only
odds_formatOdds format
last_entry_idResume from a specific point (for reconnection)
include_fixture_updatesSet to true to receive game status changes
include_deep_linkSet to true to include deep link data

Event Types

odds — Fired when an odd is posted or updated (unsuspended)

event: odds
id: 1730079534820-2
data: {"data":[{"fixture_id":"A69FA4D64518","sportsbook":"BetMGM","market":"1st Half Moneyline","name":"Philadelphia Eagles","price":-230,"is_main":true,...}],"entry_id":"1730079534820-2","type":"odds"}

locked-odds — Fired when an odd is suspended or taken off the board

event: locked-odds
id: 1730079527180-0
data: {"data":[{"fixture_id":"8BDC2E0FF301","sportsbook":"DraftKings","market":"Player Passing Yards","name":"Dak Prescott Over 247.5","price":-115,...}],"entry_id":"1730079527180-0","type":"locked-odds"}

fixture-status — Game time or status changes (requires include_fixture_updates=true)

event: fixture-status
data: {"data":{"fixture_id":"FB0D30DCDD6C","league":"ATP","new_start_date":"2024-08-28T20:30:00+00:00","old_start_date":"2024-08-28T20:20:00+00:00","new_status":null,"old_status":null}}

connected — Confirmation that stream is active

event: connected
data: ok go

ping — Heartbeat to keep connection alive

event: ping
data: 2024-08-28T18:57:49Z

Python Example

import requests
from requests.exceptions import ChunkedEncodingError
import json
import sseclient  # pip install sseclient-py

last_entry_id = None

while True:
    try:
        params = {
            "key": "YOUR_API_KEY",
            "sportsbook": ["DraftKings", "BetMGM", "Hard Rock"],
            "market": ["Moneyline"],
            "league": ["NCAAB"],
        }

        if last_entry_id:
            params["last_entry_id"] = last_entry_id

        r = requests.get(
            "https://api.opticodds.com/api/v3/stream/odds/basketball",
            params=params,
            stream=True,
        )
        client = sseclient.SSEClient(r)

        for event in client.events():
            if event.event == "odds":
                data = json.loads(event.data)
                last_entry_id = data.get("entry_id")
                print("odds:", data)
            elif event.event == "locked-odds":
                data = json.loads(event.data)
                last_entry_id = data.get("entry_id")
                print("locked-odds:", data)
            else:
                print(event.event, ":", event.data)

    except ChunkedEncodingError:
        print("Disconnected, attempting to reconnect...")
    except Exception as e:
        print("Error:", e)
        break

Node.js Example

const EventSource = require("eventsource"); // npm install eventsource

const url = "https://api.opticodds.com/api/v3/stream/odds/basketball";
const params = {
  key: "YOUR_API_KEY",
  sportsbook: ["DraftKings", "BetMGM", "Hard Rock"],
  market: ["Moneyline"],
  league: ["NCAAB"],
};

let lastEntryId = null;

function connectToStream() {
  const queryString = new URLSearchParams();
  queryString.append("key", params.key);
  params.sportsbook.forEach((sb) => queryString.append("sportsbook", sb));
  params.market.forEach((m) => queryString.append("market", m));
  params.league.forEach((l) => queryString.append("league", l));

  if (lastEntryId) {
    queryString.append("last_entry_id", lastEntryId);
  }

  const eventSource = new EventSource(`${url}?${queryString.toString()}`);

  eventSource.addEventListener("odds", function (event) {
    const data = JSON.parse(event.data);
    lastEntryId = data.entry_id;
    console.log("odds:", data);
  });

  eventSource.addEventListener("locked-odds", function (event) {
    const data = JSON.parse(event.data);
    lastEntryId = data.entry_id;
    console.log("locked-odds:", data);
  });

  eventSource.onerror = function (event) {
    console.error("EventSource failed:", event);
    eventSource.close();
    setTimeout(connectToStream, 1000);
  };
}

connectToStream();

Best Practices for Streaming

  • Group up to 10 leagues per connection — Don't overload a single stream
  • Always track last_entry_id — Use it for seamless reconnection without missing data
  • Handle disconnections gracefully — Wrap your listener in a retry loop
  • Use is_main=true — If you only care about primary lines, filter to reduce noise
  • Recommended storage key: fixture_id + sportsbook + market + name for multi-book tracking, or fixture_id + market + name for single-book

Understanding Main Line Changes

When a sportsbook moves the main line, the behavior depends on whether alternate lines exist:

No alternates: You'll receive locked-odds for the old line and odds for the new line.

With alternates: You'll receive odds events showing the new is_main assignments. No locked-odds are sent for the old main line — it simply becomes an alternate.


Step 6: Monitor Results

/stream/results/{sport} — Real-Time Results Stream

Listen for live score updates, game status changes, and in-play data via SSE.

GET https://api.opticodds.com/api/v3/stream/results/basketball?league=NBA

Event Types:

  • fixture-results — Score and stats updates during the game
  • connected — Stream is active
  • ping — Heartbeat

The results stream data format matches the /fixtures/results endpoint structure.


/fixtures/results — Get Results Snapshot

Pull the current results (scores, stats, in-play data) for specific fixtures.

GET https://api.opticodds.com/api/v3/fixtures/results?fixture_id=439A1AC1DBDB

Example Response (Baseball):

{
  "data": [
    {
      "sport": { "id": "baseball", "name": "Baseball" },
      "league": { "id": "mlb", "name": "MLB" },
      "fixture": {
        "id": "439A1AC1DBDB",
        "status": "live",
        "is_live": true
      },
      "scores": {
        "home": {
          "total": 0,
          "periods": { "period_1": 0, "period_2": 0, "period_3": 0 }
        },
        "away": {
          "total": 3,
          "periods": { "period_1": 0, "period_2": 3, "period_3": 0 }
        }
      },
      "in_play": {
        "period": "7",
        "clock": "Top",
        "balls": 0,
        "outs": 2,
        "strikes": 0,
        "runners": {
          "third": { "player_id": "19AA4BA7DD27", "player_name": "Colt Keith" },
          "second": { "player_id": "48805399AB84", "player_name": "Wenceel Perez" },
          "first": null
        },
        "batter": { "player_id": "8BDDD21FD738", "player_name": "Spencer Torkelson" }
      },
      "stats": {
        "home": [{ "period": "all", "stats": { "rbi": 0, "hits": 4, "runs": 0, "at_bats": 22 } }],
        "away": [{ "period": "all", "stats": { "rbi": 3, "hits": 9, "runs": 3, "at_bats": 28 } }]
      }
    }
  ]
}

Key fields:

  • scores — Period-by-period scoring breakdown
  • in_play — Live game state (period, clock, possession, down/distance for football, balls/strikes/outs for baseball, runners on base, etc.)
  • stats — Team-level stats (sport-specific)
  • extra — Decision/decision method (for combat sports)

/fixtures/player-results — Get Player Results

Pull individual player stat lines for specific fixtures.

GET https://api.opticodds.com/api/v3/fixtures/player-results?fixture_id=439A1AC1DBDB

Step 7: Grade Bets

/grader/odds — Settle a Bet

Given a fixture, market, and selection, the grader tells you whether the bet won, lost, or pushed.

GET https://api.opticodds.com/api/v3/grader/odds?fixture_id=B848DE682885&market=Total%20Rounds&name=Under%202.5

Required Parameters:

ParameterDescription
fixture_idThe fixture the bet applies to
marketThe market label (use display name, e.g., Moneyline, not moneyline)
nameThe selection name (e.g., Buffalo Bills, Over 10.5, Aaron Judge Under 10.5)

Optional Parameters:

  • player_id — Use if player names are ambiguous across sportsbooks
  • show_live_results — Get in-progress grading before game completion (use with caution)
  • void_substitutes — Handle substitute player scenarios

Example Response:

{
  "data": {
    "fixture_id": "B848DE682885",
    "away_team_display": "Tracy Cortez",
    "home_team_display": "Rose Namajunas",
    "status": "Completed",
    "away_score": 0,
    "home_score": 1,
    "market": "Total Rounds",
    "name": "Under 2.5",
    "result": "Lost"
  }
}

Possible Results:

ResultDescription
WonBet settled as a win
LostBet settled as a loss
RefundedBet settled as a push
PendingGame not completed or results not confirmed
Half WonApplies to Asian markets
Half LostApplies to Asian markets

Error Codes:

CodeMessage
100Game not found
104Game is still live
107Game has not started
108Game has not completed
109Game has been canceled
201Score data not found
212Unknown player

Tip: Pass the market label exactly as it appears in the odds response (e.g., Point Spread not point_spread).


Additional Endpoints

Futures

/futures — Get a list of available futures markets (e.g., "Super Bowl Winner", "MVP")

GET https://api.opticodds.com/api/v3/futures?sport=football&league=nfl

/futures/odds — Get odds for futures markets across sportsbooks

GET https://api.opticodds.com/api/v3/futures/odds?sportsbook=DraftKings&league=nfl&market=Super%20Bowl%20Winner

/grader/futures — Grade a futures bet

GET https://api.opticodds.com/api/v3/grader/futures?league=nfl&market=Super%20Bowl%20Winner&name=Kansas%20City%20Chiefs

Historical Odds

/fixtures/odds/historical — Get the full price history for specific odds

GET https://api.opticodds.com/api/v3/fixtures/odds/historical?id=ODDS_ID&sportsbook=DraftKings

Returns an array of every price change, lock, unlock, and settlement event with timestamps.

Rate limit: 10 requests per 15 seconds. Use this for analysis, not real-time tracking.


Injuries

/injuries — Get player injury reports

GET https://api.opticodds.com/api/v3/injuries?sport=football&league=nfl

Filter by sport, league, and team_id to get current injury reports.


Players

/players — Get player directory

GET https://api.opticodds.com/api/v3/players?sport=basketball&league=nba

Returns a paginated list of players with filtering options.


Squads / Rosters

/squads — Get team rosters

GET https://api.opticodds.com/api/v3/squads?team_id=TEAM_ID

Odds Formats

The API supports six odds formats. Set via the odds_format query parameter:

FormatExampleDescription
AMERICAN-110, +150US standard (default)
DECIMAL1.91, 2.50European standard
PROBABILITY0.524, 0.400Implied probability
MALAY-0.91, 0.50Malaysian format
HONG_KONG0.91, 1.50Hong Kong format
INDONESIAN-1.10, 1.50Indonesian format

Complete API Endpoint Reference

Common / Discovery

MethodEndpointDescription
GET/sportsList all sports
GET/sports/activeList sports with active odds
GET/leaguesList all leagues
GET/sportsbooksList all sportsbooks
GET/sportsbooks/last-polledLast polled time per sportsbook
GET/marketsList all markets
GET/markets/activeList markets with active odds
GET/playersList players
GET/squadsGet team rosters

Fixtures

MethodEndpointDescription
GET/fixturesGet all fixtures (paginated)
GET/fixtures/activeGet fixtures with odds
GET/fixtures/tournamentsGet tournament fixtures

Odds

MethodEndpointDescription
GET/fixtures/oddsGet current odds snapshot
GET/fixtures/odds/historicalGet full price history

Results & Scores

MethodEndpointDescription
GET/fixtures/resultsGet fixture results/scores
GET/fixtures/player-resultsGet player stat lines

Streaming (SSE)

MethodEndpointDescription
GET/stream/odds/{sport}Real-time odds stream
GET/stream/results/{sport}Real-time results stream

Grading

MethodEndpointDescription
GET/grader/oddsGrade a bet
GET/grader/futuresGrade a futures bet

Futures

MethodEndpointDescription
GET/futuresList available futures
GET/futures/oddsGet futures odds

Injuries

MethodEndpointDescription
GET/injuriesGet injury reports

Parlay (SGP)

MethodEndpointDescription
POST/parlay/oddsPrice a same game parlay

Recommended Integration Path

Here's the order we recommend for building your integration:

1. Authentication          → Confirm your API key works with GET /sports
2. Discovery               → Pull sports, leagues, sportsbooks, and markets
3. Fixtures                → Pull active fixtures for your target leagues
4. Odds Snapshot           → Pull odds from 2-3 sportsbooks per fixture
5. Streaming               → Set up SSE stream for live odds updates
6. Results                 → Stream or poll for scores and game state
7. Grading                 → Wire up bet settlement via the grader
8. Futures                 → Add futures markets if applicable
9. Historical              → Add historical analysis if needed

Best Practices

  • Use multiple sportsbooks — Always pass 2-3+ sportsbooks per odds request for redundancy
  • Track last_entry_id — Store it on every stream event for seamless reconnection
  • Use is_main=true — When you only care about primary lines, this dramatically reduces data volume
  • Group streams by sport — Use separate stream connections per sport, up to 10 leagues each
  • Paginate fixtures — Use the page parameter and check total_pages in responses
  • Use fixture IDs — Store fixture IDs from /fixtures/active and use them for odds, results, and grading
  • Handle locked-odds — When you receive a locked-odds event, remove that line from your active offerings
  • Date format — Always use ISO 8601 (YYYY-MM-DDTHH:MM:SSZ) for date parameters
  • Market labels for grading — The grader expects display names (e.g., Point Spread) not IDs (e.g., point_spread)

Glossary

TermDefinition
FixtureA single game or match between two competitors
MarketA betting category (e.g., Moneyline, Point Spread, Total Points)
Main LineThe primary/given line for a market (e.g., the consensus spread)
Alternate LineNon-primary lines (e.g., alternate spreads)
SelectionThe specific pick within a market (e.g., "Buffalo Bills", "Over 45.5")
Selection Lineover or under for total markets
PointsThe spread or total value (e.g., -6.5, 45.5)
Grouping KeyGroups related odds (e.g., an Over/Under pair share the same grouping key)
Deep LinkA URL that opens directly in a sportsbook's app
LimitsMaximum stake a sportsbook will accept on a given line
SSEServer-Sent Events — a protocol for receiving real-time server push updates
Locked OddsAn odd that has been suspended or taken off the board
is_onshoreWhether a sportsbook is a licensed/regulated operator
Rotation NumberA standardized number assigned to teams by Las Vegas sportsbooks
Entry IDA stream checkpoint used for reconnection (last_entry_id)

Need Help?


This guide covers the standard OpticOdds API endpoints. For automated odds generation with custom pricing rules, see the Getting Started with Copilot guide.