The raw board, paged
Every venue's prices per event, one page at a time: bookmakers as {name, price}, exchanges quoting a lay side as {name, back_price, lay_price, available}. Served gzip only: a request refusing gzip is 400 add Accept-Encoding: gzip; with curl use --compressed.
Checks, in this order: the per-address shield, the key, the flood cap, a suspended account, a browser key's website, the API version; region, the region and raw in the key; the parameters (each one this route reads, once) and their values; the filters (400 unknown values, 403 bookmaker_not_in_region, 403 bookmaker_not_in_plan, then your account's scope: 403 sport_not_in_plan, market_not_in_plan, bookmaker_not_in_plan); includeLinks and includeLiquidity; limit; cursor; gzip; the raw board (503 raw_not_enabled); the page (503 while it cannot be cut); quote=true; the price (402).
Paging: pages are ordered by (kick-off, event id) and a cursor resumes strictly after the last event it saw, so an event that leaves the board between pages never restarts the walk. The accepted limit: an event whose kick-off moves across the cursor during a walk can appear twice or be missed. Dedupe by event id, and take a missed event on the next walk. A cursor expires 300 s after it was issued.
Following changes: walk with updatedSince set to the start of your previous walk; last_update is when a venue's market last moved (see the schema for what it is not).
Price: a page pays its share of the query's price (its prices over all the query's events' prices, at least 1; eventIds and requireBookmakers narrow the page, never the query), so a whole walk pays the query's price (narrowed by eventIds or requireBookmakers, only its kept events' share of it); a recent updatedSince pays a reduced share. quote=true prices this page.
Request
- Base URL: https://api.oddsrelay.io
- URL: https://api.oddsrelay.io/v2/odds/raw
- Auth: one of:
- HTTP bearer
- API key in header x-api-key
Query parameters
ONE lowercase region code (/v2/regions lists yours). Missing means uk: on a data route only when your key covers uk, else 400 region_required naming a code your key has; on discovery and keyless routes always. A comma list, the parameter sent twice or an uppercase code is 400 bad_request; an unknown code, or one with no live bookmaker here, is 404 unknown_region.
envelope (default): {meta, data}. bare: the data array alone, meta moved to X-* headers.
decimal (default) or american (a signed integer; null for a price at or below 1.0). standard and dutching serve decimal only: anything else is 400.
iso (default, ISO-8601 UTC) or unix (integer epoch seconds) for commence_time, processed_at and last_update. standard and dutching serve iso only: anything else is 400.
Comma-separated, at most 20: a sport key, a prefix of one, or a sport name raw serves, lowercased. A competition key (an event's competition_key, listed on /v2/sports) returns every event of that competition, whatever its venues call it. Any other key returns what it returned before, plus every event a venue files under a key it begins (each venue names its league its own way), and, when every event that key has ever named belongs to ONE competition, the rest of that competition. Unknown is 400 unknown_sport with valid. Inside your account's raw scope: a key or prefix starting with a scope sport, a sport name only when it equals one (send soccer, not football); outside, 403 sport_not_in_plan with valid; left out, trimmed to the scope.
The same as sports (what /v2/events takes); ignored when sports is sent.
Comma-separated, at most 40: competition names (an event's league or sport_title), lowercased. Not checked against a catalogue.
Comma-separated, at most 40: venue keys of either kind, bookmakers and exchanges, as /v2/bookmakers lists them. Unknown is 400 unknown_bookmaker with valid; outside the region 403 bookmaker_not_in_region; outside your plan's bookmaker list or your account's raw scope 403 bookmaker_not_in_plan with valid. An account scope's raw list is the whole venue list, exchanges included: left out, trimmed to it (so exchangesOnly=true keeps only the exchanges it names).
Comma-separated, at most 40 venue keys, checked as bookmakers is (the same 400 and 403 codes). Keeps only the events where EVERY named venue quotes the call's markets (with several, at least one of them each), under exchangesOnly if set; a venue that lists the event but not the market does not count. bookmakers does not narrow this test and updatedSince is not part of it: with updatedSince, an event carrying every named venue is kept when any venue shown changed, and the page shows only the venues that changed. It narrows events, never venues: every venue the other filters keep is still shown, named or not. meta.total and X-Count count the events kept. Price: like eventIds, it narrows the page and not the query, so a page pays its share of the same call without requireBookmakers, and an empty page is free.
Comma-separated, at most 20: market keys raw serves. Raw's keys: keyless /v2/coverage's markets.raw. Unknown is 400 unknown_market with valid (raw's keys) and, when another product carries it, products. Keeps venues quoting one of them, and only those markets. Outside your account's scope for this product: 403 market_not_in_plan with valid; left out, trimmed to the scope.
Comma-separated, at most 50 event ids. Narrows the page, not the query: a page pays its share of the same call without eventIds.
Events kicking off at or after this ISO-8601 instant (no offset = UTC; a fraction of a second rounds up). Not ISO-8601 is 400; on the matched boards a From after To is 400.
Events kicking off at or before this ISO-8601 instant (no offset = UTC).
Exactly YYYY-MM-DDTHH:MM:SSZ (any other form is 400). Keeps venues whose last_update is at or after it, and the events holding one. The bulk way to follow raw: a recent updatedSince pays a reduced share (/v2/pricing recent).
true: exchanges only. true or false, else 400.
true: each venue's link (its primary event page; left out when it has none). Default false. true or false, else 400.
false: leave out available beside an exchange's lay_price. Default true. true or false, else 400.
The previous page's meta.next_cursor (or X-Next-Cursor). A cursor is bound to no account and expires 300 s after it was issued: 400 cursor expired: start again from the first page; any other shape 400 cursor not recognised: start again from the first page.
Events per page, 1-250 (default and maximum 250). Anything else is 400.
true (also 1, yes, on): price this exact request instead of serving it. 200 {cost, remaining, rate_card}, free, every check before the price still applies; any other value is an ordinary request.
Headers
Send gzip; with curl, --compressed sends it and decompresses the reply. The raw board answers a request that refuses gzip (identity alone, as Python's urllib sends by default, or gzip;q=0 or *;q=0) with 400 bad_request, message add Accept-Encoding: gzip; with curl use --compressed.
Response
One page (envelope, or the data array under format=bare), or under quote=true its price. Gzip.
Changes
No recorded changes to this operation across all 1 revision of this API.