Every API here is available over the APIs.io API and to AI agents over MCP.
{"openapi":"3.1.0","info":{"title":"Odds API","description":"The Odds API V1 provides sports and racing events, bookmaker odds, exchange and prediction-market order books,\nlive price updates, betting opportunity snapshots, and result lookups for production integrations.\n\nAuthenticate every request with `X-API-Key: <your_api_key>` unless an endpoint explicitly states it is public.\nUse `https://api.odds-api.net/v1` as the production base URL.\n\nSnapshot endpoints return JSON and include timestamps or resume tokens when live updates are available.\n`/stream` endpoints use Server-Sent Events (`text/event-stream`) and `/ws` endpoints use WebSockets. Stream\nmessages use the same shape in both transports: an event name such as `delta`, `heartbeat`, or `resync`, plus a\nJSON payload. Store the latest `resume` value and pass it back as `since` after reconnecting.\n\nProduction clients should start with catalog discovery, page event lists with `limit` and `cursor`, fetch odds\nsnapshots for initial state, then use streams for hot events. Recommended starting polling intervals are:\ncatalog metadata every 6-24 hours, sports event lists every 5-15 minutes, racing event lists every 1-5 minutes,\nodds snapshots every 60-120 seconds when streams are not used, betting opportunity snapshots every 30-120 seconds,\nand results every 1-5 minutes after the event starts until settled.\n\nHandle HTTP 429 by honoring `Retry-After` when present, otherwise use jittered exponential backoff. Use\n`/usage` to detect monthly API-credit quota exhaustion and `/limits` to discover response, stream, add-on, and\nplan caps. Most standard API calls use 1 credit; large odds snapshots, history, broad aggregate feeds, and\nsupport-approved betting feeds may use multiple credits as weighted metering rolls out. Cache snapshots by request\nshape, respect `ttl_seconds` when present, display `as_of_ts_ms`, and use `bookmaker_as_of_ts_ms` when a\nper-bookmaker freshness decision matters. `target_refresh_interval_seconds` is a scheduling target, not an\nartificial plan delay or a guarantee that an upstream bookmaker answered on time. Keep the most recent `resume` token with\ncached state. On stream disconnect, reconnect with `since=<last_resume>` and `catchup=true`; on `resync`, reload\nthe snapshot before applying more deltas.\n\nOdds can change quickly. Check event and bookmaker freshness timestamps, handle empty arrays, suspended selections, rate limits, and stale\nprices before displaying or acting on any betting data.\n\nNew odds-api.net API keys default to a compact response shape that keeps essential IDs, prices, teams, markets,\ntimestamps, and resume tokens while omitting raw payloads, source metadata, internal/debug IDs, bookmaker links,\nand non-offered price columns. Existing API keys keep the historical full response shape unless they explicitly\npass the compacting query flags. There is no public `profile` parameter; use the documented per-field flags when\nyou need to opt a compact client back into a specific field group.","version":"1.0.0","license":{"name":"Proprietary","url":"https://odds-api.net"},"x-workflow-examples":[{"name":"positive_ev_request","summary":"Find positive EV bets for a league.","steps":["GET /v1/events?sport=rugby-league&league=NRL","GET /v1/bets/snapshot?strategies=pos_ev","Use response timestamps and stake/risk controls before showing user-facing picks."]},{"name":"arbitrage_request","summary":"Find arbitrage opportunities across allowed bookmakers.","steps":["GET /v1/bookmakers","GET /v1/bets/snapshot?strategies=arbitrage","Show execution-risk caveats; never present arbitrage as guaranteed after limits, voids, or delays."]},{"name":"odds_history_request","summary":"Get line movement for a market.","steps":["GET /v1/events/{event_id}/odds/snapshot","Pick a selection_key from an odds line.","GET /v1/events/{event_id}/odds/history?selection_key=..."]},{"name":"prediction_market_orderbook_request","summary":"Read and follow a curated prediction-market order book.","steps":["GET /v1/events?sport=basketball&league=NBA","GET /v1/events/{event_id}/prediction-markets/orderbook/snapshot?providers=polymarket,kalshi&depth=3","Connect to the matching /stream or /ws route with since=<snapshot resume>."]}],"x-responsible-gambling":"Do not present betting outcomes as risk-free. Always mention execution risk, stale prices, bookmaker limits, voids, delays, and jurisdictional availability in user-facing products.","x-production-integration":{"recommended_flow":["Authenticate backend requests with X-API-Key.","Discover sports, leagues, and bookmakers before storing local filters.","Page sports or racing events with limit and cursor.","Fetch odds snapshots for initial state. Explicit bookmaker filters are complete in one response; otherwise follow bookmaker-complete pages until complete=true. Persist as_of_ts_ms, ttl_seconds, and resume.","Use SSE or WebSocket streams for realtime updates and reconnect with since=<last_resume>.","Use history endpoints for line movement and results endpoints after events finish."],"recommended_polling_intervals":{"catalog_metadata":"6-24h","sports_events":"5-15m, or 1-5m for active leagues and near-start windows","racing_events":"1-5m with narrow time windows","odds_snapshots_without_streams":"60-120s, or 15-30s for priority events with strict quota controls","betting_opportunity_snapshots":"30-120s depending on alert urgency","results_after_start":"1-5m until settled, then back off"},"stream_reconnects":["Snapshot first, then connect to /stream or /ws with matching filters.","Apply delta messages idempotently and persist the newest resume token.","Use heartbeat messages as liveness checks.","Reconnect with jittered exponential backoff and since=<last_resume>.","Reload the snapshot when a resync message indicates the resume token is unavailable."],"rate_limit_backoff":["Honor Retry-After on 429 when present.","Otherwise start around 2 seconds and double up to about 60 seconds with jitter.","Use X-RateLimit-* response headers when present to tune callers.","Use /usage to detect monthly API-credit quota exhaustion and stop retry loops."],"cache_strategy":["Cache by endpoint path, event ID, normalized filters, page cursor, and product context.","Respect ttl_seconds when present and always surface as_of_ts_ms.","Use streams to update hot caches and reload snapshots after resync or parse failure.","Prefer stale-while-revalidate displays with a visible timestamp."],"failure_modes":["400 invalid request shape, cursor, timestamp, or filter.","401 missing or invalid API key.","403 key lacks plan, product, bookmaker, stream, racing, or strategy access.","404 event, race, result, or selection is unavailable.","429 rate limit or monthly quota exhaustion.","5xx transient service failure; retry with backoff and keep last good cached data marked stale.","Stream close or resync; reconnect with since or reload the snapshot."]}},"paths":{"/":{"get":{"tags":["Start here"],"summary":"Start here: API metadata","operationId":"root__get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiRootResponse"}}}},"400":{"description":"Invalid request parameters or body.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid credentials.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Credentials are valid but do not allow this resource.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded.","headers":{"Retry-After":{"description":"Seconds to wait before retrying when supplied by the limiter.","schema":{"type":"integer","minimum":1}},"X-RateLimit-Limit":{"description":"Request bucket capacity for the active limiter bucket when supplied.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Approximate remaining requests in the active limiter bucket when supplied.","schema":{"type":"integer","minimum":0}},"X-RateLimit-Bucket":{"description":"Limiter bucket name that produced the response when supplied.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitResponse"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"description":"Returns the API name, version, OpenAPI document URL, and hosted reference URL.","security":[],"x-rate-limit-note":"Handle HTTP 429 with backoff and avoid tight polling loops."}},"/status":{"get":{"tags":["Status"],"summary":"API status: Public health summary","operationId":"public_status_status_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicStatusResponse"},"examples":{"default":{"summary":"API status: Public health summary","value":{"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":{"description":"Invalid request parameters or body.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid credentials.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Credentials are valid but do not allow this resource.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded.","headers":{"Retry-After":{"description":"Seconds to wait before retrying when supplied by the limiter.","schema":{"type":"integer","minimum":1}},"X-RateLimit-Limit":{"description":"Request bucket capacity for the active limiter bucket when supplied.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Approximate remaining requests in the active limiter bucket when supplied.","schema":{"type":"integer","minimum":0}},"X-RateLimit-Bucket":{"description":"Limiter bucket name that produced the response when supplied.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitResponse"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"description":"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.","security":[],"x-rate-limit-note":"Handle HTTP 429 with backoff and avoid tight polling loops."}},"/me":{"get":{"tags":["Account"],"summary":"Account: Current identity","operationId":"me_me_get","security":[{"ApiKeyAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiIdentityResponse"}}}},"400":{"description":"Invalid request parameters or body.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid credentials.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Credentials are valid but do not allow this resource.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded.","headers":{"Retry-After":{"description":"Seconds to wait before retrying when supplied by the limiter.","schema":{"type":"integer","minimum":1}},"X-RateLimit-Limit":{"description":"Request bucket capacity for the active limiter bucket when supplied.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Approximate remaining requests in the active limiter bucket when supplied.","schema":{"type":"integer","minimum":0}},"X-RateLimit-Bucket":{"description":"Limiter bucket name that produced the response when supplied.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitResponse"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"description":"Returns the authenticated API identity and enabled product capabilities for the supplied key.","x-rate-limit-note":"Handle HTTP 429 with backoff and avoid tight polling loops."}},"/usage":{"get":{"tags":["Account"],"summary":"Account: Usage","operationId":"usage_usage_get","security":[{"ApiKeyAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UsageResponse"},"examples":{"default":{"summary":"Account: Usage","value":{"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,"stream_hours_used":438.25,"stream_hours_limit":6000,"stream_logical_bytes_used":187654321,"stream_logical_bytes_limit":536870912000,"stream_concurrent_units_used":7,"stream_concurrent_units_limit":25,"exceeded":false}}}}}},"400":{"description":"Invalid request parameters or body.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid credentials.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Credentials are valid but do not allow this resource.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded.","headers":{"Retry-After":{"description":"Seconds to wait before retrying when supplied by the limiter.","schema":{"type":"integer","minimum":1}},"X-RateLimit-Limit":{"description":"Request bucket capacity for the active limiter bucket when supplied.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Approximate remaining requests in the active limiter bucket when supplied.","schema":{"type":"integer","minimum":0}},"X-RateLimit-Bucket":{"description":"Limiter bucket name that produced the response when supplied.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitResponse"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"description":"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.","x-rate-limit-note":"Handle HTTP 429 with backoff and avoid tight polling loops."}},"/limits":{"get":{"tags":["Account"],"summary":"Account: Limits","operationId":"limits_limits_get","security":[{"ApiKeyAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LimitsResponse"},"examples":{"default":{"summary":"Account: Limits","value":{"responses":{"events_limit_max":1000,"odds_snapshot_limit_max":25000,"bets_snapshot_limit_max":20000},"sse":{"heartbeat_sec_min":5,"heartbeat_sec_max":120,"max_batch_default":500},"streams":{"metering":"all authenticated API-key SSE and WebSocket connections","formula":"stream_units * open_seconds / 3600","enforcement_interval_seconds":5}}}}}}},"400":{"description":"Invalid request parameters or body.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid credentials.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Credentials are valid but do not allow this resource.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded.","headers":{"Retry-After":{"description":"Seconds to wait before retrying when supplied by the limiter.","schema":{"type":"integer","minimum":1}},"X-RateLimit-Limit":{"description":"Request bucket capacity for the active limiter bucket when supplied.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Approximate remaining requests in the active limiter bucket when supplied.","schema":{"type":"integer","minimum":0}},"X-RateLimit-Bucket":{"description":"Limiter bucket name that produced the response when supplied.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitResponse"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"description":"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.","x-rate-limit-note":"Handle HTTP 429 with backoff and avoid tight polling loops."}},"/sports":{"get":{"tags":["Catalog"],"summary":"Catalog: Sports","operationId":"sports_sports_get","security":[{"ApiKeyAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StringListResponse"}}}},"400":{"description":"Invalid request parameters or body.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid credentials.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Credentials are valid but do not allow this resource.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded.","headers":{"Retry-After":{"description":"Seconds to wait before retrying when supplied by the limiter.","schema":{"type":"integer","minimum":1}},"X-RateLimit-Limit":{"description":"Request bucket capacity for the active limiter bucket when supplied.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Approximate remaining requests in the active limiter bucket when supplied.","schema":{"type":"integer","minimum":0}},"X-RateLimit-Bucket":{"description":"Limiter bucket name that produced the response when supplied.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitResponse"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"description":"Lists sports with event and odds coverage.","x-rate-limit-note":"Handle HTTP 429 with backoff and avoid tight polling loops."}},"/leagues":{"get":{"tags":["Catalog"],"summary":"Catalog: Leagues","operationId":"leagues_leagues_get","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"sport","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sport"},"description":"Sport filter. Use `/sports` to discover supported values."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StringListResponse"}}}},"400":{"description":"Invalid request parameters or body.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid credentials.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Credentials are valid but do not allow this resource.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded.","headers":{"Retry-After":{"description":"Seconds to wait before retrying when supplied by the limiter.","schema":{"type":"integer","minimum":1}},"X-RateLimit-Limit":{"description":"Request bucket capacity for the active limiter bucket when supplied.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Approximate remaining requests in the active limiter bucket when supplied.","schema":{"type":"integer","minimum":0}},"X-RateLimit-Bucket":{"description":"Limiter bucket name that produced the response when supplied.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitResponse"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"description":"Lists available leagues. Pass `sport` to narrow the response.","x-rate-limit-note":"Handle HTTP 429 with backoff and avoid tight polling loops."}},"/bookmakers":{"get":{"tags":["Catalog"],"summary":"Catalog: Bookmakers","operationId":"bookmakers_bookmakers_get","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"country_code","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Optional comma-separated country code filter, for example `AU` or `AU,UK`.","title":"Country Code"},"description":"Comma-separated country code filter, for example `AU` or `AU,UK`."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BookmakerCatalogResponse"},"examples":{"default":{"summary":"Catalog: Bookmakers","value":{"items":[{"bookmaker":"bet365","country_codes":["AU","UK"]},{"bookmaker":"pinnacle","country_codes":["US"]}]}}}}}},"400":{"description":"Invalid request parameters or body.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid credentials.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Credentials are valid but do not allow this resource.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded.","headers":{"Retry-After":{"description":"Seconds to wait before retrying when supplied by the limiter.","schema":{"type":"integer","minimum":1}},"X-RateLimit-Limit":{"description":"Request bucket capacity for the active limiter bucket when supplied.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Approximate remaining requests in the active limiter bucket when supplied.","schema":{"type":"integer","minimum":0}},"X-RateLimit-Bucket":{"description":"Limiter bucket name that produced the response when supplied.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitResponse"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"description":"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.","x-rate-limit-note":"Handle HTTP 429 with backoff and avoid tight polling loops."}},"/bookmakers/countries":{"get":{"tags":["Catalog"],"summary":"Catalog: Bookmaker countries","operationId":"bookmaker_countries_bookmakers_countries_get","security":[{"ApiKeyAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BookmakerCountriesCatalogResponse"},"examples":{"default":{"summary":"Catalog: Bookmaker countries","value":{"items":[{"country_code":"AU","country":"Australia","bookmakers":["bet365","sportsbet"]},{"country_code":"UK","country":"United Kingdom","bookmakers":["bet365"]}]}}}}}},"400":{"description":"Invalid request parameters or body.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid credentials.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Credentials are valid but do not allow this resource.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded.","headers":{"Retry-After":{"description":"Seconds to wait before retrying when supplied by the limiter.","schema":{"type":"integer","minimum":1}},"X-RateLimit-Limit":{"description":"Request bucket capacity for the active limiter bucket when supplied.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Approximate remaining requests in the active limiter bucket when supplied.","schema":{"type":"integer","minimum":0}},"X-RateLimit-Bucket":{"description":"Limiter bucket name that produced the response when supplied.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitResponse"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"description":"Lists country codes represented in the active bookmaker catalog and the bookmakers available in each country.","x-rate-limit-note":"Handle HTTP 429 with backoff and avoid tight polling loops."}},"/coverage":{"get":{"tags":["Catalog"],"summary":"Catalog: Coverage","operationId":"coverage_coverage_get","security":[],"parameters":[{"name":"bookmaker","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Canonical bookmaker filter, for example `bet365`.","title":"Bookmaker"},"description":"Canonical bookmaker filter. Use `/bookmakers` or `/coverage` to discover supported keys."},{"name":"sport","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Sport filter, for example `basketball`.","title":"Sport"},"description":"Sport filter. Use `/sports` to discover supported values."},{"name":"league","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"League filter, for example `NBA`.","title":"League"},"description":"League filter. Use `/leagues?sport=...` to discover supported values."},{"name":"country_code","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Optional comma-separated country code filter.","title":"Country Code"},"description":"Comma-separated country code filter, for example `AU` or `AU,UK`."},{"name":"lookback_days","in":"query","required":false,"schema":{"type":"integer","maximum":90,"minimum":1,"default":30,"title":"Lookback Days"},"description":"Number of days of recently observed approximate market coverage to include. Maximum is 90."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CoverageResponse"},"examples":{"default":{"summary":"Catalog: Coverage","value":{"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":{"description":"Invalid request parameters or body.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid credentials.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Credentials are valid but do not allow this resource.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded.","headers":{"Retry-After":{"description":"Seconds to wait before retrying when supplied by the limiter.","schema":{"type":"integer","minimum":1}},"X-RateLimit-Limit":{"description":"Request bucket capacity for the active limiter bucket when supplied.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Approximate remaining requests in the active limiter bucket when supplied.","schema":{"type":"integer","minimum":0}},"X-RateLimit-Bucket":{"description":"Limiter bucket name that produced the response when supplied.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitResponse"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"description":"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.","x-rate-limit-note":"Handle HTTP 429 with backoff and avoid tight polling loops."}},"/widgets/odds-ticker":{"get":{"tags":["Widgets"],"summary":"Widgets: Odds ticker","operationId":"odds_ticker_widgets_odds_ticker_get","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"league","in":"query","required":true,"schema":{"type":"string","minLength":1,"title":"League"},"description":"League filter. Use `/leagues?sport=...` to discover supported values."},{"name":"bookmakers","in":"query","required":true,"schema":{"type":"string","minLength":1,"title":"Bookmakers"},"description":"Comma-separated bookmaker allow-list. Use `/bookmakers` to discover supported keys."},{"name":"widget_id","in":"query","required":true,"schema":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[A-Za-z0-9_.:-]+$","title":"Widget Id"},"description":"Stable widget identifier configured on the API client record."},{"name":"markets","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Markets"},"description":"Comma-separated widget market list. Supported values are moneyline, handicap, and total; aliases include h2h, 1x2, spread, and over_under."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":50,"minimum":1,"default":20,"title":"Limit"},"description":"Maximum items to return. Respect the caps returned by `/limits`."},{"name":"window_hours","in":"query","required":false,"schema":{"type":"integer","maximum":168,"minimum":1,"default":48,"title":"Window Hours"}}],"responses":{"200":{"description":"Successfu
# --- truncated at 32 KB (247 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/odds-api/refs/heads/main/openapi/odds-api-openapi.json