History
Gameline history uses three endpoints under /v1/historical/sports/{sport}/events/{id}/, all requiring the Scale plan or above (x-plan-min: scale). History covers archived fixtures after their scheduled kickoff, so an upcoming fixture is not found here: read its current prices from /v1/sports/{sport}/odds instead. Scale covers fixtures that started in the last 2 years; Business covers everything recorded. The archive begins at the date returned by archive_from; older fixtures carry opening and closing prices, newer ones the full series. A fixture from before archive_from returns 404 UNKNOWN_EVENT. The coverage page lists each sport's books, date range and depth.
Endpoints
| Endpoint | Returns |
|---|---|
/odds | Recorded checkpoint prices between the opening and closing line. |
/openers | The market snapshot recorded when each book was first seen offering that market. |
/closing | The last price each book showed before the fixture started. |
Recorded vs. not recorded
Where a fixture has archived change rows, the series includes every retained price, point or size change. For each bookmaker and market, the first point contains the full market at that time. Every later point contains only the outcomes that changed, each with its own values, plus recorded_at. Rebuild the full market by applying points in order, matching outcomes by name and point. A new point/rung adds an outcome; history has no removal records. Bookmaker markets without change rows keep whole-market points at each recorded checkpoint. A fixture recorded with only its opening and closing prices returns a two-point series (opener, then close) with no extra flag, and such a point may carry an empty (null) recorded_at. Opening and closing routes are unchanged.
not_recorded means there are no recorded points for the requested market; no_movement means one recorded point; recorded means multiple recorded points. An empty points array means not_recorded. Checkpoint-only coverage does not prove whether prices changed between checkpoints.
Opening and closing spread, total and team-total ladders put their main line first. Each outcome carries main: true on that line and main: false on alternates. Selection uses the most balanced two-sided line by implied probability, preferring lines whose implied probabilities sum to at most 1.25 when available. A one-sided line is never main while a two-sided line exists. Extreme prices remain as quoted. Series points retain recorded order and omit main.
Opening and closing snapshots include every recorded side and alternate line in the requested market. Their recorded_at is the oldest included quote time, because each side and line can have a different last quote. A gameline closing quote is the last price before the book stopped pre-game betting, which is the stored kickoff. Team sports often start a minute or two after the listed time, so a closing recorded_at can fall shortly after the commence_time served (the scheduled start); it is still a pre-game price. When a book took a market down shortly before kickoff, the close is still that book's last pre-game price, and its recorded_at shows how long before kickoff it was taken. Missing close checkpoints appear as not_recorded.
Sports and scope
History accepts nfl, ncaaf, nba, ncaab, wnba, mlb, nhl, mma, aggregate soccer and aggregate tennis. Use the event ID returned by the live API. nhl and mlb serve the same franchise fixtures as their live routes. A soccer league path such as epl serves fixtures with a recorded league matching that key, including older fixtures; fixtures without a recorded league are served by aggregate soccer only, and an event outside the path's league answers 404, like an unknown ID. League and tournament query selectors are rejected. Tournament-specific tennis paths are not supported here.
Gameline history contains recorded full-game moneylines, spreads and totals, plus the tennis market families captured by the recorder. A live market's availability does not guarantee an archived checkpoint. Part-game markets are archived only for soccer (1h, 2h) from March 2014; tennis (1s) from July 2026; mlb (f5) from August 2026; wnba (1h) from August 2026; select them with periods=. The coverage page lists each market and its dates. No quarter markets are archived.
Historical fixture identity
Keep the event ID returned by the live API. Some legacy archives contain conflicting schedule versions for the same competitors and date. The gameline lookup returns 409 AMBIGUOUS_EVENT when the event ID identifies multiple stored kickoffs, with stored_commence_times listing the choices. Retry with storedCommenceTime set to one of those timestamps (or its Unix seconds) to select that stored schedule. No earliest-choice default is applied. A recorded closing checkpoint is relative to that stored schedule; it does not confirm the actual start time. Legacy doubleheader second-leg IDs may also be unavailable. These are known archive identity limits, so a missing historical row does not establish that the book never priced the fixture.
Player prop history
Use /props, /props/openers or /props/closing under the same historical fixture path, with a player-prop markets selection. These routes require Scale or Business. Full-game props are recorded at seven checkpoints: open, 24 hours, 12 hours, 6 hours, 60 minutes, 30 minutes and close. Every offered player, stat, alternate line and side keeps its own identity. Each selection's opener is its first observation, including selections added later.
Prop history holds player props for NBA from October 2022, NHL from May 2023, NFL from September 2023 and MLB from March 2025; other sports as recorded, from 4 October 2026. Before that date, NBA prop fixtures carry checkpoints from open to close in October 2025 to April 2026, and opening and closing prices only otherwise. NHL, NFL and MLB prop fixtures carry opening and closing prices only. The archive_from start applies to gamelines only. Each fixture can have a later capture start and missing checkpoints. capture_started_at reports when that fixture was first observed. status distinguishes recorded, observed_empty, failed and not_recorded, with checkpoint coverage beside the rows. A missing selected market is not proof that a book offered no props. recorded_at is the recorder observation time; each outcome's last_update is its source timestamp. A close requires an observation before kickoff and a fresh source quote. A book or sport with no safely mapped prop rows has no prices invented for it. Halves and quarters are not recorded.
/v1/historical/sports/nfl/events/nfl:atlantafalcons-carolinapanthers:2026-10-04/props?markets=player_pass_ydsGET/v1/historical/sports/nfl/events/nfl:atlantafalcons-carolinapanthers:2026-10-04/props/openers?markets=player_pass_ydsGET/v1/historical/sports/nfl/events/nfl:atlantafalcons-carolinapanthers:2026-10-04/props/closing?markets=player_pass_ydscurl --request GET \
--url "https://oddslink.app/v1/historical/sports/nfl/events/nfl:atlantafalcons-carolinapanthers:2026-10-04/props?markets=player_pass_yds" \
--header "X-API-Key: ok_live_..." \
--compressedimport requests
import json
resp = requests.get(
"https://oddslink.app/v1/historical/sports/nfl/events/nfl:atlantafalcons-carolinapanthers:2026-10-04/props",
params={"markets": "player_pass_yds"},
headers={"X-API-Key": "ok_live_..."},
timeout=60,
)
resp.raise_for_status()
data = resp.json()
print(json.dumps(data, indent=2))async function main() {
const res = await fetch(
"https://oddslink.app/v1/historical/sports/nfl/events/nfl:atlantafalcons-carolinapanthers:2026-10-04/props?markets=player_pass_yds",
{ headers: { "X-API-Key": "ok_live_..." } }
);
if (!res.ok) throw new Error((await res.json()).error.code);
const data = await res.json();
console.log(JSON.stringify(data, null, 2));
}
main().catch((error) => {
console.error(error);
process.exitCode = 1;
});package main
import (
"fmt"
"io"
"net/http"
)
func main() {
req, _ := http.NewRequest("GET",
"https://oddslink.app/v1/historical/sports/nfl/events/nfl:atlantafalcons-carolinapanthers:2026-10-04/props?markets=player_pass_yds", nil)
req.Header.Set("X-API-Key", "ok_live_...")
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}<?php
$ch = curl_init("https://oddslink.app/v1/historical/sports/nfl/events/nfl:atlantafalcons-carolinapanthers:2026-10-04/props?markets=player_pass_yds");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_HTTPHEADER => ["X-API-Key: ok_live_..."],
]);
$data = json_decode(curl_exec($ch), true);
curl_close($ch);curl --request GET \
--url "https://oddslink.app/v1/historical/sports/nfl/events/nfl:atlantafalcons-carolinapanthers:2026-10-04/props/openers?markets=player_pass_yds" \
--header "X-API-Key: ok_live_..." \
--compressedimport requests
import json
resp = requests.get(
"https://oddslink.app/v1/historical/sports/nfl/events/nfl:atlantafalcons-carolinapanthers:2026-10-04/props/openers",
params={"markets": "player_pass_yds"},
headers={"X-API-Key": "ok_live_..."},
timeout=60,
)
resp.raise_for_status()
data = resp.json()
print(json.dumps(data, indent=2))async function main() {
const res = await fetch(
"https://oddslink.app/v1/historical/sports/nfl/events/nfl:atlantafalcons-carolinapanthers:2026-10-04/props/openers?markets=player_pass_yds",
{ headers: { "X-API-Key": "ok_live_..." } }
);
if (!res.ok) throw new Error((await res.json()).error.code);
const data = await res.json();
console.log(JSON.stringify(data, null, 2));
}
main().catch((error) => {
console.error(error);
process.exitCode = 1;
});package main
import (
"fmt"
"io"
"net/http"
)
func main() {
req, _ := http.NewRequest("GET",
"https://oddslink.app/v1/historical/sports/nfl/events/nfl:atlantafalcons-carolinapanthers:2026-10-04/props/openers?markets=player_pass_yds", nil)
req.Header.Set("X-API-Key", "ok_live_...")
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}<?php
$ch = curl_init("https://oddslink.app/v1/historical/sports/nfl/events/nfl:atlantafalcons-carolinapanthers:2026-10-04/props/openers?markets=player_pass_yds");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_HTTPHEADER => ["X-API-Key: ok_live_..."],
]);
$data = json_decode(curl_exec($ch), true);
curl_close($ch);curl --request GET \
--url "https://oddslink.app/v1/historical/sports/nfl/events/nfl:atlantafalcons-carolinapanthers:2026-10-04/props/closing?markets=player_pass_yds" \
--header "X-API-Key: ok_live_..." \
--compressedimport requests
import json
resp = requests.get(
"https://oddslink.app/v1/historical/sports/nfl/events/nfl:atlantafalcons-carolinapanthers:2026-10-04/props/closing",
params={"markets": "player_pass_yds"},
headers={"X-API-Key": "ok_live_..."},
timeout=60,
)
resp.raise_for_status()
data = resp.json()
print(json.dumps(data, indent=2))async function main() {
const res = await fetch(
"https://oddslink.app/v1/historical/sports/nfl/events/nfl:atlantafalcons-carolinapanthers:2026-10-04/props/closing?markets=player_pass_yds",
{ headers: { "X-API-Key": "ok_live_..." } }
);
if (!res.ok) throw new Error((await res.json()).error.code);
const data = await res.json();
console.log(JSON.stringify(data, null, 2));
}
main().catch((error) => {
console.error(error);
process.exitCode = 1;
});package main
import (
"fmt"
"io"
"net/http"
)
func main() {
req, _ := http.NewRequest("GET",
"https://oddslink.app/v1/historical/sports/nfl/events/nfl:atlantafalcons-carolinapanthers:2026-10-04/props/closing?markets=player_pass_yds", nil)
req.Header.Set("X-API-Key", "ok_live_...")
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}<?php
$ch = curl_init("https://oddslink.app/v1/historical/sports/nfl/events/nfl:atlantafalcons-carolinapanthers:2026-10-04/props/closing?markets=player_pass_yds");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_HTTPHEADER => ["X-API-Key: ok_live_..."],
]);
$data = json_decode(curl_exec($ch), true);
curl_close($ch);{
"id": "nfl:atlantafalcons-carolinapanthers:2026-10-04",
"sport_key": "nfl",
"sport_title": "NFL",
"commence_time": "2026-10-04T17:00:00.000Z",
"is_live": false,
"home_team": "Atlanta Falcons",
"away_team": "Carolina Panthers",
"capture_started_at": "2026-10-04T16:00:00.000Z",
"status": "recorded",
"props": [
{
"bookmaker": {
"key": "draftkings",
"title": "DraftKings",
"last_update": "2026-10-04T16:59:40.125Z"
},
"player": "Example Quarterback",
"stat": "player_pass_yds",
"point": 249.5,
"points": [
{
"checkpoint": "close",
"status": "recorded",
"recorded_at": "2026-10-04T16:59:41.250Z",
"outcomes": [
{
"name": "Over",
"price": -110,
"last_update": "2026-10-04T16:59:40.125Z"
},
{
"name": "Under",
"price": -110,
"last_update": "2026-10-04T16:59:40.125Z"
}
]
}
]
}
],
"coverage": [],
"unmatched_bookmakers": []
}{
"id": "nfl:atlantafalcons-carolinapanthers:2026-10-04",
"sport_key": "nfl",
"sport_title": "NFL",
"commence_time": "2026-10-04T17:00:00.000Z",
"is_live": false,
"home_team": "Atlanta Falcons",
"away_team": "Carolina Panthers",
"capture_started_at": "2026-10-04T16:00:00.000Z",
"status": "recorded",
"props": [
{
"bookmaker": {
"key": "draftkings",
"title": "DraftKings",
"last_update": "2026-10-04T16:59:40.125Z"
},
"player": "Example Quarterback",
"stat": "player_pass_yds",
"point": 249.5,
"checkpoint": "open",
"status": "recorded",
"recorded_at": "2026-10-04T16:59:41.250Z",
"outcomes": [
{
"name": "Over",
"price": -110,
"last_update": "2026-10-04T16:59:40.125Z"
},
{
"name": "Under",
"price": -110,
"last_update": "2026-10-04T16:59:40.125Z"
}
]
}
],
"coverage": [],
"unmatched_bookmakers": []
}{
"id": "nfl:atlantafalcons-carolinapanthers:2026-10-04",
"sport_key": "nfl",
"sport_title": "NFL",
"commence_time": "2026-10-04T17:00:00.000Z",
"is_live": false,
"home_team": "Atlanta Falcons",
"away_team": "Carolina Panthers",
"capture_started_at": "2026-10-04T16:00:00.000Z",
"status": "recorded",
"props": [
{
"bookmaker": {
"key": "draftkings",
"title": "DraftKings",
"last_update": "2026-10-04T16:59:40.125Z"
},
"player": "Example Quarterback",
"stat": "player_pass_yds",
"point": 249.5,
"checkpoint": "close",
"status": "recorded",
"recorded_at": "2026-10-04T16:59:41.250Z",
"outcomes": [
{
"name": "Over",
"price": -110,
"last_update": "2026-10-04T16:59:40.125Z"
},
{
"name": "Under",
"price": -110,
"last_update": "2026-10-04T16:59:40.125Z"
}
]
}
],
"coverage": [],
"unmatched_bookmakers": []
}Example
/v1/historical/sports/nfl/events/nfl:atlantafalcons-carolinapanthers:2026-09-20/odds?markets=spreads,totalsGET/v1/historical/sports/nfl/events/nfl:atlantafalcons-carolinapanthers:2026-09-20/openers?markets=spreads,h2h&periods=full,1hGET/v1/historical/sports/nfl/events/nfl:atlantafalcons-carolinapanthers:2026-09-20/closing?markets=spreadscurl --request GET \
--url "https://oddslink.app/v1/historical/sports/nfl/events/nfl:atlantafalcons-carolinapanthers:2026-09-20/odds?markets=spreads,totals" \
--header "X-API-Key: ok_live_..." \
--compressedimport requests
import json
resp = requests.get(
"https://oddslink.app/v1/historical/sports/nfl/events/nfl:atlantafalcons-carolinapanthers:2026-09-20/odds",
params={"markets": "spreads,totals"},
headers={"X-API-Key": "ok_live_..."},
timeout=60,
)
resp.raise_for_status()
data = resp.json()
print(json.dumps(data, indent=2))async function main() {
const res = await fetch(
"https://oddslink.app/v1/historical/sports/nfl/events/nfl:atlantafalcons-carolinapanthers:2026-09-20/odds?markets=spreads,totals",
{ headers: { "X-API-Key": "ok_live_..." } }
);
if (!res.ok) throw new Error((await res.json()).error.code);
const data = await res.json();
console.log(JSON.stringify(data, null, 2));
}
main().catch((error) => {
console.error(error);
process.exitCode = 1;
});package main
import (
"fmt"
"io"
"net/http"
)
func main() {
req, _ := http.NewRequest("GET",
"https://oddslink.app/v1/historical/sports/nfl/events/nfl:atlantafalcons-carolinapanthers:2026-09-20/odds?markets=spreads,totals", nil)
req.Header.Set("X-API-Key", "ok_live_...")
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}<?php
$ch = curl_init("https://oddslink.app/v1/historical/sports/nfl/events/nfl:atlantafalcons-carolinapanthers:2026-09-20/odds?markets=spreads,totals");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_HTTPHEADER => ["X-API-Key: ok_live_..."],
]);
$data = json_decode(curl_exec($ch), true);
curl_close($ch);curl --request GET \
--url "https://oddslink.app/v1/historical/sports/nfl/events/nfl:atlantafalcons-carolinapanthers:2026-09-20/openers?markets=spreads,h2h&periods=full,1h" \
--header "X-API-Key: ok_live_..." \
--compressedimport requests
import json
resp = requests.get(
"https://oddslink.app/v1/historical/sports/nfl/events/nfl:atlantafalcons-carolinapanthers:2026-09-20/openers",
params={"markets": "spreads,h2h", "periods": "full,1h"},
headers={"X-API-Key": "ok_live_..."},
timeout=60,
)
resp.raise_for_status()
data = resp.json()
print(json.dumps(data, indent=2))async function main() {
const res = await fetch(
"https://oddslink.app/v1/historical/sports/nfl/events/nfl:atlantafalcons-carolinapanthers:2026-09-20/openers?markets=spreads,h2h&periods=full,1h",
{ headers: { "X-API-Key": "ok_live_..." } }
);
if (!res.ok) throw new Error((await res.json()).error.code);
const data = await res.json();
console.log(JSON.stringify(data, null, 2));
}
main().catch((error) => {
console.error(error);
process.exitCode = 1;
});package main
import (
"fmt"
"io"
"net/http"
)
func main() {
req, _ := http.NewRequest("GET",
"https://oddslink.app/v1/historical/sports/nfl/events/nfl:atlantafalcons-carolinapanthers:2026-09-20/openers?markets=spreads,h2h&periods=full,1h", nil)
req.Header.Set("X-API-Key", "ok_live_...")
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}<?php
$ch = curl_init("https://oddslink.app/v1/historical/sports/nfl/events/nfl:atlantafalcons-carolinapanthers:2026-09-20/openers?markets=spreads,h2h&periods=full,1h");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_HTTPHEADER => ["X-API-Key: ok_live_..."],
]);
$data = json_decode(curl_exec($ch), true);
curl_close($ch);curl --request GET \
--url "https://oddslink.app/v1/historical/sports/nfl/events/nfl:atlantafalcons-carolinapanthers:2026-09-20/closing?markets=spreads" \
--header "X-API-Key: ok_live_..." \
--compressedimport requests
import json
resp = requests.get(
"https://oddslink.app/v1/historical/sports/nfl/events/nfl:atlantafalcons-carolinapanthers:2026-09-20/closing",
params={"markets": "spreads"},
headers={"X-API-Key": "ok_live_..."},
timeout=60,
)
resp.raise_for_status()
data = resp.json()
print(json.dumps(data, indent=2))async function main() {
const res = await fetch(
"https://oddslink.app/v1/historical/sports/nfl/events/nfl:atlantafalcons-carolinapanthers:2026-09-20/closing?markets=spreads",
{ headers: { "X-API-Key": "ok_live_..." } }
);
if (!res.ok) throw new Error((await res.json()).error.code);
const data = await res.json();
console.log(JSON.stringify(data, null, 2));
}
main().catch((error) => {
console.error(error);
process.exitCode = 1;
});package main
import (
"fmt"
"io"
"net/http"
)
func main() {
req, _ := http.NewRequest("GET",
"https://oddslink.app/v1/historical/sports/nfl/events/nfl:atlantafalcons-carolinapanthers:2026-09-20/closing?markets=spreads", nil)
req.Header.Set("X-API-Key", "ok_live_...")
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}<?php
$ch = curl_init("https://oddslink.app/v1/historical/sports/nfl/events/nfl:atlantafalcons-carolinapanthers:2026-09-20/closing?markets=spreads");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_HTTPHEADER => ["X-API-Key: ok_live_..."],
]);
$data = json_decode(curl_exec($ch), true);
curl_close($ch);{
"id": "nfl:atlantafalcons-carolinapanthers:2026-09-20",
"sport_key": "nfl",
"sport_title": "NFL",
"commence_time": "2026-09-20T17:00:00.000Z",
"is_live": false,
"home_team": "Atlanta Falcons",
"away_team": "Carolina Panthers",
"archive_from": "2026-09-01T00:00:00.000Z",
"bookmakers": [
{
"key": "draftkings",
"title": "DraftKings",
"markets": [
{
"key": "spreads",
"movement": "recorded",
"points": [
{
"recorded_at": "2026-09-15T14:00:03.000Z",
"outcomes": [
{
"name": "Atlanta Falcons",
"price": -110,
"point": 3
},
{
"name": "Carolina Panthers",
"price": -110,
"point": -3
}
]
},
{
"recorded_at": "2026-09-18T18:08:20.000Z",
"outcomes": [
{
"name": "Atlanta Falcons",
"price": 100,
"point": 2.5
},
{
"name": "Carolina Panthers",
"price": -120,
"point": -2.5
}
]
}
]
},
{
"key": "totals",
"movement": "no_movement",
"points": [
{
"recorded_at": "2026-09-15T14:00:03.000Z",
"outcomes": [
{
"name": "Over",
"price": -108,
"point": 43.5
},
{
"name": "Under",
"price": -112,
"point": 43.5
}
]
}
]
},
{
"key": "h2h",
"period": "1h",
"movement": "not_recorded",
"points": []
}
]
}
],
"unmatched_bookmakers": []
}{
"id": "nfl:atlantafalcons-carolinapanthers:2026-09-20",
"sport_key": "nfl",
"sport_title": "NFL",
"commence_time": "2026-09-20T17:00:00.000Z",
"is_live": false,
"home_team": "Atlanta Falcons",
"away_team": "Carolina Panthers",
"bookmakers": [
{
"key": "draftkings",
"title": "DraftKings",
"markets": [
{
"key": "spreads",
"status": "recorded",
"recorded_at": "2026-09-15T14:00:03.000Z",
"outcomes": [
{
"name": "Atlanta Falcons",
"price": -110,
"point": 3,
"main": true
},
{
"name": "Carolina Panthers",
"price": -110,
"point": -3,
"main": true
}
]
},
{
"key": "h2h",
"period": "1h",
"status": "not_recorded",
"recorded_at": null,
"outcomes": []
}
]
}
],
"unmatched_bookmakers": []
}{
"id": "nfl:atlantafalcons-carolinapanthers:2026-09-20",
"sport_key": "nfl",
"sport_title": "NFL",
"commence_time": "2026-09-20T17:00:00.000Z",
"is_live": false,
"home_team": "Atlanta Falcons",
"away_team": "Carolina Panthers",
"bookmakers": [
{
"key": "draftkings",
"title": "DraftKings",
"markets": [
{
"key": "spreads",
"status": "recorded",
"recorded_at": "2026-09-20T16:59:41.000Z",
"outcomes": [
{
"name": "Atlanta Falcons",
"price": 100,
"point": 2.5,
"main": true
},
{
"name": "Carolina Panthers",
"price": -120,
"point": -2.5,
"main": true
}
]
}
]
}
],
"unmatched_bookmakers": []
}