Quick start

Odds API docs

Make one server-side request first. Then move through coverage, events, streaming updates, limits, caching, and endpoint groups as needed.

Step 1

Choose a plan

Start free with an API key or choose a paid USD plan for higher volume.

Step 2

Get your API key

Use your key in the docs or your own requests.

Step 3

Call the API

Start with meta, events, odds, bets, and results.

curl -H "X-API-Key: $ODDS_API_KEY" \
  "https://api.odds-api.net/v1/events?sport=basketball&league=NBA&limit=25"
Base URLhttps://api.odds-api.net/v1 AuthX-API-Key FormatJSON responses, SSE streams, WebSocket streams

How to use these docs

Use the guide pages for integration decisions. Use the endpoint pages for live parameters, response codes, response body samples, stream formats, and request examples generated from the current OpenAPI schema.

Coverage

Discover what exists before requesting odds.

Build filters from coverage and metadata endpoints. This keeps UI filters honest and prevents background jobs from polling unsupported combinations.

/v1/coverage

Coverage snapshot

Use this for buyer-facing or internal coverage views across bookmakers, sports, leagues, and markets.

/v1/sports and /v1/leagues

Sport and league filters

Load these before event requests so your UI and jobs only ask for supported competitions.

/v1/bookmakers

Bookmaker filters

Inspect bookmaker keys, display names, countries, and availability before requesting odds.

Events and odds

Page event lists, then load odds snapshots.

Keep event windows narrow, process pagination idempotently, and store freshness fields from odds snapshots so stale prices are visible.

/v1/events

Upcoming sports events

Use sport, league, start-time, status, limit, and cursor filters. Keep windows narrow in production.

/v1/racing/events

Racing events

Use shorter polling windows because racing schedules can move close to jump.

/v1/events/{event_id}/odds/snapshot

Initial odds state

Start every hot event view with a snapshot before polling deltas or opening a stream.

1

Authenticate server-side

Send X-API-Key from your backend. Do not expose keys in browser-visible code.

2

Discover coverage

Build filters from coverage, sports, leagues, bookmakers, and bookmaker country routes.

3

Page events

Call event routes with a narrow time window, limit, and cursor until next_cursor is empty.

4

Load odds snapshots

Fetch an event odds snapshot for initial state and store as_of_ts_ms, ttl_seconds, next_cursor, and resume.

5

Stream hot updates

For realtime products, connect to SSE or WebSocket streams after the snapshot and resume with since on reconnect.

6

Query history and results

Use history endpoints for line movement and result routes after events finish. Back off when data is settled.

SSE and WebSocket

Use streams after the initial snapshot.

Streams are best for hot odds views and alerting products. Snapshot first, apply deltas, and resync when the stream tells you the resume token is no longer available.

GET /v1/events/{event_id}/odds/snapshot
GET /v1/events/{event_id}/odds/stream?since=<resume>&catchup=true
GET /v1/events/{event_id}/odds/ws?since=<resume>&catchup=true
  1. Fetch a snapshot first and persist the `resume` token with the cached event state.
  2. Connect to `/stream` with Server-Sent Events or `/ws` with WebSockets. Use the same filters as the snapshot.
  3. Handle `delta` by applying changes idempotently. Store the newest `resume` after each accepted message.
  4. Treat `heartbeat` as a liveness signal. If no heartbeat or data arrives within your timeout, reconnect.
  5. On disconnect, reconnect with `since=<last_resume>` and `catchup=true` using jittered exponential backoff.
  6. On `resync`, reload the snapshot because the resume token is no longer available.

Rate limits

Poll slower by default and treat 429s as a control signal.

Prefer streams for realtime odds. When polling is required, keep filters narrow and let rate-limit headers shape worker behavior.

Surface Starting interval Production notes
Sports, leagues, bookmakers 6-24 hours Coverage changes slowly. Refresh daily unless you are syncing a new catalog view.
Sports event lists 5-15 minutes Use tighter 1-5 minute polling only for active leagues or near-start windows.
Racing event lists 1-5 minutes Racing schedules change closer to jump. Keep the time window narrow.
Odds snapshots 60-120 seconds Use 15-30 seconds only for priority events when streams are not available.
Betting opportunity snapshots 30-120 seconds Poll faster only for alerting products with strict quota controls.
Results 1-5 minutes after start After final status appears, stop hot polling or move to a long retention refresh.

429 backoff

  • On HTTP 429, wait for `Retry-After` when present before sending another request to that route/key.
  • When `Retry-After` is absent, start around 2 seconds and double up to about 60 seconds with random jitter.
  • Use `X-RateLimit-Limit`, `X-RateLimit-Remaining`, and `X-RateLimit-Bucket` when present to tune callers.
  • If `/usage` shows the monthly API-credit quota is exhausted, stop retry loops and alert the account owner.
  • Reduce polling breadth first: narrower leagues, fewer events, fewer bookmakers, and smaller page sizes.

Cache and pages

Cache by request shape and make cursors durable.

Use last-known-good odds with timestamps for UI surfaces, and only advance pagination checkpoints after a page is processed successfully.

Cache strategy

Key caches by request shape

Include endpoint path, event ID, normalized filters, page cursor, and API product context in the cache key.

Respect freshness fields

Use `ttl_seconds` when present. Always display or store `as_of_ts_ms` so stale odds are obvious.

Use streams to update hot caches

Apply stream deltas to the cached snapshot, but fall back to a fresh snapshot after `resync` or parse failure.

Prefer stale-while-revalidate for UI

Show the last good snapshot with a visible timestamp while refreshing in the background.

Pagination

  • Pass `limit` within `/limits` response caps.
  • Keep all filters identical between pages.
  • Pass `next_cursor` into the next request's `cursor` parameter.
  • Stop when `next_cursor` is missing, null, empty, or `0`.
  • Persist the last completed cursor only after the page is processed successfully.

History and errors

Separate historical analysis from current odds.

Line movement is useful for audit and backtesting. Current odds can still be stale, suspended, limited, or unavailable.

History queries

  • Enable History Lite or History Pro before calling history endpoints on v2-priced API keys.
  • Start from a current odds snapshot and copy the exact `selection_key` for the line you want to chart.
  • Use `from_ts` and `to_ts` ISO8601 UTC windows for bounded history queries.
  • Use `bookmakers`, `market_group_id`, `price_type`, and `limit_points_per_bookmaker` to keep responses small.
  • Store history separately from live caches because it is an audit/backtesting view, not the current tradable price.

Failure modes

400 Fix invalid filters, cursors, timestamps, or request shape.
401 API key is missing or invalid. Rotate or reconfigure the key.
403 The key is valid but lacks the plan, product, bookmaker, stream, racing, or strategy access.
404 The event, race, result, or selection is not available in the current public surface.
429 Back off, honor `Retry-After`, check `/usage`, and reduce request volume.
5xx Retry with backoff and keep the last good cached data marked with its timestamp.
Stream close Reconnect with `since`; reload the snapshot if the stream sends `resync`.
Empty or stale data Show unavailable/stale state instead of treating missing odds as valid prices.

Endpoint group

Start here

API identity, base URL, authentication, and reference links.

Base URLhttps://api.odds-api.net/v1 Version1.0.0 SourceLive OpenAPI
GET API metadata /

Returns the API name, version, OpenAPI document URL, and hosted reference URL.

Public endpoint Handle HTTP 429 with backoff and avoid tight polling loops.

Request example

curl -H "X-API-Key: $ODDS_API_KEY" "https://api.odds-api.net/v1/"

Responses

200 Successful Response

application/json · object

Generated sample

{
  "name": "Odds API",
  "version": "1.0.0",
  "openapi": "/v1/openapi.json",
  "reference": "/v1/reference"
}
400 Invalid request parameters or body.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
401 Missing or invalid credentials.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
403 Credentials are valid but do not allow this resource.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
404 Resource was not found.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
429 Rate limit exceeded.

application/json · value

Retry-After
integer

Seconds to wait before retrying when supplied by the limiter.

X-RateLimit-Limit
integer

Request bucket capacity for the active limiter bucket when supplied.

X-RateLimit-Remaining
integer

Approximate remaining requests in the active limiter bucket when supplied.

X-RateLimit-Bucket
string

Limiter bucket name that produced the response when supplied.

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
500 Unexpected server error.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}

Endpoint group

Status

Buyer-facing API availability, latency, stream health, and rate-limit health.

Base URLhttps://api.odds-api.net/v1 Version1.0.0 SourceLive OpenAPI
GET Public health summary /status

Returns a sanitized public status summary for buyer-facing pages. The response includes recent component availability, latency percentiles, 5xx error rate, stream health, and rate-limit health without exposing internal service names, infrastructure metrics, bookmaker details, raw traffic volume, or incident history.

Public endpoint Handle HTTP 429 with backoff and avoid tight polling loops.

Request example

curl -H "X-API-Key: $ODDS_API_KEY" "https://api.odds-api.net/v1/status"

Responses

200 Successful Response

application/json · object

API status: Public health summary

{
  "status": "operational",
  "as_of": "2026-04-29T10:25:00Z",
  "window_seconds": 300,
  "components": [
    {
      "id": "rest_api",
      "name": "REST API",
      "status": "operational",
      "metrics": {
        "uptime_pct": 100.0,
        "p50_ms": 24.0,
        "p95_ms": 410.0,
        "p99_ms": 846.0,
        "error_rate_pct": 0.02
      }
    }
  ],
  "rate_limits": {
    "status": "operational",
    "throttled_pct": 0.4
  },
  "source": {
    "fresh": true,
    "age_seconds": 18
  }
}
400 Invalid request parameters or body.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
401 Missing or invalid credentials.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
403 Credentials are valid but do not allow this resource.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
404 Resource was not found.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
429 Rate limit exceeded.

application/json · value

Retry-After
integer

Seconds to wait before retrying when supplied by the limiter.

X-RateLimit-Limit
integer

Request bucket capacity for the active limiter bucket when supplied.

X-RateLimit-Remaining
integer

Approximate remaining requests in the active limiter bucket when supplied.

X-RateLimit-Bucket
string

Limiter bucket name that produced the response when supplied.

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
500 Unexpected server error.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}

Endpoint group

Account

Current API identity, usage counters, and contract limits.

Base URLhttps://api.odds-api.net/v1 Version1.0.0 SourceLive OpenAPI
GET Current identity /me

Returns the authenticated API identity and enabled product capabilities for the supplied key.

Auth: X-API-Key Handle HTTP 429 with backoff and avoid tight polling loops.

Request example

curl -H "X-API-Key: $ODDS_API_KEY" "https://api.odds-api.net/v1/me"

Responses

200 Successful Response

application/json · object

Generated sample

{
  "method": "api_key",
  "client_id": "string",
  "capabilities": {},
  "membership_tier": 123
}
400 Invalid request parameters or body.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
401 Missing or invalid credentials.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
403 Credentials are valid but do not allow this resource.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
404 Resource was not found.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
429 Rate limit exceeded.

application/json · value

Retry-After
integer

Seconds to wait before retrying when supplied by the limiter.

X-RateLimit-Limit
integer

Request bucket capacity for the active limiter bucket when supplied.

X-RateLimit-Remaining
integer

Approximate remaining requests in the active limiter bucket when supplied.

X-RateLimit-Bucket
string

Limiter bucket name that produced the response when supplied.

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
500 Unexpected server error.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
GET Usage /usage

Returns quota and usage counters for the supplied API key. New odds-api.net pricing uses API credits rather than raw request counts. Production clients should check this endpoint when 429 responses persist so quota exhaustion does not become an infinite retry loop.

Auth: X-API-Key Handle HTTP 429 with backoff and avoid tight polling loops.

Request example

curl -H "X-API-Key: $ODDS_API_KEY" "https://api.odds-api.net/v1/usage"

Responses

200 Successful Response

application/json · object

Account: Usage

{
  "period_start_utc": "2026-05-01T00:00:00Z",
  "period_end_utc": "2026-06-01T00:00:00Z",
  "plan": "live",
  "pricing_model": "odds_api_net_v2",
  "api_credits_used": 18420,
  "api_credits_limit": 20000000,
  "exceeded": false
}
400 Invalid request parameters or body.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
401 Missing or invalid credentials.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
403 Credentials are valid but do not allow this resource.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
404 Resource was not found.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
429 Rate limit exceeded.

application/json · value

Retry-After
integer

Seconds to wait before retrying when supplied by the limiter.

X-RateLimit-Limit
integer

Request bucket capacity for the active limiter bucket when supplied.

X-RateLimit-Remaining
integer

Approximate remaining requests in the active limiter bucket when supplied.

X-RateLimit-Bucket
string

Limiter bucket name that produced the response when supplied.

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
500 Unexpected server error.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
GET Limits /limits

Returns contract-level API-credit, request, stream, add-on, and response limits that clients should respect. Use this to cap page sizes, snapshot sizes, stream heartbeat settings, and stream batch sizes before starting high-volume jobs.

Auth: X-API-Key Handle HTTP 429 with backoff and avoid tight polling loops.

Request example

curl -H "X-API-Key: $ODDS_API_KEY" "https://api.odds-api.net/v1/limits"

Responses

200 Successful Response

application/json · object

Account: Limits

{
  "responses": {
    "events_limit_max": 1000,
    "odds_snapshot_limit_max": 10000,
    "bets_snapshot_limit_max": 20000
  },
  "sse": {
    "heartbeat_sec_min": 5,
    "heartbeat_sec_max": 120,
    "max_batch_default": 500
  }
}
400 Invalid request parameters or body.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
401 Missing or invalid credentials.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
403 Credentials are valid but do not allow this resource.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
404 Resource was not found.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
429 Rate limit exceeded.

application/json · value

Retry-After
integer

Seconds to wait before retrying when supplied by the limiter.

X-RateLimit-Limit
integer

Request bucket capacity for the active limiter bucket when supplied.

X-RateLimit-Remaining
integer

Approximate remaining requests in the active limiter bucket when supplied.

X-RateLimit-Bucket
string

Limiter bucket name that produced the response when supplied.

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
500 Unexpected server error.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}

Endpoint group

Catalog

Supported sports, leagues, bookmakers, and approximate market coverage.

Base URLhttps://api.odds-api.net/v1 Version1.0.0 SourceLive OpenAPI
GET Sports /sports

Lists sports with event and odds coverage.

Auth: X-API-Key Handle HTTP 429 with backoff and avoid tight polling loops.

Request example

curl -H "X-API-Key: $ODDS_API_KEY" "https://api.odds-api.net/v1/sports"

Responses

200 Successful Response

application/json · object

Generated sample

{
  "items": [
    "string"
  ]
}
400 Invalid request parameters or body.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
401 Missing or invalid credentials.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
403 Credentials are valid but do not allow this resource.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
404 Resource was not found.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
429 Rate limit exceeded.

application/json · value

Retry-After
integer

Seconds to wait before retrying when supplied by the limiter.

X-RateLimit-Limit
integer

Request bucket capacity for the active limiter bucket when supplied.

X-RateLimit-Remaining
integer

Approximate remaining requests in the active limiter bucket when supplied.

X-RateLimit-Bucket
string

Limiter bucket name that produced the response when supplied.

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
500 Unexpected server error.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
GET Leagues /leagues

Lists available leagues. Pass `sport` to narrow the response.

Auth: X-API-Key Handle HTTP 429 with backoff and avoid tight polling loops.

Request example

curl -H "X-API-Key: $ODDS_API_KEY" "https://api.odds-api.net/v1/leagues?sport=basketball"

Parameters

Query

sport
string

Sport filter. Use `/sports` to discover supported values.

Responses

200 Successful Response

application/json · object

Generated sample

{
  "items": [
    "string"
  ]
}
400 Invalid request parameters or body.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
401 Missing or invalid credentials.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
403 Credentials are valid but do not allow this resource.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
404 Resource was not found.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
429 Rate limit exceeded.

application/json · value

Retry-After
integer

Seconds to wait before retrying when supplied by the limiter.

X-RateLimit-Limit
integer

Request bucket capacity for the active limiter bucket when supplied.

X-RateLimit-Remaining
integer

Approximate remaining requests in the active limiter bucket when supplied.

X-RateLimit-Bucket
string

Limiter bucket name that produced the response when supplied.

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
500 Unexpected server error.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
GET Bookmakers /bookmakers

Lists active bookmakers accepted by bookmaker filters across odds and betting endpoints. Each item includes the country codes where that bookmaker is available. Pass `country_code=AU` or `country_code=AU,UK` to filter the catalog.

Auth: X-API-Key Handle HTTP 429 with backoff and avoid tight polling loops.

Request example

curl -H "X-API-Key: $ODDS_API_KEY" "https://api.odds-api.net/v1/bookmakers"

Parameters

Query

country_code
string

Comma-separated country code filter, for example `AU` or `AU,UK`.

Responses

200 Successful Response

application/json · object

Catalog: Bookmakers

{
  "items": [
    {
      "bookmaker": "bet365",
      "country_codes": [
        "AU",
        "UK"
      ]
    },
    {
      "bookmaker": "pinnacle",
      "country_codes": [
        "US"
      ]
    }
  ]
}
400 Invalid request parameters or body.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
401 Missing or invalid credentials.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
403 Credentials are valid but do not allow this resource.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
404 Resource was not found.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
429 Rate limit exceeded.

application/json · value

Retry-After
integer

Seconds to wait before retrying when supplied by the limiter.

X-RateLimit-Limit
integer

Request bucket capacity for the active limiter bucket when supplied.

X-RateLimit-Remaining
integer

Approximate remaining requests in the active limiter bucket when supplied.

X-RateLimit-Bucket
string

Limiter bucket name that produced the response when supplied.

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
500 Unexpected server error.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
GET Bookmaker countries /bookmakers/countries

Lists country codes represented in the active bookmaker catalog and the bookmakers available in each country.

Auth: X-API-Key Handle HTTP 429 with backoff and avoid tight polling loops.

Request example

curl -H "X-API-Key: $ODDS_API_KEY" "https://api.odds-api.net/v1/bookmakers/countries"

Responses

200 Successful Response

application/json · object

Catalog: Bookmaker countries

{
  "items": [
    {
      "country_code": "AU",
      "country": "Australia",
      "bookmakers": [
        "bet365",
        "sportsbet"
      ]
    },
    {
      "country_code": "UK",
      "country": "United Kingdom",
      "bookmakers": [
        "bet365"
      ]
    }
  ]
}
400 Invalid request parameters or body.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
401 Missing or invalid credentials.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
403 Credentials are valid but do not allow this resource.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
404 Resource was not found.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
429 Rate limit exceeded.

application/json · value

Retry-After
integer

Seconds to wait before retrying when supplied by the limiter.

X-RateLimit-Limit
integer

Request bucket capacity for the active limiter bucket when supplied.

X-RateLimit-Remaining
integer

Approximate remaining requests in the active limiter bucket when supplied.

X-RateLimit-Bucket
string

Limiter bucket name that produced the response when supplied.

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
500 Unexpected server error.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
GET Coverage /coverage

Returns public bookmaker, sport, league, and recently observed market coverage. Market records are approximate and based on normalized odds lines seen in the configured lookback window, not a guarantee that every market is available for every event at request time.

Public endpoint Handle HTTP 429 with backoff and avoid tight polling loops.

Request example

curl -H "X-API-Key: $ODDS_API_KEY" "https://api.odds-api.net/v1/coverage?sport=basketball&league=NBA"

Parameters

Query

bookmaker
string

Canonical bookmaker filter. Use `/bookmakers` or `/coverage` to discover supported keys.

sport
string

Sport filter. Use `/sports` to discover supported values.

league
string

League filter. Use `/leagues?sport=...` to discover supported values.

country_code
string

Comma-separated country code filter, for example `AU` or `AU,UK`.

lookback_days
integer

Number of days of recently observed approximate market coverage to include. Maximum is 90.

Responses

200 Successful Response

application/json · object

Catalog: Coverage

{
  "as_of": "2026-04-29T10:25:00Z",
  "bookmakers": [
    {
      "bookmaker": "bet365",
      "country_codes": [
        "AU",
        "UK"
      ]
    },
    {
      "bookmaker": "sportsbet",
      "country_codes": [
        "AU"
      ]
    }
  ],
  "sports": [
    "basketball",
    "rugby league"
  ],
  "leagues": [
    {
      "sport": "basketball",
      "league": "NBA"
    },
    {
      "sport": "rugby league",
      "league": "NRL"
    }
  ],
  "markets": [
    {
      "bookmaker": "bet365",
      "sport": "basketball",
      "league": "NBA",
      "bet_type": "moneyline",
      "last_seen_at": "2026-04-29T10:20:00Z",
      "sample_event_id": "3704597661"
    },
    {
      "bookmaker": "sportsbet",
      "sport": "rugby league",
      "league": "NRL",
      "bet_type": "total",
      "metric": "tries",
      "last_seen_at": "2026-04-29T10:18:00Z",
      "sample_event_id": "3704597662"
    }
  ],
  "source": {
    "markets_are_approximate": true,
    "lookback_days": 30
  }
}
400 Invalid request parameters or body.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
401 Missing or invalid credentials.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
403 Credentials are valid but do not allow this resource.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
404 Resource was not found.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
429 Rate limit exceeded.

application/json · value

Retry-After
integer

Seconds to wait before retrying when supplied by the limiter.

X-RateLimit-Limit
integer

Request bucket capacity for the active limiter bucket when supplied.

X-RateLimit-Remaining
integer

Approximate remaining requests in the active limiter bucket when supplied.

X-RateLimit-Bucket
string

Limiter bucket name that produced the response when supplied.

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
500 Unexpected server error.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}

Endpoint group

Sports events

Upcoming and live sports events plus event metadata.

Base URLhttps://api.odds-api.net/v1 Version1.0.0 SourceLive OpenAPI
GET Search /events

Searches sports events by sport, league, team, time window, status, bookmaker coverage, and pagination cursor. For production polling, use bounded time windows, keep filters stable across pages, and pass `next_cursor` back as `cursor` until there is no next cursor.

Auth: X-API-Key Handle HTTP 429 with backoff and avoid tight polling loops.

Request example

curl -H "X-API-Key: $ODDS_API_KEY" "https://api.odds-api.net/v1/events?sport=basketball&league=NBA&limit=25"

Parameters

Query

sport
string

Sport filter. Use `/sports` to discover supported values.

league
string

League filter. Use `/leagues?sport=...` to discover supported values.

start_from
integer

Unix seconds lower bound for event start time. Use bounded windows in production polling.

start_to
integer

Unix seconds upper bound for event start time. Keep windows narrow for hot sync jobs.

cursor
string

Pagination cursor from the previous `next_cursor`. Keep filters identical between pages.

limit
integer

Maximum items to return. Respect the caps returned by `/limits`.

include_bookmaker_ids
boolean

When true, include bookmaker-to-odds-data IDs and preview ID maps on event responses.

include_source
boolean

When true, include per-line/per-bookmaker provenance and capture metadata. Top-level freshness fields are always kept.

include_opportunity_counts
boolean

Responses

200 Successful Response

application/json · object

Sports events: Search

{
  "items": [
    {
      "event_id": "3704597661",
      "sport": "rugby-league",
      "league": "NRL",
      "start_time": 1760000000,
      "home_team": "Home",
      "away_team": "Away",
      "bookmakers": {
        "bet365": "odds-doc-id"
      }
    }
  ],
  "next_cursor": null,
  "count": 1
}
400 Invalid request parameters or body.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
401 Missing or invalid credentials.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
403 Credentials are valid but do not allow this resource.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
404 Resource was not found.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
429 Rate limit exceeded.

application/json · value

Retry-After
integer

Seconds to wait before retrying when supplied by the limiter.

X-RateLimit-Limit
integer

Request bucket capacity for the active limiter bucket when supplied.

X-RateLimit-Remaining
integer

Approximate remaining requests in the active limiter bucket when supplied.

X-RateLimit-Bucket
string

Limiter bucket name that produced the response when supplied.

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
500 Unexpected server error.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
GET Event details /events/{event_id}

Returns the current event record for a canonical sports event ID.

Auth: X-API-Key Handle HTTP 429 with backoff and avoid tight polling loops.

Request example

curl -H "X-API-Key: $ODDS_API_KEY" "https://api.odds-api.net/v1/events/3704597661"

Parameters

Path

event_id required
string

Canonical event or race identifier from an event list response.

Query

include_links
boolean

When true, include bookmaker/deep-link fields such as match links and racing links.

include_raw_payload
boolean

When true, include raw stored payload/data objects where the endpoint exposes them.

include_source
boolean

When true, include per-line/per-bookmaker provenance and capture metadata. Top-level freshness fields are always kept.

include_bookmaker_ids
boolean

When true, include bookmaker-to-odds-data IDs and preview ID maps on event responses.

include_debug_ids
boolean

When true, include internal/subgroup/opposing IDs useful for reconciliation.

Responses

200 Successful Response

application/json · object

Generated sample

{
  "event_id": "3704597661",
  "data": {}
}
400 Invalid request parameters or body.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
401 Missing or invalid credentials.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
403 Credentials are valid but do not allow this resource.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
404 Resource was not found.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
429 Rate limit exceeded.

application/json · value

Retry-After
integer

Seconds to wait before retrying when supplied by the limiter.

X-RateLimit-Limit
integer

Request bucket capacity for the active limiter bucket when supplied.

X-RateLimit-Remaining
integer

Approximate remaining requests in the active limiter bucket when supplied.

X-RateLimit-Bucket
string

Limiter bucket name that produced the response when supplied.

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
500 Unexpected server error.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
GET Bookmaker coverage /events/{event_id}/bookmakers

Lists bookmakers currently attached to a sports event.

Auth: X-API-Key Handle HTTP 429 with backoff and avoid tight polling loops.

Request example

curl -H "X-API-Key: $ODDS_API_KEY" "https://api.odds-api.net/v1/events/3704597661/bookmakers"

Parameters

Path

event_id required
string

Canonical event or race identifier from an event list response.

Responses

200 Successful Response

application/json · object

Generated sample

{
  "event_id": "3704597661",
  "items": [
    "string"
  ]
}
400 Invalid request parameters or body.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
401 Missing or invalid credentials.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
403 Credentials are valid but do not allow this resource.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
404 Resource was not found.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
429 Rate limit exceeded.

application/json · value

Retry-After
integer

Seconds to wait before retrying when supplied by the limiter.

X-RateLimit-Limit
integer

Request bucket capacity for the active limiter bucket when supplied.

X-RateLimit-Remaining
integer

Approximate remaining requests in the active limiter bucket when supplied.

X-RateLimit-Bucket
string

Limiter bucket name that produced the response when supplied.

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
500 Unexpected server error.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}

Endpoint group

Sports odds

Sports odds snapshots, line movement, Server-Sent Events, and WebSocket updates.

Base URLhttps://api.odds-api.net/v1 Version1.0.0 SourceLive OpenAPI
GET Snapshot /events/{event_id}/odds/snapshot

Returns the current odds lines for one event. Use filters to narrow bookmakers, market types, market keys, and periods. Cache by request shape, display `as_of_ts_ms`, respect `ttl_seconds` when present, page with `cursor` and `next_cursor`, and persist `resume` when you plan to subscribe to updates. Pass `price_fields=odds,fair` to include nullable composite fair odds alongside bookmaker odds.

Auth: X-API-Key Handle HTTP 429 with backoff and avoid tight polling loops.

Request example

curl -H "X-API-Key: $ODDS_API_KEY" "https://api.odds-api.net/v1/events/3704597661/odds/snapshot?limit=25&bookmakers=bet365&types=moneyline&market_keys=moneyline"

Parameters

Path

event_id required
string

Canonical event or race identifier from an event list response.

Query

limit
integer

Maximum items to return. Respect the caps returned by `/limits`.

cursor
string

Pagination cursor from the previous `next_cursor`. Keep filters identical between pages.

bookmakers
string

Comma-separated bookmaker allow-list. Use `/bookmakers` to discover supported keys.

types
string

Comma-separated market type allow-list for odds filters.

market_keys
string

Comma-separated market key allow-list for odds filters.

periods
string

Comma-separated period allow-list for odds filters.

price_fields
string

`odds`, `odds,novig`, `odds,fair`, or `all`. Compact clients default to `odds`; existing clients default to current full pricing fields.

include_source
boolean

When true, include per-line/per-bookmaker provenance and capture metadata. Top-level freshness fields are always kept.

include_debug_ids
boolean

When true, include internal/subgroup/opposing IDs useful for reconciliation.

include_unavailable
boolean

When true, include unavailable or suspended rows where the endpoint supports them.

Responses

200 Successful Response

application/json · object

Event odds: Snapshot

{
  "event_id": "3704597661",
  "as_of_ts_ms": 1760000000000,
  "ttl_seconds": 1800,
  "items": [
    {
      "id": "bet365::moneyline::moneyline::0::::home::",
      "event_id": "3704597661",
      "bookmaker": "bet365",
      "market_key": "moneyline",
      "bet_type": "moneyline",
      "period": "full time",
      "side": "home",
      "selection_name": "Home",
      "odds": 2.1,
      "fair_odds": 1.98,
      "is_available": true
    }
  ],
  "next_cursor": null,
  "resume": "1760000000000-0"
}
400 Invalid request parameters or body.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
401 Missing or invalid credentials.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
403 Credentials are valid but do not allow this resource.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
404 Resource was not found.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
429 Rate limit exceeded.

application/json · value

Retry-After
integer

Seconds to wait before retrying when supplied by the limiter.

X-RateLimit-Limit
integer

Request bucket capacity for the active limiter bucket when supplied.

X-RateLimit-Remaining
integer

Approximate remaining requests in the active limiter bucket when supplied.

X-RateLimit-Bucket
string

Limiter bucket name that produced the response when supplied.

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
500 Unexpected server error.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
GET Stream (SSE) /events/{event_id}/odds/stream

Server-Sent Events feed for odds changes on one event. Subscribe after reading the snapshot and pass the snapshot `resume` value as `since` to receive catch-up changes when available. Handle `delta`, `heartbeat`, and `resync`; reload the snapshot after `resync`.

Auth: X-API-Key Handle HTTP 429 with backoff and avoid tight polling loops.

Request example

curl -H "X-API-Key: $ODDS_API_KEY" "https://api.odds-api.net/v1/events/3704597661/odds/stream?bookmakers=bet365&types=moneyline&market_keys=moneyline&since=1760000000000-0"

Parameters

Path

event_id required
string

Canonical event or race identifier from an event list response.

Query

bookmakers
string

Comma-separated bookmaker allow-list. Use `/bookmakers` to discover supported keys.

types
string

Comma-separated market type allow-list for odds filters.

market_keys
string

Comma-separated market key allow-list for odds filters.

periods
string

Comma-separated period allow-list for odds filters.

price_fields
string

`odds`, `odds,novig`, `odds,fair`, or `all`. Compact clients default to `odds`; existing clients default to current full pricing fields.

include_source
boolean

When true, include per-line/per-bookmaker provenance and capture metadata. Top-level freshness fields are always kept.

include_debug_ids
boolean

When true, include internal/subgroup/opposing IDs useful for reconciliation.

include_unavailable
boolean

When true, include unavailable or suspended rows where the endpoint supports them.

since
string

Resume token from a previous snapshot or stream message. Pass it after reconnecting.

catchup
boolean

When true, return available missed stream events after `since` before waiting for new events.

heartbeat_sec
integer

Heartbeat interval in seconds for stream liveness. Valid range is 5-120.

max_batch
integer

Maximum stream messages to read per batch. Default is 500; use smaller batches for low-latency clients.

Responses

200 Server-Sent Events stream. Each message has an event name and JSON data payload.

text/event-stream · object

Decoded delta message

event: delta
data: {
  "event_id": "3704597661",
  "resume": "1760000000000-0",
  "changes": []
}

Decoded heartbeat message

event: heartbeat
data: {}

Decoded resync message

event: resync
data: {
  "event_id": "3704597661",
  "resume": null,
  "reason": "trimmed"
}
400 Invalid request parameters or body.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
401 Missing or invalid credentials.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
403 Credentials are valid but do not allow this resource.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
404 Resource was not found.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
429 Rate limit exceeded.

application/json · value

Retry-After
integer

Seconds to wait before retrying when supplied by the limiter.

X-RateLimit-Limit
integer

Request bucket capacity for the active limiter bucket when supplied.

X-RateLimit-Remaining
integer

Approximate remaining requests in the active limiter bucket when supplied.

X-RateLimit-Bucket
string

Limiter bucket name that produced the response when supplied.

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
500 Unexpected server error.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
GET Stream (WebSocket) /events/{event_id}/odds/ws

WebSocket feed for odds changes on one event. Messages use the same `delta`, `heartbeat`, and `resync` payloads as the SSE stream. Reconnect with jittered exponential backoff and `since=<last_resume>`.

Auth: X-API-Key Handle HTTP 429 with backoff and avoid tight polling loops.

Request example

curl -H "X-API-Key: $ODDS_API_KEY" "https://api.odds-api.net/v1/events/3704597661/odds/ws?bookmakers=bet365&types=moneyline&market_keys=moneyline&since=1760000000000-0"

Parameters

Path

event_id required
string

Canonical event or race identifier from an event list response.

Query

bookmakers
string

Comma-separated bookmaker allow-list. Use `/bookmakers` to discover supported keys.

types
string

Comma-separated market type allow-list for odds filters.

market_keys
string

Comma-separated market key allow-list for odds filters.

periods
string

Comma-separated period allow-list for odds filters.

price_fields
string

`odds`, `odds,novig`, `odds,fair`, or `all`. Compact clients default to `odds`; existing clients default to current full pricing fields.

include_source
boolean

When true, include per-line/per-bookmaker provenance and capture metadata. Top-level freshness fields are always kept.

include_debug_ids
boolean

When true, include internal/subgroup/opposing IDs useful for reconciliation.

include_unavailable
boolean

When true, include unavailable or suspended rows where the endpoint supports them.

since
string

Resume token from a previous snapshot or stream message. Pass it after reconnecting.

catchup
boolean

When true, return available missed stream events after `since` before waiting for new events.

heartbeat_sec
integer

Heartbeat interval in seconds for stream liveness. Valid range is 5-120.

max_batch
integer

Maximum stream messages to read per batch. Default is 500; use smaller batches for low-latency clients.

Responses

101 WebSocket connection established. Messages are JSON objects.

application/json · object

Delta message

{
  "event": "delta",
  "data": {
    "event_id": "3704597661",
    "resume": "1760000000000-0",
    "changes": []
  }
}

Heartbeat message

{
  "event": "heartbeat",
  "data": {}
}

Resync message

{
  "event": "resync",
  "data": {
    "event_id": "3704597661",
    "resume": null,
    "reason": "trimmed"
  }
}
200 OpenAPI tooling compatibility response schema. Runtime WebSocket connections upgrade with 101.

application/json · object

Delta message

{
  "event": "delta",
  "data": {
    "event_id": "3704597661",
    "resume": "1760000000000-0",
    "changes": []
  }
}

Heartbeat message

{
  "event": "heartbeat",
  "data": {}
}

Resync message

{
  "event": "resync",
  "data": {
    "event_id": "3704597661",
    "resume": null,
    "reason": "trimmed"
  }
}
400 Invalid request parameters or body.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
401 Missing or invalid credentials.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
403 Credentials are valid but do not allow this resource.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
404 Resource was not found.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
429 Rate limit exceeded.

application/json · value

Retry-After
integer

Seconds to wait before retrying when supplied by the limiter.

X-RateLimit-Limit
integer

Request bucket capacity for the active limiter bucket when supplied.

X-RateLimit-Remaining
integer

Approximate remaining requests in the active limiter bucket when supplied.

X-RateLimit-Bucket
string

Limiter bucket name that produced the response when supplied.

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
500 Unexpected server error.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
GET Snapshot /events/{event_id}/odds/history

Returns line movement for a single selection across bookmakers and a time range. Use `selection_key` from an odds snapshot response, bound queries with `from_ts` and `to_ts`, and narrow by bookmaker or market when building charts or backtests.

Auth: X-API-Key Handle HTTP 429 with backoff and avoid tight polling loops.

Request example

curl -H "X-API-Key: $ODDS_API_KEY" "https://api.odds-api.net/v1/events/3704597661/odds/history?selection_key=moneyline%3Ahome&bookmakers=bet365"

Parameters

Path

event_id required
string

Canonical event or race identifier from an event list response.

Query

selection_key required
string

Stable selection identifier from an odds snapshot line, used for history and line movement.

market_group_id
string

Optional market grouping filter for history queries.

bookmakers
string

Comma-separated bookmaker allow-list. Use `/bookmakers` to discover supported keys.

from_ts
string

ISO8601 UTC start timestamp for a bounded history query.

to_ts
string

ISO8601 UTC end timestamp for a bounded history query.

price_type
string

History price type to return, for example odds.

price_fields
string

`odds`, `odds,novig`, `odds,fair`, or `all`. Compact clients default to `odds`; existing clients default to current full pricing fields.

include_source
boolean

When true, include per-line/per-bookmaker provenance and capture metadata. Top-level freshness fields are always kept.

include_debug_ids
boolean

When true, include internal/subgroup/opposing IDs useful for reconciliation.

include_unavailable
boolean

When true, include unavailable or suspended rows where the endpoint supports them.

limit_points_per_bookmaker
integer

Maximum history points per bookmaker. Use this to keep chart/backtest payloads bounded.

Responses

200 Successful Response

application/json · object

Event odds history: Snapshot

{
  "event_id": "3704597661",
  "selection_key": "moneyline:home",
  "price_type": "odds",
  "series": [
    {
      "bookmaker_name": "bet365",
      "points": [
        {
          "tick_ts": "2026-04-29T08:00:00Z",
          "is_available": true,
          "odds": 2.08
        },
        {
          "tick_ts": "2026-04-29T08:05:00Z",
          "is_available": true,
          "odds": 2.1
        }
      ]
    }
  ],
  "meta": {
    "from_ts": "2026-04-29T08:00:00Z",
    "to_ts": "2026-04-29T09:00:00Z",
    "available_price_types": [
      "odds",
      "odds_no_vig",
      "fair_odds"
    ]
  }
}
400 Invalid request parameters or body.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
401 Missing or invalid credentials.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
403 Credentials are valid but do not allow this resource.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
404 Resource was not found.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
429 Rate limit exceeded.

application/json · value

Retry-After
integer

Seconds to wait before retrying when supplied by the limiter.

X-RateLimit-Limit
integer

Request bucket capacity for the active limiter bucket when supplied.

X-RateLimit-Remaining
integer

Approximate remaining requests in the active limiter bucket when supplied.

X-RateLimit-Bucket
string

Limiter bucket name that produced the response when supplied.

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
500 Unexpected server error.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
GET Stream (SSE) /events/{event_id}/odds/history/stream

Server-Sent Events feed for line movement on one selection. This is useful for charts that should update while an event market is moving.

Auth: X-API-Key Handle HTTP 429 with backoff and avoid tight polling loops.

Request example

curl -H "X-API-Key: $ODDS_API_KEY" "https://api.odds-api.net/v1/events/3704597661/odds/history/stream?selection_key=moneyline%3Ahome&bookmakers=bet365&since=1760000000000-0&catchup=true"

Parameters

Path

event_id required
string

Canonical event or race identifier from an event list response.

Query

selection_key required
string

Stable selection identifier from an odds snapshot line, used for history and line movement.

market_group_id
string

Optional market grouping filter for history queries.

bookmakers
string

Comma-separated bookmaker allow-list. Use `/bookmakers` to discover supported keys.

price_type
string

History price type to return, for example odds.

price_fields
string

`odds`, `odds,novig`, `odds,fair`, or `all`. Compact clients default to `odds`; existing clients default to current full pricing fields.

include_source
boolean

When true, include per-line/per-bookmaker provenance and capture metadata. Top-level freshness fields are always kept.

include_debug_ids
boolean

When true, include internal/subgroup/opposing IDs useful for reconciliation.

include_unavailable
boolean

When true, include unavailable or suspended rows where the endpoint supports them.

since
string

Resume token from a previous snapshot or stream message. Pass it after reconnecting.

catchup
boolean

When true, return available missed stream events after `since` before waiting for new events.

heartbeat_sec
integer

Heartbeat interval in seconds for stream liveness. Valid range is 5-120.

max_batch
integer

Maximum stream messages to read per batch. Default is 500; use smaller batches for low-latency clients.

Responses

200 Server-Sent Events stream. Each message has an event name and JSON data payload.

text/event-stream · object

Decoded delta message

event: delta
data: {
  "event_id": "3704597661",
  "selection_key": "moneyline:home",
  "resume": "1760000000000-0",
  "points": []
}

Decoded heartbeat message

event: heartbeat
data: {}

Decoded resync message

event: resync
data: {
  "event_id": "3704597661",
  "resume": null,
  "reason": "trimmed"
}
400 Invalid request parameters or body.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
401 Missing or invalid credentials.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
403 Credentials are valid but do not allow this resource.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
404 Resource was not found.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
429 Rate limit exceeded.

application/json · value

Retry-After
integer

Seconds to wait before retrying when supplied by the limiter.

X-RateLimit-Limit
integer

Request bucket capacity for the active limiter bucket when supplied.

X-RateLimit-Remaining
integer

Approximate remaining requests in the active limiter bucket when supplied.

X-RateLimit-Bucket
string

Limiter bucket name that produced the response when supplied.

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
500 Unexpected server error.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
GET Stream (WebSocket) /events/{event_id}/odds/history/ws

WebSocket feed for line movement on one selection. Messages mirror the history SSE stream payloads.

Auth: X-API-Key Handle HTTP 429 with backoff and avoid tight polling loops.

Request example

curl -H "X-API-Key: $ODDS_API_KEY" "https://api.odds-api.net/v1/events/3704597661/odds/history/ws?selection_key=moneyline%3Ahome&bookmakers=bet365&since=1760000000000-0&catchup=true"

Parameters

Path

event_id required
string

Canonical event or race identifier from an event list response.

Query

selection_key required
string

Stable selection identifier from an odds snapshot line, used for history and line movement.

market_group_id
string

Optional market grouping filter for history queries.

bookmakers
string

Comma-separated bookmaker allow-list. Use `/bookmakers` to discover supported keys.

price_type
string

History price type to return, for example odds.

price_fields
string

`odds`, `odds,novig`, `odds,fair`, or `all`. Compact clients default to `odds`; existing clients default to current full pricing fields.

include_source
boolean

When true, include per-line/per-bookmaker provenance and capture metadata. Top-level freshness fields are always kept.

include_debug_ids
boolean

When true, include internal/subgroup/opposing IDs useful for reconciliation.

include_unavailable
boolean

When true, include unavailable or suspended rows where the endpoint supports them.

since
string

Resume token from a previous snapshot or stream message. Pass it after reconnecting.

catchup
boolean

When true, return available missed stream events after `since` before waiting for new events.

heartbeat_sec
integer

Heartbeat interval in seconds for stream liveness. Valid range is 5-120.

max_batch
integer

Maximum stream messages to read per batch. Default is 500; use smaller batches for low-latency clients.

Responses

101 WebSocket connection established. Messages are JSON objects.

application/json · object

Delta message

{
  "event": "delta",
  "data": {
    "event_id": "3704597661",
    "selection_key": "moneyline:home",
    "resume": "1760000000000-0",
    "points": []
  }
}

Heartbeat message

{
  "event": "heartbeat",
  "data": {}
}

Resync message

{
  "event": "resync",
  "data": {
    "event_id": "3704597661",
    "resume": null,
    "reason": "trimmed"
  }
}
200 OpenAPI tooling compatibility response schema. Runtime WebSocket connections upgrade with 101.

application/json · object

Delta message

{
  "event": "delta",
  "data": {
    "event_id": "3704597661",
    "selection_key": "moneyline:home",
    "resume": "1760000000000-0",
    "points": []
  }
}

Heartbeat message

{
  "event": "heartbeat",
  "data": {}
}

Resync message

{
  "event": "resync",
  "data": {
    "event_id": "3704597661",
    "resume": null,
    "reason": "trimmed"
  }
}
400 Invalid request parameters or body.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
401 Missing or invalid credentials.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
403 Credentials are valid but do not allow this resource.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
404 Resource was not found.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
429 Rate limit exceeded.

application/json · value

Retry-After
integer

Seconds to wait before retrying when supplied by the limiter.

X-RateLimit-Limit
integer

Request bucket capacity for the active limiter bucket when supplied.

X-RateLimit-Remaining
integer

Approximate remaining requests in the active limiter bucket when supplied.

X-RateLimit-Bucket
string

Limiter bucket name that produced the response when supplied.

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
500 Unexpected server error.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}

Endpoint group

Sports exchange

Sports betting exchange order books with back/lay ladders, liquidity, and live updates.

Base URLhttps://api.odds-api.net/v1 Version1.0.0 SourceLive OpenAPI
GET Snapshot /events/{event_id}/exchange/orderbook/snapshot

Returns sports betting exchange order books for one event. Supported exchanges are betdaq, betfair, smarkets, and matchbook. Each selection includes back and lay price levels with available size, plus top-of-book summary fields such as best_back_price, best_lay_price, traded volume, and total matched where supplied by the exchange source. Use `depth` to limit ladder levels and cache only briefly because exchange liquidity can move quickly.

Auth: X-API-Key Handle HTTP 429 with backoff and avoid tight polling loops.

Request example

curl -H "X-API-Key: $ODDS_API_KEY" "https://api.odds-api.net/v1/events/3704597661/exchange/orderbook/snapshot?market_keys=moneyline"

Parameters

Path

event_id required
string

Canonical event or race identifier from an event list response.

Query

exchanges
string

Comma-separated exchange allow-list. Supported values are `betdaq`, `betfair`, `smarkets`, and `matchbook`.

market_keys
string

Comma-separated market key allow-list for odds filters.

selection_keys
string

Comma-separated stable selection identifiers from an exchange order book or odds snapshot.

depth
integer

Number of exchange price levels per back/lay side. Use smaller values for lower latency and payload size.

include_source
boolean

When true, include per-line/per-bookmaker provenance and capture metadata. Top-level freshness fields are always kept.

include_unavailable
boolean

When true, include unavailable or suspended rows where the endpoint supports them.

Responses

200 Successful Response

application/json · object

Event exchange order book: Snapshot

{
  "event_id": "3704597661",
  "as_of_ts_ms": 1760000000000,
  "ttl_seconds": 30,
  "items": [
    {
      "id": "betfair::1.23456789::moneyline",
      "event_id": "3704597661",
      "exchange": "betfair",
      "exchange_market_id": "1.23456789",
      "market_key": "moneyline",
      "bet_type": "moneyline",
      "period": "full time",
      "status": "open",
      "in_play": false,
      "total_matched": 24567.12,
      "selections": [
        {
          "selection_key": "moneyline:home",
          "exchange_selection_id": "12345",
          "selection_name": "Home",
          "last_traded_price": 2.08,
          "available_to_back": [
            {
              "price": 2.08,
              "size": 120.5
            }
          ],
          "available_to_lay": [
            {
              "price": 2.1,
              "size": 84.3
            }
          ],
          "best_back_price": 2.08,
          "best_back_size": 120.5,
          "best_lay_price": 2.1,
          "best_lay_size": 84.3
        }
      ]
    }
  ],
  "next_cursor": null,
  "resume": "1760000000000-0"
}
400 Invalid request parameters or body.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
401 Missing or invalid credentials.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
403 Credentials are valid but do not allow this resource.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
404 Resource was not found.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
429 Rate limit exceeded.

application/json · value

Retry-After
integer

Seconds to wait before retrying when supplied by the limiter.

X-RateLimit-Limit
integer

Request bucket capacity for the active limiter bucket when supplied.

X-RateLimit-Remaining
integer

Approximate remaining requests in the active limiter bucket when supplied.

X-RateLimit-Bucket
string

Limiter bucket name that produced the response when supplied.

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
500 Unexpected server error.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
GET Stream (SSE) /events/{event_id}/exchange/orderbook/stream

Server-Sent Events feed for sports exchange order book changes on one event. Subscribe after reading the snapshot and pass the snapshot `resume` value as `since` to receive catch-up changes when available. Handle `delta`, `heartbeat`, and `resync`; reload the snapshot after `resync`.

Auth: X-API-Key Handle HTTP 429 with backoff and avoid tight polling loops.

Request example

curl -H "X-API-Key: $ODDS_API_KEY" "https://api.odds-api.net/v1/events/3704597661/exchange/orderbook/stream?market_keys=moneyline&since=1760000000000-0&catchup=true"

Parameters

Path

event_id required
string

Canonical event or race identifier from an event list response.

Query

exchanges
string

Comma-separated exchange allow-list. Supported values are `betdaq`, `betfair`, `smarkets`, and `matchbook`.

market_keys
string

Comma-separated market key allow-list for odds filters.

selection_keys
string

Comma-separated stable selection identifiers from an exchange order book or odds snapshot.

depth
integer

Number of exchange price levels per back/lay side. Use smaller values for lower latency and payload size.

include_source
boolean

When true, include per-line/per-bookmaker provenance and capture metadata. Top-level freshness fields are always kept.

include_unavailable
boolean

When true, include unavailable or suspended rows where the endpoint supports them.

since
string

Resume token from a previous snapshot or stream message. Pass it after reconnecting.

catchup
boolean

When true, return available missed stream events after `since` before waiting for new events.

heartbeat_sec
integer

Heartbeat interval in seconds for stream liveness. Valid range is 5-120.

max_batch
integer

Maximum stream messages to read per batch. Default is 500; use smaller batches for low-latency clients.

Responses

200 Server-Sent Events stream. Each message has an event name and JSON data payload.

text/event-stream · object

Decoded delta message

event: delta
data: {
  "event_id": "3704597661",
  "resume": "1760000000000-0",
  "changes": []
}

Decoded heartbeat message

event: heartbeat
data: {}

Decoded resync message

event: resync
data: {
  "event_id": "3704597661",
  "resume": null,
  "reason": "trimmed"
}
400 Invalid request parameters or body.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
401 Missing or invalid credentials.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
403 Credentials are valid but do not allow this resource.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
404 Resource was not found.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
429 Rate limit exceeded.

application/json · value

Retry-After
integer

Seconds to wait before retrying when supplied by the limiter.

X-RateLimit-Limit
integer

Request bucket capacity for the active limiter bucket when supplied.

X-RateLimit-Remaining
integer

Approximate remaining requests in the active limiter bucket when supplied.

X-RateLimit-Bucket
string

Limiter bucket name that produced the response when supplied.

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
500 Unexpected server error.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
GET Stream (WebSocket) /events/{event_id}/exchange/orderbook/ws

WebSocket feed for sports exchange order book changes on one event. Messages mirror the exchange order book SSE stream payloads.

Auth: X-API-Key Handle HTTP 429 with backoff and avoid tight polling loops.

Request example

curl -H "X-API-Key: $ODDS_API_KEY" "https://api.odds-api.net/v1/events/3704597661/exchange/orderbook/ws?market_keys=moneyline&since=1760000000000-0&catchup=true"

Parameters

Path

event_id required
string

Canonical event or race identifier from an event list response.

Query

exchanges
string

Comma-separated exchange allow-list. Supported values are `betdaq`, `betfair`, `smarkets`, and `matchbook`.

market_keys
string

Comma-separated market key allow-list for odds filters.

selection_keys
string

Comma-separated stable selection identifiers from an exchange order book or odds snapshot.

depth
integer

Number of exchange price levels per back/lay side. Use smaller values for lower latency and payload size.

include_source
boolean

When true, include per-line/per-bookmaker provenance and capture metadata. Top-level freshness fields are always kept.

include_unavailable
boolean

When true, include unavailable or suspended rows where the endpoint supports them.

since
string

Resume token from a previous snapshot or stream message. Pass it after reconnecting.

catchup
boolean

When true, return available missed stream events after `since` before waiting for new events.

heartbeat_sec
integer

Heartbeat interval in seconds for stream liveness. Valid range is 5-120.

max_batch
integer

Maximum stream messages to read per batch. Default is 500; use smaller batches for low-latency clients.

Responses

101 WebSocket connection established. Messages are JSON objects.

application/json · object

Delta message

{
  "event": "delta",
  "data": {
    "event_id": "3704597661",
    "resume": "1760000000000-0",
    "changes": []
  }
}

Heartbeat message

{
  "event": "heartbeat",
  "data": {}
}

Resync message

{
  "event": "resync",
  "data": {
    "event_id": "3704597661",
    "resume": null,
    "reason": "trimmed"
  }
}
200 OpenAPI tooling compatibility response schema. Runtime WebSocket connections upgrade with 101.

application/json · object

Delta message

{
  "event": "delta",
  "data": {
    "event_id": "3704597661",
    "resume": "1760000000000-0",
    "changes": []
  }
}

Heartbeat message

{
  "event": "heartbeat",
  "data": {}
}

Resync message

{
  "event": "resync",
  "data": {
    "event_id": "3704597661",
    "resume": null,
    "reason": "trimmed"
  }
}
400 Invalid request parameters or body.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
401 Missing or invalid credentials.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
403 Credentials are valid but do not allow this resource.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
404 Resource was not found.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
429 Rate limit exceeded.

application/json · value

Retry-After
integer

Seconds to wait before retrying when supplied by the limiter.

X-RateLimit-Limit
integer

Request bucket capacity for the active limiter bucket when supplied.

X-RateLimit-Remaining
integer

Approximate remaining requests in the active limiter bucket when supplied.

X-RateLimit-Bucket
string

Limiter bucket name that produced the response when supplied.

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
500 Unexpected server error.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}

Endpoint group

Racing events

Racing event discovery and live racing event updates.

Base URLhttps://api.odds-api.net/v1 Version1.0.0 SourceLive OpenAPI
GET Search /racing/events

Searches upcoming and live racing events with race type, state, country, status, and time filters. Racing polling should use narrow windows, stable cursors, and shorter intervals near jump.

Auth: X-API-Key Handle HTTP 429 with backoff and avoid tight polling loops.

Request example

curl -H "X-API-Key: $ODDS_API_KEY" "https://api.odds-api.net/v1/racing/events?limit=25"

Parameters

Query

race_type
string

Comma-separated racing type filters.

race_state
string

Comma-separated racing state filters.

race_country
string

Comma-separated racing country filters.

status
string

Comma-separated status filters.

start_from
integer

Unix seconds lower bound for event start time. Use bounded windows in production polling.

start_to
integer

Unix seconds upper bound for event start time. Keep windows narrow for hot sync jobs.

cursor
string

Pagination cursor from the previous `next_cursor`. Keep filters identical between pages.

limit
integer

Maximum items to return. Respect the caps returned by `/limits`.

include_links
boolean

When true, include bookmaker/deep-link fields such as match links and racing links.

include_source
boolean

When true, include per-line/per-bookmaker provenance and capture metadata. Top-level freshness fields are always kept.

Responses

200 Successful Response

application/json · object

Racing events: Search

{
  "items": [
    {
      "event_id": "race-1001",
      "race_type": "horse",
      "race_country": "AU",
      "race_state": "QLD",
      "status": "open",
      "race_start_time": 1760000000,
      "race_venue": "Doomben"
    }
  ],
  "next_cursor": null,
  "count": 1
}
400 Invalid request parameters or body.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
401 Missing or invalid credentials.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
403 Credentials are valid but do not allow this resource.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
404 Resource was not found.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
429 Rate limit exceeded.

application/json · value

Retry-After
integer

Seconds to wait before retrying when supplied by the limiter.

X-RateLimit-Limit
integer

Request bucket capacity for the active limiter bucket when supplied.

X-RateLimit-Remaining
integer

Approximate remaining requests in the active limiter bucket when supplied.

X-RateLimit-Bucket
string

Limiter bucket name that produced the response when supplied.

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
500 Unexpected server error.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
GET Stream (SSE) /racing/events/stream

Server-Sent Events feed for racing event inserts, updates, and removals. Store resume tokens and reload the event list if a stream asks the client to resync.

Auth: X-API-Key Handle HTTP 429 with backoff and avoid tight polling loops.

Request example

curl -H "X-API-Key: $ODDS_API_KEY" "https://api.odds-api.net/v1/racing/events/stream?since=1760000000000-0&catchup=true"

Parameters

Query

include_links
boolean

When true, include bookmaker/deep-link fields such as match links and racing links.

include_raw_payload
boolean

When true, include raw stored payload/data objects where the endpoint exposes them.

include_source
boolean

When true, include per-line/per-bookmaker provenance and capture metadata. Top-level freshness fields are always kept.

since
string

Resume token from a previous snapshot or stream message. Pass it after reconnecting.

catchup
boolean

When true, return available missed stream events after `since` before waiting for new events.

heartbeat_sec
integer

Heartbeat interval in seconds for stream liveness. Valid range is 5-120.

max_batch
integer

Maximum stream messages to read per batch. Default is 500; use smaller batches for low-latency clients.

Responses

200 Server-Sent Events stream. Each message has an event name and JSON data payload.

text/event-stream · object

Decoded delta message

event: delta
data: {
  "resume": "1760000000000-0",
  "changes": []
}

Decoded heartbeat message

event: heartbeat
data: {}

Decoded resync message

event: resync
data: {
  "event_id": "3704597661",
  "resume": null,
  "reason": "trimmed"
}
400 Invalid request parameters or body.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
401 Missing or invalid credentials.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
403 Credentials are valid but do not allow this resource.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
404 Resource was not found.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
429 Rate limit exceeded.

application/json · value

Retry-After
integer

Seconds to wait before retrying when supplied by the limiter.

X-RateLimit-Limit
integer

Request bucket capacity for the active limiter bucket when supplied.

X-RateLimit-Remaining
integer

Approximate remaining requests in the active limiter bucket when supplied.

X-RateLimit-Bucket
string

Limiter bucket name that produced the response when supplied.

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
500 Unexpected server error.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
GET Stream (WebSocket) /racing/events/ws

WebSocket feed for racing event inserts, updates, and removals. Messages mirror the racing events SSE feed.

Auth: X-API-Key Handle HTTP 429 with backoff and avoid tight polling loops.

Request example

curl -H "X-API-Key: $ODDS_API_KEY" "https://api.odds-api.net/v1/racing/events/ws?since=1760000000000-0&catchup=true"

Parameters

Query

include_links
boolean

When true, include bookmaker/deep-link fields such as match links and racing links.

include_raw_payload
boolean

When true, include raw stored payload/data objects where the endpoint exposes them.

include_source
boolean

When true, include per-line/per-bookmaker provenance and capture metadata. Top-level freshness fields are always kept.

since
string

Resume token from a previous snapshot or stream message. Pass it after reconnecting.

catchup
boolean

When true, return available missed stream events after `since` before waiting for new events.

heartbeat_sec
integer

Heartbeat interval in seconds for stream liveness. Valid range is 5-120.

max_batch
integer

Maximum stream messages to read per batch. Default is 500; use smaller batches for low-latency clients.

Responses

101 WebSocket connection established. Messages are JSON objects.

application/json · object

Delta message

{
  "event": "delta",
  "data": {
    "resume": "1760000000000-0",
    "changes": []
  }
}

Heartbeat message

{
  "event": "heartbeat",
  "data": {}
}

Resync message

{
  "event": "resync",
  "data": {
    "event_id": "3704597661",
    "resume": null,
    "reason": "trimmed"
  }
}
200 OpenAPI tooling compatibility response schema. Runtime WebSocket connections upgrade with 101.

application/json · object

Delta message

{
  "event": "delta",
  "data": {
    "resume": "1760000000000-0",
    "changes": []
  }
}

Heartbeat message

{
  "event": "heartbeat",
  "data": {}
}

Resync message

{
  "event": "resync",
  "data": {
    "event_id": "3704597661",
    "resume": null,
    "reason": "trimmed"
  }
}
400 Invalid request parameters or body.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
401 Missing or invalid credentials.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
403 Credentials are valid but do not allow this resource.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
404 Resource was not found.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
429 Rate limit exceeded.

application/json · value

Retry-After
integer

Seconds to wait before retrying when supplied by the limiter.

X-RateLimit-Limit
integer

Request bucket capacity for the active limiter bucket when supplied.

X-RateLimit-Remaining
integer

Approximate remaining requests in the active limiter bucket when supplied.

X-RateLimit-Bucket
string

Limiter bucket name that produced the response when supplied.

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
500 Unexpected server error.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
GET Event details /racing/events/{event_id}

Returns the current racing event record for a canonical race ID.

Auth: X-API-Key Handle HTTP 429 with backoff and avoid tight polling loops.

Request example

curl -H "X-API-Key: $ODDS_API_KEY" "https://api.odds-api.net/v1/racing/events/3704597661"

Parameters

Path

event_id required
string

Canonical event or race identifier from an event list response.

Query

include_links
boolean

When true, include bookmaker/deep-link fields such as match links and racing links.

include_raw_payload
boolean

When true, include raw stored payload/data objects where the endpoint exposes them.

include_source
boolean

When true, include per-line/per-bookmaker provenance and capture metadata. Top-level freshness fields are always kept.

Responses

200 Successful Response

application/json · object

Generated sample

{
  "event_id": "3704597661",
  "data": {}
}
400 Invalid request parameters or body.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
401 Missing or invalid credentials.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
403 Credentials are valid but do not allow this resource.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
404 Resource was not found.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
429 Rate limit exceeded.

application/json · value

Retry-After
integer

Seconds to wait before retrying when supplied by the limiter.

X-RateLimit-Limit
integer

Request bucket capacity for the active limiter bucket when supplied.

X-RateLimit-Remaining
integer

Approximate remaining requests in the active limiter bucket when supplied.

X-RateLimit-Bucket
string

Limiter bucket name that produced the response when supplied.

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
500 Unexpected server error.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}

Endpoint group

Racing odds

Racing odds snapshots, home racing feeds, Server-Sent Events, and WebSocket updates.

Base URLhttps://api.odds-api.net/v1 Version1.0.0 SourceLive OpenAPI
GET Snapshot /racing/events/{event_id}/odds

Returns bookmaker odds snapshots for one racing event. Cache the last good snapshot with its timestamp and prefer streams for near-jump realtime displays.

Auth: X-API-Key Handle HTTP 429 with backoff and avoid tight polling loops.

Request example

curl -H "X-API-Key: $ODDS_API_KEY" "https://api.odds-api.net/v1/racing/events/3704597661/odds?bookmakers=bet365"

Parameters

Path

event_id required
string

Canonical event or race identifier from an event list response.

Query

bookmakers
string

Comma-separated bookmaker allow-list. Use `/bookmakers` to discover supported keys.

include_links
boolean

When true, include bookmaker/deep-link fields such as match links and racing links.

include_raw_payload
boolean

When true, include raw stored payload/data objects where the endpoint exposes them.

include_source
boolean

When true, include per-line/per-bookmaker provenance and capture metadata. Top-level freshness fields are always kept.

include_unavailable
boolean

When true, include unavailable or suspended rows where the endpoint supports them.

Responses

200 Successful Response

application/json · object

Racing odds: Snapshot

{
  "event_id": "race-1001",
  "as_of_ts_ms": 1760000000000,
  "items": [
    {
      "bookmaker_name": "sportsbet",
      "race_id": "race-1001",
      "status": "open",
      "payload": {
        "runners": [
          {
            "runner_number": "1",
            "runner_name": "Example Runner",
            "win_odds": 3.4,
            "place_odds": 1.65
          }
        ]
      }
    }
  ],
  "resume": "1760000000000-0"
}
400 Invalid request parameters or body.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
401 Missing or invalid credentials.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
403 Credentials are valid but do not allow this resource.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
404 Resource was not found.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
429 Rate limit exceeded.

application/json · value

Retry-After
integer

Seconds to wait before retrying when supplied by the limiter.

X-RateLimit-Limit
integer

Request bucket capacity for the active limiter bucket when supplied.

X-RateLimit-Remaining
integer

Approximate remaining requests in the active limiter bucket when supplied.

X-RateLimit-Bucket
string

Limiter bucket name that produced the response when supplied.

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
500 Unexpected server error.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
GET Stream (SSE) /racing/events/{event_id}/odds/stream

Server-Sent Events feed for racing odds changes on one event. Reconnect with `since=<last_resume>` and reload the snapshot after `resync`.

Auth: X-API-Key Handle HTTP 429 with backoff and avoid tight polling loops.

Request example

curl -H "X-API-Key: $ODDS_API_KEY" "https://api.odds-api.net/v1/racing/events/3704597661/odds/stream?since=1760000000000-0&catchup=true"

Parameters

Path

event_id required
string

Canonical event or race identifier from an event list response.

Query

include_links
boolean

When true, include bookmaker/deep-link fields such as match links and racing links.

include_raw_payload
boolean

When true, include raw stored payload/data objects where the endpoint exposes them.

include_source
boolean

When true, include per-line/per-bookmaker provenance and capture metadata. Top-level freshness fields are always kept.

include_unavailable
boolean

When true, include unavailable or suspended rows where the endpoint supports them.

since
string

Resume token from a previous snapshot or stream message. Pass it after reconnecting.

catchup
boolean

When true, return available missed stream events after `since` before waiting for new events.

heartbeat_sec
integer

Heartbeat interval in seconds for stream liveness. Valid range is 5-120.

max_batch
integer

Maximum stream messages to read per batch. Default is 500; use smaller batches for low-latency clients.

Responses

200 Server-Sent Events stream. Each message has an event name and JSON data payload.

text/event-stream · object

Decoded delta message

event: delta
data: {
  "event_id": "race-1001",
  "resume": "1760000000000-0",
  "changes": []
}

Decoded heartbeat message

event: heartbeat
data: {}

Decoded resync message

event: resync
data: {
  "event_id": "3704597661",
  "resume": null,
  "reason": "trimmed"
}
400 Invalid request parameters or body.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
401 Missing or invalid credentials.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
403 Credentials are valid but do not allow this resource.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
404 Resource was not found.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
429 Rate limit exceeded.

application/json · value

Retry-After
integer

Seconds to wait before retrying when supplied by the limiter.

X-RateLimit-Limit
integer

Request bucket capacity for the active limiter bucket when supplied.

X-RateLimit-Remaining
integer

Approximate remaining requests in the active limiter bucket when supplied.

X-RateLimit-Bucket
string

Limiter bucket name that produced the response when supplied.

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
500 Unexpected server error.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
GET Stream (WebSocket) /racing/events/{event_id}/odds/ws

WebSocket feed for racing odds changes on one event. Messages mirror the racing odds SSE feed.

Auth: X-API-Key Handle HTTP 429 with backoff and avoid tight polling loops.

Request example

curl -H "X-API-Key: $ODDS_API_KEY" "https://api.odds-api.net/v1/racing/events/3704597661/odds/ws?since=1760000000000-0&catchup=true"

Parameters

Path

event_id required
string

Canonical event or race identifier from an event list response.

Query

include_links
boolean

When true, include bookmaker/deep-link fields such as match links and racing links.

include_raw_payload
boolean

When true, include raw stored payload/data objects where the endpoint exposes them.

include_source
boolean

When true, include per-line/per-bookmaker provenance and capture metadata. Top-level freshness fields are always kept.

include_unavailable
boolean

When true, include unavailable or suspended rows where the endpoint supports them.

since
string

Resume token from a previous snapshot or stream message. Pass it after reconnecting.

catchup
boolean

When true, return available missed stream events after `since` before waiting for new events.

heartbeat_sec
integer

Heartbeat interval in seconds for stream liveness. Valid range is 5-120.

max_batch
integer

Maximum stream messages to read per batch. Default is 500; use smaller batches for low-latency clients.

Responses

101 WebSocket connection established. Messages are JSON objects.

application/json · object

Delta message

{
  "event": "delta",
  "data": {
    "event_id": "race-1001",
    "resume": "1760000000000-0",
    "changes": []
  }
}

Heartbeat message

{
  "event": "heartbeat",
  "data": {}
}

Resync message

{
  "event": "resync",
  "data": {
    "event_id": "3704597661",
    "resume": null,
    "reason": "trimmed"
  }
}
200 OpenAPI tooling compatibility response schema. Runtime WebSocket connections upgrade with 101.

application/json · object

Delta message

{
  "event": "delta",
  "data": {
    "event_id": "race-1001",
    "resume": "1760000000000-0",
    "changes": []
  }
}

Heartbeat message

{
  "event": "heartbeat",
  "data": {}
}

Resync message

{
  "event": "resync",
  "data": {
    "event_id": "3704597661",
    "resume": null,
    "reason": "trimmed"
  }
}
400 Invalid request parameters or body.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
401 Missing or invalid credentials.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
403 Credentials are valid but do not allow this resource.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
404 Resource was not found.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
429 Rate limit exceeded.

application/json · value

Retry-After
integer

Seconds to wait before retrying when supplied by the limiter.

X-RateLimit-Limit
integer

Request bucket capacity for the active limiter bucket when supplied.

X-RateLimit-Remaining
integer

Approximate remaining requests in the active limiter bucket when supplied.

X-RateLimit-Bucket
string

Limiter bucket name that produced the response when supplied.

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
500 Unexpected server error.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}

Endpoint group

Betting opportunities

Positive EV, arbitrage, middle, and bonus-bet opportunity feeds.

Base URLhttps://api.odds-api.net/v1 Version1.0.0 SourceLive OpenAPI
GET Snapshot /bets/snapshot

Returns current betting opportunities by strategy. Use `strategies`, `limit`, and `event_id` to keep the payload scoped to what your product needs. Poll at a bounded interval, cache the last good response, and show execution-risk language before any user-facing bet action.

Auth: X-API-Key Handle HTTP 429 with backoff and avoid tight polling loops.

Request example

curl -H "X-API-Key: $ODDS_API_KEY" "https://api.odds-api.net/v1/bets/snapshot?strategies=pos_ev&limit=25"

Parameters

Query

strategies
string

Comma-separated betting strategies or `all`.

limit
integer

Maximum items to return. Respect the caps returned by `/limits`.

event_id
string

Canonical event or race identifier from an event list response.

source
string

Live bet source: active, legacy, or admin-only hybrid

price_fields
string

`odds`, `odds,novig`, `odds,fair`, or `all`. Compact clients default to `odds`; existing clients default to current full pricing fields.

include_links
boolean

When true, include bookmaker/deep-link fields such as match links and racing links.

include_raw_payload
boolean

When true, include raw stored payload/data objects where the endpoint exposes them.

include_source
boolean

When true, include per-line/per-bookmaker provenance and capture metadata. Top-level freshness fields are always kept.

include_debug_ids
boolean

When true, include internal/subgroup/opposing IDs useful for reconciliation.

Responses

200 Successful Response

application/json · object

Betting opportunities: Snapshot

{
  "items": [
    {
      "id": "example-positive-ev",
      "strategy": "pos_ev",
      "event_id": "3704597661",
      "bookmaker_name": "Bet365",
      "selection_key": "moneyline:home",
      "odds": 2.1,
      "ev": 7.7
    }
  ],
  "resume": "{\"pos_ev\":\"1760000000000-0\"}"
}
400 Invalid request parameters or body.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
401 Missing or invalid credentials.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
403 Credentials are valid but do not allow this resource.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
404 Resource was not found.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
429 Rate limit exceeded.

application/json · value

Retry-After
integer

Seconds to wait before retrying when supplied by the limiter.

X-RateLimit-Limit
integer

Request bucket capacity for the active limiter bucket when supplied.

X-RateLimit-Remaining
integer

Approximate remaining requests in the active limiter bucket when supplied.

X-RateLimit-Bucket
string

Limiter bucket name that produced the response when supplied.

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
500 Unexpected server error.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
GET Stream (SSE) /bets/stream

Server-Sent Events feed for betting opportunity inserts, updates, and removals. Use this for alerting instead of high-frequency snapshot polling. Source-binding response headers identify the requested logical live-bet source and per-strategy effective sources.

Auth: X-API-Key Handle HTTP 429 with backoff and avoid tight polling loops.

Request example

curl -H "X-API-Key: $ODDS_API_KEY" "https://api.odds-api.net/v1/bets/stream?strategies=pos_ev&since=1760000000000-0&catchup=true"

Parameters

Query

strategies
string

Comma-separated betting strategies or `all`.

event_id
string

Canonical event or race identifier from an event list response.

source
string

Live bet source: active, legacy, or admin-only hybrid

price_fields
string

`odds`, `odds,novig`, `odds,fair`, or `all`. Compact clients default to `odds`; existing clients default to current full pricing fields.

include_links
boolean

When true, include bookmaker/deep-link fields such as match links and racing links.

include_raw_payload
boolean

When true, include raw stored payload/data objects where the endpoint exposes them.

include_source
boolean

When true, include per-line/per-bookmaker provenance and capture metadata. Top-level freshness fields are always kept.

include_debug_ids
boolean

When true, include internal/subgroup/opposing IDs useful for reconciliation.

since
string

Resume token from a previous snapshot or stream message. Pass it after reconnecting.

catchup
boolean

When true, return available missed stream events after `since` before waiting for new events.

heartbeat_sec
integer

Heartbeat interval in seconds for stream liveness. Valid range is 5-120.

Responses

200 Server-Sent Events stream. Each message has an event name and JSON data payload.

text/event-stream · object

Decoded delta message

event: delta
data: {
  "resume": "1760000000000-0",
  "events": []
}

Decoded heartbeat message

event: heartbeat
data: {}

Decoded resync message

event: resync
data: {
  "event_id": "3704597661",
  "resume": null,
  "reason": "trimmed"
}
400 Invalid request parameters or body.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
401 Missing or invalid credentials.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
403 Credentials are valid but do not allow this resource.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
404 Resource was not found.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
429 Rate limit exceeded.

application/json · value

Retry-After
integer

Seconds to wait before retrying when supplied by the limiter.

X-RateLimit-Limit
integer

Request bucket capacity for the active limiter bucket when supplied.

X-RateLimit-Remaining
integer

Approximate remaining requests in the active limiter bucket when supplied.

X-RateLimit-Bucket
string

Limiter bucket name that produced the response when supplied.

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
500 Unexpected server error.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
GET Stream (WebSocket) /bets/ws

WebSocket feed for betting opportunity inserts, updates, and removals. The accept handshake includes source-binding headers matching the SSE stream.

Auth: X-API-Key Handle HTTP 429 with backoff and avoid tight polling loops.

Request example

curl -H "X-API-Key: $ODDS_API_KEY" "https://api.odds-api.net/v1/bets/ws?strategies=pos_ev&since=1760000000000-0&catchup=true"

Parameters

Query

strategies
string

Comma-separated betting strategies or `all`.

event_id
string

Canonical event or race identifier from an event list response.

source
string

Live bet source: active, legacy, or admin-only hybrid

price_fields
string

`odds`, `odds,novig`, `odds,fair`, or `all`. Compact clients default to `odds`; existing clients default to current full pricing fields.

include_links
boolean

When true, include bookmaker/deep-link fields such as match links and racing links.

include_raw_payload
boolean

When true, include raw stored payload/data objects where the endpoint exposes them.

include_source
boolean

When true, include per-line/per-bookmaker provenance and capture metadata. Top-level freshness fields are always kept.

include_debug_ids
boolean

When true, include internal/subgroup/opposing IDs useful for reconciliation.

since
string

Resume token from a previous snapshot or stream message. Pass it after reconnecting.

catchup
boolean

When true, return available missed stream events after `since` before waiting for new events.

heartbeat_sec
integer

Heartbeat interval in seconds for stream liveness. Valid range is 5-120.

Responses

101 WebSocket connection established. Messages are JSON objects.

application/json · object

Delta message

{
  "event": "delta",
  "data": {
    "resume": "1760000000000-0",
    "events": []
  }
}

Heartbeat message

{
  "event": "heartbeat",
  "data": {}
}

Resync message

{
  "event": "resync",
  "data": {
    "event_id": "3704597661",
    "resume": null,
    "reason": "trimmed"
  }
}
200 OpenAPI tooling compatibility response schema. Runtime WebSocket connections upgrade with 101.

application/json · object

Delta message

{
  "event": "delta",
  "data": {
    "resume": "1760000000000-0",
    "events": []
  }
}

Heartbeat message

{
  "event": "heartbeat",
  "data": {}
}

Resync message

{
  "event": "resync",
  "data": {
    "event_id": "3704597661",
    "resume": null,
    "reason": "trimmed"
  }
}
400 Invalid request parameters or body.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
401 Missing or invalid credentials.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
403 Credentials are valid but do not allow this resource.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
404 Resource was not found.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
429 Rate limit exceeded.

application/json · value

Retry-After
integer

Seconds to wait before retrying when supplied by the limiter.

X-RateLimit-Limit
integer

Request bucket capacity for the active limiter bucket when supplied.

X-RateLimit-Remaining
integer

Approximate remaining requests in the active limiter bucket when supplied.

X-RateLimit-Bucket
string

Limiter bucket name that produced the response when supplied.

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
500 Unexpected server error.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}

Endpoint group

Results

Sports event result lookup.

Base URLhttps://api.odds-api.net/v1 Version1.0.0 SourceLive OpenAPI
GET Event result /events/{event_id}/results

Returns the latest known result for a sports event, or `pending` until settled. Poll every 1-5 minutes after start, then back off once the event is final.

Auth: X-API-Key Handle HTTP 429 with backoff and avoid tight polling loops.

Request example

curl -H "X-API-Key: $ODDS_API_KEY" "https://api.odds-api.net/v1/events/3704597661/results"

Parameters

Path

event_id required
string

Canonical event or race identifier from an event list response.

Responses

200 Successful Response

application/json · object

Results: Event result

{
  "event_id": "3704597661",
  "status": "final",
  "result": {
    "home_score": 24,
    "away_score": 18
  }
}
400 Invalid request parameters or body.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
401 Missing or invalid credentials.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
403 Credentials are valid but do not allow this resource.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
404 Resource was not found.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
429 Rate limit exceeded.

application/json · value

Retry-After
integer

Seconds to wait before retrying when supplied by the limiter.

X-RateLimit-Limit
integer

Request bucket capacity for the active limiter bucket when supplied.

X-RateLimit-Remaining
integer

Approximate remaining requests in the active limiter bucket when supplied.

X-RateLimit-Bucket
string

Limiter bucket name that produced the response when supplied.

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}
500 Unexpected server error.

application/json · object

Generated sample

{
  "detail": "string",
  "code": "string",
  "request_id": "string"
}