{"id":5329,"date":"2026-10-28T10:00:00","date_gmt":"2026-10-28T10:00:00","guid":{"rendered":"https:\/\/oddspapi.io\/blog\/?p=5329"},"modified":"2026-10-23T13:38:26","modified_gmt":"2026-10-23T13:38:26","slug":"world-series-odds-api","status":"publish","type":"post","link":"https:\/\/oddspapi.io\/blog\/world-series-odds-api\/","title":{"rendered":"World Series Odds API: Price the Next Game 65 Hours Early"},"content":{"rendered":"<p>If you search for a World Series odds API, you want the moneyline on every game of the series, from more than one book, as JSON. On 23 October 2026 at 13:35 UTC, eleven hours before the first pitch of Brewers v Rays, OddsPapi listed seven series fixtures. Game 1 carried 273 books. Game 2 carried Kalshi and the two Polymarket feeds. No sportsbook had posted it yet.<\/p>\n<p>To check whether that gap is normal, we pulled the price history of all 29 played 2026 postseason games and found the pattern on every series. Pinnacle, DraftKings and FanDuel post the next game after the previous one ends: the first of the three arrived a median 41 minutes after the last out, and never later than 82 minutes. Kalshi listed 16 of those 19 follow-on games before the previous game had even finished, a median 64 hours ahead. If you want a line on Game 5 while Game 4 is still a day away, you read it from a prediction market, then watch for the sportsbooks to arrive.<\/p>\n<h2>Why a scraper sees an empty series<\/h2>\n<p>A scraper that polls a sportsbook&#8217;s MLB page sees one World Series game at a time. Games 2 to 7 do not exist on that page until the book posts them, so your model has nothing to price and your alert has nothing to compare. When the book does post, it posts in the hour after the last out, which is the hour you are least likely to be watching.<\/p>\n<p>OddsPapi lists every scheduled game of the series as its own fixture, and attaches every book that quotes each game: 350+ bookmakers in the catalogue, sportsbooks and exchanges and prediction markets under one schema. One <code>\/v4\/odds<\/code> call shows you who is on the board. One <code>\/v4\/historical-odds<\/code> call, free on every plan, shows you when each of them arrived.<\/p>\n<figure class=\"wp-block-table\">\n<table>\n<thead>\n<tr>\n<th><\/th>\n<th>Scrape the sportsbooks<\/th>\n<th>OddsPapi<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Games 2 to 7<\/td>\n<td>Missing until each book posts them<\/td>\n<td>Listed as fixtures from day one, with Kalshi and Polymarket quotes days ahead<\/td>\n<\/tr>\n<tr>\n<td>Books on Game 1<\/td>\n<td>The sites you scrape<\/td>\n<td>273 feeds on one call, deduped to 62 distinct price pairs in Step 2<\/td>\n<\/tr>\n<tr>\n<td>When a book opened a game<\/td>\n<td>Only if your poller was running<\/td>\n<td>First snapshot per book on <code>\/v4\/historical-odds<\/code><\/td>\n<\/tr>\n<tr>\n<td>Closing margins<\/td>\n<td>Your own archive<\/td>\n<td>Last active price before first pitch, any played game<\/td>\n<\/tr>\n<tr>\n<td>New game alerts<\/td>\n<td>Re-poll every page<\/td>\n<td>Poll one fixture ID, or take pushed updates over the WebSocket feed<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/figure>\n<h2>When each book opened each LCS game<\/h2>\n<p>The table below covers both League Championship Series. Each cell shows the time of the book&#8217;s first moneyline price on that game, measured from the end of the previous game in the same series (the fixture&#8217;s <code>trueEndTime<\/code>). A negative number means the book listed the game before the previous one had finished. The right half shows each book&#8217;s closing margin: the overround on its last active moneyline pair before the scheduled first pitch.<\/p>\n<figure class=\"wp-block-table\">\n<table>\n<thead>\n<tr>\n<th>Game<\/th>\n<th>Start (UTC)<\/th>\n<th>Pinnacle<\/th>\n<th>DraftKings<\/th>\n<th>FanDuel<\/th>\n<th>Kalshi<\/th>\n<th>Pinnacle close<\/th>\n<th>DraftKings close<\/th>\n<th>FanDuel close<\/th>\n<th>Kalshi close<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>NLCS G1<\/td>\n<td>10-12<\/td>\n<td>opener<\/td>\n<td>opener<\/td>\n<td>opener<\/td>\n<td>opener<\/td>\n<td>1.97%<\/td>\n<td>2.91%<\/td>\n<td>2.86%<\/td>\n<td>0.99%<\/td>\n<\/tr>\n<tr>\n<td>NLCS G2<\/td>\n<td>10-12<\/td>\n<td>+0.6 h<\/td>\n<td>+1.1 h<\/td>\n<td>+1.1 h<\/td>\n<td>-74.7 h<\/td>\n<td>2.04%<\/td>\n<td>2.83%<\/td>\n<td>3.35%<\/td>\n<td>1.00%<\/td>\n<\/tr>\n<tr>\n<td>NLCS G3<\/td>\n<td>10-15<\/td>\n<td>+1.1 h<\/td>\n<td>+1.5 h<\/td>\n<td>+1.3 h<\/td>\n<td>-102.0 h<\/td>\n<td>2.07%<\/td>\n<td>2.72%<\/td>\n<td>2.86%<\/td>\n<td>1.00%<\/td>\n<\/tr>\n<tr>\n<td>NLCS G4<\/td>\n<td>10-16<\/td>\n<td>+6.4 h<\/td>\n<td>+1.6 h<\/td>\n<td>+1.4 h<\/td>\n<td>-152.8 h<\/td>\n<td>2.08%<\/td>\n<td>2.72%<\/td>\n<td>2.62%<\/td>\n<td>1.99%<\/td>\n<\/tr>\n<tr>\n<td>ALCS G1<\/td>\n<td>10-13<\/td>\n<td>opener<\/td>\n<td>opener<\/td>\n<td>opener<\/td>\n<td>opener<\/td>\n<td>2.08%<\/td>\n<td>2.81%<\/td>\n<td>2.97%<\/td>\n<td>1.01%<\/td>\n<\/tr>\n<tr>\n<td>ALCS G2<\/td>\n<td>10-14<\/td>\n<td>+0.4 h<\/td>\n<td>+2.1 h<\/td>\n<td>+0.8 h<\/td>\n<td>-46.9 h<\/td>\n<td>2.04%<\/td>\n<td>2.80%<\/td>\n<td>2.91%<\/td>\n<td>1.00%<\/td>\n<\/tr>\n<tr>\n<td>ALCS G3<\/td>\n<td>10-15<\/td>\n<td>+0.2 h<\/td>\n<td>+1.4 h<\/td>\n<td>+1.3 h<\/td>\n<td>-70.6 h<\/td>\n<td>1.93%<\/td>\n<td>2.73%<\/td>\n<td>2.79%<\/td>\n<td>2.00%<\/td>\n<\/tr>\n<tr>\n<td>ALCS G4<\/td>\n<td>10-18<\/td>\n<td>+30.1 h<\/td>\n<td>+31.5 h<\/td>\n<td>+30.4 h<\/td>\n<td>-39.3 h<\/td>\n<td>1.95%<\/td>\n<td>2.66%<\/td>\n<td>2.86%<\/td>\n<td>0.99%<\/td>\n<\/tr>\n<tr>\n<td>ALCS G5<\/td>\n<td>10-18<\/td>\n<td>+1.4 h<\/td>\n<td>+1.7 h<\/td>\n<td>+1.8 h<\/td>\n<td>-19.6 h<\/td>\n<td>1.99%<\/td>\n<td>2.79%<\/td>\n<td>2.87%<\/td>\n<td>0.99%<\/td>\n<\/tr>\n<tr>\n<td>ALCS G6<\/td>\n<td>10-20<\/td>\n<td>+0.6 h<\/td>\n<td>+1.8 h<\/td>\n<td>+0.6 h<\/td>\n<td>-0.2 h<\/td>\n<td>2.04%<\/td>\n<td>2.90%<\/td>\n<td>3.37%<\/td>\n<td>1.00%<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/figure>\n<p>ALCS Game 4 breaks the pattern for a known reason. Its first date, 17 October, shows up on the feed as a <code>Cancelled<\/code> fixture, and the books posted the new date 30 hours after Game 3. We left it out of the medians. Across the other 19 follow-on games of the postseason (1 to 20 October), the first sportsbook arrived 12 to 82 minutes after the last out, and Kalshi beat the first sportsbook to the game on 17 of 19, by a median 65 hours.<\/p>\n<p>Three more things the table shows:<\/p>\n<ul>\n<li><strong>Pinnacle closed every playoff game between 1.82% and 2.24%.<\/strong> Its smaller-side stake limit at the close had a median of 37,500 across the 29 games, which is the depth you can lean on for a fair price.<\/li>\n<li><strong>DraftKings closed the first 18 playoff games at 4.49% to 4.76%, and the 11 games from 11 October onward at 2.66% to 2.91%.<\/strong> The step happened between Guardians v White Sox Game 4 on 9 October and Game 5 on 11 October. On Game 1 of the World Series, eleven hours out, DraftKings quoted 4.61% again, so read its close, not its open.<\/li>\n<li><strong>Kalshi closed 27 of 29 games at 0.98% to 1.02%.<\/strong> The other two read 1.99% and 2.00%.<\/li>\n<\/ul>\n<p>The same &#8220;next game opens after the last one ends&#8221; pattern holds in other sports with a series or a short turnaround; our study of <a href=\"https:\/\/oddspapi.io\/blog\/when-do-nfl-odds-open\/\">when NFL odds open<\/a> measures the same clock across a full NFL season.<\/p>\n<h2>Step 1: List the series and see who is on each game<\/h2>\n<p>Sign up for a free key and export it as <code>ODDSPAPI_API_KEY<\/code>. MLB is <code>tournamentId<\/code> 109. Filter on it and <code>\/v4\/fixtures<\/code> returns the whole postseason window in one call. The feed also carries a <code>Cancelled<\/code> placeholder named &#8220;American League Champion v National League Champion&#8221;, and it marks a rained-out date the same way, so drop that status first.<\/p>\n<pre class=\"wp-block-code\"><code>import os, time, requests\n\nAPI_KEY = os.environ[&quot;ODDSPAPI_API_KEY&quot;]\nBASE = &quot;https:\/\/api.oddspapi.io\/v4&quot;\n\ndef get(path, **params):\n    params[&quot;apiKey&quot;] = API_KEY\n    for _ in range(5):\n        r = requests.get(f&quot;{BASE}\/{path}&quot;, params=params, timeout=120)\n        if r.status_code == 429:\n            time.sleep(r.json().get(&quot;error&quot;, {}).get(&quot;retryMs&quot;, 2000) \/ 1000 + 0.5)\n            continue\n        r.raise_for_status()\n        return r.json()\n    raise RuntimeError(f&quot;{path} kept returning 429&quot;)\n\n# MLB is tournamentId 109. `to` is a midnight-UTC instant, so go one day past the end.\nfixtures = get(&quot;fixtures&quot;, tournamentId=109, **{&quot;from&quot;: &quot;2026-10-23&quot;, &quot;to&quot;: &quot;2026-11-03&quot;})\nseries = [f for f in fixtures if f[&quot;statusName&quot;] != &quot;Cancelled&quot;]\n\nfor f in sorted(series, key=lambda f: f[&quot;startTime&quot;]):\n    board = get(&quot;odds&quot;, fixtureId=f[&quot;fixtureId&quot;])\n    books = sorted(board.get(&quot;bookmakerOdds&quot;, {}))\n    label = &quot;, &quot;.join(books) if len(books) &lt;= 4 else f&quot;{len(books)} books&quot;\n    print(f&#x27;{f[&quot;startTime&quot;][:16]}  {f[&quot;participant1Name&quot;]} v {f[&quot;participant2Name&quot;]}  -&gt;  {label}&#x27;)\n    time.sleep(1.0)<\/code><\/pre>\n<p>Output on 23 October 2026, 13:35 UTC:<\/p>\n<pre class=\"wp-block-code\"><code>2026-10-24T00:00  Milwaukee Brewers v Tampa Bay Rays  -&gt;  273 books\n2026-10-25T00:00  Milwaukee Brewers v Tampa Bay Rays  -&gt;  fliff, kalshi, polymarket, polymarket.us\n2026-10-27T00:00  Tampa Bay Rays v Milwaukee Brewers  -&gt;  fliff, kalshi, polymarket, polymarket.us\n2026-10-28T00:00  Tampa Bay Rays v Milwaukee Brewers  -&gt;  kalshi, polymarket, polymarket.us\n2026-10-29T00:00  Tampa Bay Rays v Milwaukee Brewers  -&gt;  polymarket\n2026-10-31T00:00  Milwaukee Brewers v Tampa Bay Rays  -&gt;  \n2026-11-01T00:00  Milwaukee Brewers v Tampa Bay Rays  -&gt;  neds.com.au<\/code><\/pre>\n<p>Game 1 is a full board. Games 2 to 5 hold the prediction markets (<code>fliff<\/code> flickers on and off with suspended prices), Game 6 is empty, and Game 7 has one Australian book with its market switched off. Participant order follows the home team, so Games 3 to 5 read Rays v Brewers.<\/p>\n<h2>Step 2: Price Game 1 across every live book<\/h2>\n<p>The World Series moneyline is market <code>131<\/code>, outcomes <code>131<\/code> (home) and <code>132<\/code> (away). Baseball also ships a nine-inning result with a tie leg under <code>133<\/code>, and two first-five-innings markets; our <a href=\"https:\/\/oddspapi.io\/blog\/mlb-first-five-innings-odds-api\/\">first five innings guide<\/a> covers those clocks, and the <a href=\"https:\/\/oddspapi.io\/blog\/mlb-odds-api-run-lines-totals\/\">MLB odds API guide<\/a> covers run lines and totals. Stay on <code>131<\/code> for the series winner of each game.<\/p>\n<p>One parser rule matters on this board. On a 13:14 UTC read, 115 of the 206 books with a fresh, active Game 1 moneyline also ship <code>marketActive: false<\/code> on it, Kalshi, Novig, ProphetX, SX Bet and bet365 among them. If you filter on <code>marketActive<\/code>, you throw away the tightest prices on the board. Filter on the book-level <code>suspended<\/code> and <code>bookmakerIsActive<\/code> flags, the price-level <code>active<\/code> flag, and the age of the book&#8217;s newest <code>changedAt<\/code>.<\/p>\n<pre class=\"wp-block-code\"><code>import os, time, statistics, requests\nfrom collections import defaultdict\nfrom datetime import datetime, timezone\n\nAPI_KEY = os.environ[&quot;ODDSPAPI_API_KEY&quot;]\nBASE = &quot;https:\/\/api.oddspapi.io\/v4&quot;\nGAME_1 = &quot;id1300010975060814&quot;        # Brewers v Rays, first pitch 2026-10-24 00:00 UTC\n\ndef ts(s):\n    return datetime.fromisoformat(s.replace(&quot;Z&quot;, &quot;+00:00&quot;))\n\nboard = requests.get(f&quot;{BASE}\/odds&quot;, params={&quot;apiKey&quot;: API_KEY, &quot;fixtureId&quot;: GAME_1}, timeout=120).json()\nnow = datetime.now(timezone.utc)\n\nquotes = {}\nfor slug, book in board[&quot;bookmakerOdds&quot;].items():\n    if &quot;+&quot; in slug or slug in (&quot;demo&quot;, &quot;singbet-b&quot;):          # internal test feeds\n        continue\n    if book.get(&quot;suspended&quot;) or book.get(&quot;bookmakerIsActive&quot;) is False:\n        continue\n    markets = book.get(&quot;markets&quot;) or {}\n    stamps = [ts(p[&quot;changedAt&quot;]) for m in markets.values() for o in m[&quot;outcomes&quot;].values()\n              for p in o[&quot;players&quot;].values() if p.get(&quot;changedAt&quot;)]\n    if not stamps or (now - max(stamps)).total_seconds() &gt; 3600:   # whole feed gone quiet\n        continue\n    legs = (markets.get(&quot;131&quot;) or {}).get(&quot;outcomes&quot;, {})\n    try:\n        home, away = legs[&quot;131&quot;][&quot;players&quot;][&quot;0&quot;], legs[&quot;132&quot;][&quot;players&quot;][&quot;0&quot;]\n    except KeyError:\n        continue\n    # Read the price-level flag. marketActive is false on fresh, live prices here.\n    if home.get(&quot;active&quot;) is False or away.get(&quot;active&quot;) is False:\n        continue\n    if 1 \/ home[&quot;price&quot;] + 1 \/ away[&quot;price&quot;] &lt;= 1.0:                # one book never arbs itself\n        continue\n    quotes[slug] = (home[&quot;price&quot;], away[&quot;price&quot;])\n\nmed_h = statistics.median(q[0] for q in quotes.values())\nmed_a = statistics.median(q[1] for q in quotes.values())\nquotes = {s: q for s, q in quotes.items()\n          if abs(q[0] \/ med_h - 1) &lt;= 0.10 and abs(q[1] \/ med_a - 1) &lt;= 0.10}\n\ngroups = defaultdict(list)                                         # dedupe on the price pair\nfor slug, q in quotes.items():\n    groups[q].append(slug)\n\ndef margin(q):\n    return 100 * (1 \/ q[0] + 1 \/ q[1] - 1)\n\nfair_home = statistics.median((1 \/ h) \/ (1 \/ h + 1 \/ a) for h, a in groups)\nprint(f&quot;{len(quotes)} books, {len(groups)} distinct price pairs&quot;)\nprint(f&quot;deduped consensus: Brewers {fair_home:.1%}  Rays {1 - fair_home:.1%}&quot;)\nprint(&quot;tightest pairs:&quot;)\nfor q in sorted(groups, key=margin)[:6]:\n    print(f&quot;  {q[0]:&gt;6} \/ {q[1]:&lt;6} {margin(q):5.2f}%  {&#x27;, &#x27;.join(sorted(groups[q])[:4])}&quot;)\nfor slug in (&quot;pinnacle&quot;, &quot;fanduel&quot;, &quot;draftkings&quot;, &quot;bet365&quot;):\n    if slug in quotes:\n        print(f&quot;  {slug:&lt;11} {quotes[slug][0]} \/ {quotes[slug][1]}  {margin(quotes[slug]):.2f}%&quot;)<\/code><\/pre>\n<p>Output on 23 October 2026, 13:35 UTC:<\/p>\n<pre class=\"wp-block-code\"><code>207 books, 62 distinct price pairs\ndeduped consensus: Brewers 63.0%  Rays 37.0%\ntightest pairs:\n   1.578 \/ 2.712   0.24%  sx.bet\n   1.587 \/ 2.667   0.51%  novig.us, polymarket.us\n   1.575 \/ 2.7     0.53%  prophetx\n    1.58 \/ 2.68    0.60%  betfair-ex, fair999-ex, orbitx, piwi247-ex\n   1.587 \/ 2.632   1.01%  kalshi, polymarket\n    1.54 \/ 2.7     1.97%  duel\n  pinnacle    1.549 \/ 2.66  2.15%\n  fanduel     1.51 \/ 2.64  4.10%\n  draftkings  1.505 \/ 2.62  4.61%\n  bet365      1.48 \/ 2.63  5.59%<\/code><\/pre>\n<p>207 books collapse to 62 distinct price pairs, because skins share feeds: 27 slugs quote the same 1.50 \/ 2.60, and Pinnacle&#8217;s price appears on eight slugs. The deduped consensus puts the Brewers at 63.0%; Pinnacle de-vigs to 63.2%. Five exchanges and prediction markets quote the pair at 0.60% or less, so for a fair price on a World Series game you anchor on them and Pinnacle rather than on the retail books at 4% to 5.6%. Our <a href=\"https:\/\/oddspapi.io\/blog\/consensus-odds-fair-odds-calculator-python\/\">consensus odds guide<\/a> covers the de-vig methods in full.<\/p>\n<h2>Step 3: Measure when each book opened a played game<\/h2>\n<p><code>\/v4\/historical-odds<\/code> returns every snapshot the feed recorded on a fixture, up to three bookmakers per call. Pass <code>outcomeId=131<\/code> and the payload shrinks to the home moneyline only: 81 to 203 KB for Pinnacle, DraftKings and FanDuel together on these games. Kalshi goes in its own call; at 1.5 to 7.3 MB per outcome on these games it is still small enough for a loop. The fixture endpoint gives you <code>trueEndTime<\/code>, the recorded end of each game.<\/p>\n<pre class=\"wp-block-code\"><code>import os, time, requests\nfrom datetime import datetime\n\nAPI_KEY = os.environ[&quot;ODDSPAPI_API_KEY&quot;]\nBASE = &quot;https:\/\/api.oddspapi.io\/v4&quot;\nNLCS = [&quot;id1300010975060874&quot;, &quot;id1300010975060876&quot;,       # Dodgers v Brewers, played\n        &quot;id1300010975060878&quot;, &quot;id1300010975060880&quot;]        # 12-16 Oct 2026\n\ndef get(path, **params):\n    params[&quot;apiKey&quot;] = API_KEY\n    for _ in range(5):\n        r = requests.get(f&quot;{BASE}\/{path}&quot;, params=params, timeout=180)\n        if r.status_code == 429:\n            time.sleep(r.json().get(&quot;error&quot;, {}).get(&quot;retryMs&quot;, 2000) \/ 1000 + 0.5)\n            continue\n        r.raise_for_status()\n        return r.json()\n    raise RuntimeError(f&quot;{path} kept returning 429&quot;)\n\ndef ts(s):\n    return datetime.fromisoformat(s.replace(&quot;Z&quot;, &quot;+00:00&quot;))\n\ndef first_quote(fixture_id, books):\n    # outcomeId=131 (home win) shrinks the payload from megabytes to kilobytes\n    hist = get(&quot;historical-odds&quot;, fixtureId=fixture_id, bookmakers=books, outcomeId=131)\n    time.sleep(4.6)\n    out = {}\n    for slug, book in hist[&quot;bookmakers&quot;].items():\n        snaps = book[&quot;markets&quot;][&quot;131&quot;][&quot;outcomes&quot;][&quot;131&quot;][&quot;players&quot;][&quot;0&quot;]\n        out[slug] = min(ts(s[&quot;createdAt&quot;]) for s in snaps)\n    return out\n\nprev_end = None\nfor n, fid in enumerate(NLCS, start=1):\n    meta = get(&quot;fixture&quot;, fixtureId=fid)\n    time.sleep(1.0)\n    opened = first_quote(fid, &quot;pinnacle,draftkings,fanduel&quot;)\n    opened.update(first_quote(fid, &quot;kalshi&quot;))\n    row = []\n    for slug in (&quot;pinnacle&quot;, &quot;draftkings&quot;, &quot;fanduel&quot;, &quot;kalshi&quot;):\n        if prev_end is None:\n            row.append(f&quot;{slug} {opened[slug]:%d %b %H:%M}&quot;)\n        else:\n            hours = (opened[slug] - prev_end).total_seconds() \/ 3600\n            row.append(f&quot;{slug} {hours:+.1f} h&quot;)\n    print(f&quot;Game {n}: &quot; + &quot; | &quot;.join(row))\n    prev_end = ts(meta[&quot;trueEndTime&quot;])<\/code><\/pre>\n<p>Output on 23 October 2026 (the NLCS, Dodgers v Brewers, played 12 to 16 October):<\/p>\n<pre class=\"wp-block-code\"><code>Game 1: pinnacle 08 Oct 14:17 | draftkings 08 Oct 09:08 | fanduel 08 Oct 09:11 | kalshi 08 Oct 23:46\nGame 2: pinnacle +0.6 h | draftkings +1.1 h | fanduel +1.1 h | kalshi -74.7 h\nGame 3: pinnacle +1.1 h | draftkings +1.5 h | fanduel +1.3 h | kalshi -102.0 h\nGame 4: pinnacle +6.4 h | draftkings +1.6 h | fanduel +1.4 h | kalshi -152.8 h<\/code><\/pre>\n<p>Swap in any series. The <a href=\"https:\/\/oddspapi.io\/blog\/historical-odds-api\/\">historical odds API guide<\/a> explains the closing-line cut and the three-book cap, and the <a href=\"https:\/\/oddspapi.io\/blog\/backtest-betting-model-free-historical-odds\/\">backtesting guide<\/a> shows how to turn the same calls into a season of closes.<\/p>\n<h2>Step 4: Price the next game before the books post it<\/h2>\n<p>Until the sportsbooks arrive, the prediction markets are the line. The snippet below reads them off the next game, de-vigs each feed, and prints the stake behind each side. Run it in a loop after the last out and it returns the full board once 20 sportsbooks have posted.<\/p>\n<pre class=\"wp-block-code\"><code>import os, time, requests\n\nAPI_KEY = os.environ[&quot;ODDSPAPI_API_KEY&quot;]\nBASE = &quot;https:\/\/api.oddspapi.io\/v4&quot;\nGAME_2 = &quot;id1300010975060816&quot;        # Brewers v Rays, first pitch 2026-10-25 00:00 UTC\nPREDICTION = {&quot;kalshi&quot;, &quot;polymarket&quot;, &quot;polymarket.us&quot;, &quot;novig.us&quot;, &quot;prophetx&quot;, &quot;sx.bet&quot;}\n\ndef read_board(fixture_id):\n    r = requests.get(f&quot;{BASE}\/odds&quot;, params={&quot;apiKey&quot;: API_KEY, &quot;fixtureId&quot;: fixture_id}, timeout=120)\n    r.raise_for_status()\n    return r.json().get(&quot;bookmakerOdds&quot;, {})\n\ndef early_line(books):\n    for slug in sorted(PREDICTION &amp; books.keys()):\n        legs = (books[slug].get(&quot;markets&quot;) or {}).get(&quot;131&quot;, {}).get(&quot;outcomes&quot;, {})\n        if &quot;131&quot; not in legs or &quot;132&quot; not in legs:\n            continue\n        h, a = legs[&quot;131&quot;][&quot;players&quot;][&quot;0&quot;], legs[&quot;132&quot;][&quot;players&quot;][&quot;0&quot;]\n        if h.get(&quot;active&quot;) is False or a.get(&quot;active&quot;) is False:\n            continue\n        fair = (1 \/ h[&quot;price&quot;]) \/ (1 \/ h[&quot;price&quot;] + 1 \/ a[&quot;price&quot;])\n        print(f&quot;  {slug:&lt;14} Brewers {h[&#x27;price&#x27;]:&lt;6} Rays {a[&#x27;price&#x27;]:&lt;6} &quot;\n              f&quot;no-vig Brewers {fair:.1%}  depth ${h.get(&#x27;limit&#x27;) or 0:,.0f} \/ ${a.get(&#x27;limit&#x27;) or 0:,.0f}&quot;)\n\ndef wait_for_sportsbooks(fixture_id, min_books=20, every=600, checks=36):\n    for _ in range(checks):\n        books = read_board(fixture_id)\n        sportsbooks = [s for s in books if s not in PREDICTION]\n        print(f&quot;{len(books)} feeds on the board, {len(sportsbooks)} sportsbooks&quot;)\n        if len(sportsbooks) &gt;= min_books:\n            return books\n        early_line(books)\n        time.sleep(every)\n    return None\n\nwait_for_sportsbooks(GAME_2, checks=1, every=0)<\/code><\/pre>\n<p>Output on 23 October 2026, 13:35 UTC, for Game 2:<\/p>\n<pre class=\"wp-block-code\"><code>3 feeds on the board, 0 sportsbooks\n  kalshi         Brewers 1.695  Rays 2.326  no-vig Brewers 57.8%  depth $793 \/ $344\n  polymarket     Brewers 1.667  Rays 2.326  no-vig Brewers 58.3%  depth $272 \/ $86\n  polymarket.us  Brewers 1.739  Rays 2.326  no-vig Brewers 57.2%  depth $145 \/ $212<\/code><\/pre>\n<p>The three feeds agree within 1.1 points on Game 2. Read the depth before you trust a number: a few hundred dollars per side sits behind these quotes two days out, against the 20,491 Pinnacle limit on the Brewers in Game 1 at the same moment. Quotes on the later games can read far off a fair pair, because those games may never be played: Polymarket&#8217;s Game 5 pair read 1.25 \/ 1.282, which implies 158%. Reject any two-way quote whose implied probabilities do not sum to about 100%. Our <a href=\"https:\/\/oddspapi.io\/blog\/polymarket-api-kalshi-api-vs-sportsbooks-the-developers-guide\/\">Polymarket and Kalshi API guide<\/a> covers both venues&#8217; market formats.<\/p>\n<p>Polling every ten minutes works, but the <a href=\"https:\/\/oddspapi.io\/blog\/websocket-odds-api-real-time-betting-data\/\">WebSocket feed<\/a> pushes each new book the moment it posts, inside that 41-minute window.<\/p>\n<h2>World Series odds API FAQ<\/h2>\n<h3>Is there a free World Series odds API?<\/h3>\n<p>Yes. OddsPapi&#8217;s free plan returns live moneylines, run lines and totals on every World Series game from 350+ bookmakers, prediction markets included, plus the full price history of every played postseason game. MLB is tournamentId 109; each game is its own fixture.<\/p>\n<h3>When do sportsbooks post odds for the next World Series game?<\/h3>\n<p>After the previous game ends. On 19 follow-on games of the 2026 MLB postseason, the first of Pinnacle, DraftKings and FanDuel posted the next game a median 41 minutes after the last out, and within 82 minutes every time. Kalshi listed 16 of those games before the previous game had finished.<\/p>\n<h3>Which book has the tightest World Series moneyline?<\/h3>\n<p>On Game 1, eleven hours out, the exchanges and prediction markets: SX Bet, Novig, Polymarket US, ProphetX and Betfair quoted the pair at 0.24% to 0.60%. Pinnacle quoted 2.15% with a 20,491 limit on the favourite. Pinnacle closed every 2026 playoff game between 1.82% and 2.24%.<\/p>\n<h3>Can I get the closing odds of past World Series and playoff games?<\/h3>\n<p>Yes. \/v4\/historical-odds returns every recorded snapshot for up to three bookmakers per call. Take the last price with active: true before the scheduled startTime. Pass outcomeId to cut the payload to one outcome.<\/p>\n<h3>Why does a World Series board show marketActive false on live prices?<\/h3>\n<p>Some feeds ship the flag as false on fresh, active quotes; on Game 1 that was 115 of 206 books with a live moneyline. Read the price-level active flag and each book&#8217;s newest changedAt instead.<\/p>\n<h2>Read the whole series from one key<\/h2>\n<p>Every call above runs on the free key: 350+ bookmakers under one schema, free historical odds on every played game, and a WebSocket feed for the hour after the last out. <a href=\"https:\/\/oddspapi.io\/en\/sign-up\">Get a free API key<\/a> and run Step 1 on tonight&#8217;s game.<\/p>\n<p><script type=\"application\/ld+json\">\n{\n  \"@context\": \"https:\/\/schema.org\",\n  \"@type\": \"FAQPage\",\n  \"mainEntity\": [\n    {\n      \"@type\": \"Question\",\n      \"name\": \"Is there a free World Series odds API?\",\n      \"acceptedAnswer\": {\n        \"@type\": \"Answer\",\n        \"text\": \"Yes. OddsPapi's free plan returns live moneylines, run lines and totals on every World Series game from 350+ bookmakers, prediction markets included, plus the full price history of every played postseason game. MLB is tournamentId 109; each game is its own fixture.\"\n      }\n    },\n    {\n      \"@type\": \"Question\",\n      \"name\": \"When do sportsbooks post odds for the next World Series game?\",\n      \"acceptedAnswer\": {\n        \"@type\": \"Answer\",\n        \"text\": \"After the previous game ends. On 19 follow-on games of the 2026 MLB postseason, the first of Pinnacle, DraftKings and FanDuel posted the next game a median 41 minutes after the last out, and within 82 minutes every time. Kalshi listed 16 of those games before the previous game had finished.\"\n      }\n    },\n    {\n      \"@type\": \"Question\",\n      \"name\": \"Which book has the tightest World Series moneyline?\",\n      \"acceptedAnswer\": {\n        \"@type\": \"Answer\",\n        \"text\": \"On Game 1, eleven hours out, the exchanges and prediction markets: SX Bet, Novig, Polymarket US, ProphetX and Betfair quoted the pair at 0.24% to 0.60%. Pinnacle quoted 2.15% with a 20,491 limit on the favourite. Pinnacle closed every 2026 playoff game between 1.82% and 2.24%.\"\n      }\n    },\n    {\n      \"@type\": \"Question\",\n      \"name\": \"Can I get the closing odds of past World Series and playoff games?\",\n      \"acceptedAnswer\": {\n        \"@type\": \"Answer\",\n        \"text\": \"Yes. \/v4\/historical-odds returns every recorded snapshot for up to three bookmakers per call. Take the last price with active: true before the scheduled startTime. Pass outcomeId to cut the payload to one outcome.\"\n      }\n    },\n    {\n      \"@type\": \"Question\",\n      \"name\": \"Why does a World Series board show marketActive false on live prices?\",\n      \"acceptedAnswer\": {\n        \"@type\": \"Answer\",\n        \"text\": \"Some feeds ship the flag as false on fresh, active quotes; on Game 1 that was 115 of 206 books with a live moneyline. Read the price-level active flag and each book's newest changedAt instead.\"\n      }\n    }\n  ]\n}\n<\/script><\/p>\n<p><!--\nFocus Keyphrase: world series odds api\nSEO Title: World Series Odds API: Price the Next Game 65 Hours Early\nMeta Description: World Series odds API data: sportsbooks opened each 2026 playoff game 41 minutes after the last one ended, and Kalshi opened it 65 hours sooner.\nSlug: world-series-odds-api\n--><\/p>\n","protected":false},"excerpt":{"rendered":"<p>World Series odds API data: sportsbooks opened each 2026 playoff game 41 minutes after the last one ended, and Kalshi opened it 65 hours sooner.<\/p>\n","protected":false},"author":2,"featured_media":5330,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7],"tags":[80,4,108,17,9,34,11,10],"class_list":["post-5329","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-how-to-guides","tag-baseball","tag-historical-odds","tag-kalshi","tag-mlb","tag-odds-api","tag-prediction-markets","tag-python","tag-sports-betting-api"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v26.4 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>World Series Odds API: Price the Next Game 65 Hours Early | OddsPapi Blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/oddspapi.io\/blog\/world-series-odds-api\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"World Series Odds API: Price the Next Game 65 Hours Early | OddsPapi Blog\" \/>\n<meta property=\"og:description\" content=\"World Series odds API data: sportsbooks opened each 2026 playoff game 41 minutes after the last one ended, and Kalshi opened it 65 hours sooner.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/oddspapi.io\/blog\/world-series-odds-api\/\" \/>\n<meta property=\"og:site_name\" content=\"OddsPapi Blog\" \/>\n<meta property=\"article:published_time\" content=\"2026-10-28T10:00:00+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/10\/world-series-odds-api.webp\" \/>\n\t<meta property=\"og:image:width\" content=\"1200\" \/>\n\t<meta property=\"og:image:height\" content=\"675\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/webp\" \/>\n<meta name=\"author\" content=\"Odds API Writer\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:image\" content=\"https:\/\/oddspapi.io\/logo-v2.webp\" \/>\n<meta name=\"twitter:creator\" content=\"@oddspapiapi\" \/>\n<meta name=\"twitter:site\" content=\"@oddspapiapi\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Odds API Writer\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"15 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/oddspapi.io\/blog\/world-series-odds-api\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/oddspapi.io\/blog\/world-series-odds-api\/\"},\"author\":{\"name\":\"Odds API Writer\",\"@id\":\"https:\/\/oddspapi.io\/blog\/#\/schema\/person\/b6f21e649c4f556f0a95c23a0f1efa13\"},\"headline\":\"World Series Odds API: Price the Next Game 65 Hours Early\",\"datePublished\":\"2026-10-28T10:00:00+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/oddspapi.io\/blog\/world-series-odds-api\/\"},\"wordCount\":1693,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/oddspapi.io\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/oddspapi.io\/blog\/world-series-odds-api\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/10\/world-series-odds-api.webp\",\"keywords\":[\"Baseball\",\"historical odds\",\"Kalshi\",\"MLB\",\"Odds API\",\"Prediction Markets\",\"Python\",\"Sports Betting API\"],\"articleSection\":[\"How To Guides\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/oddspapi.io\/blog\/world-series-odds-api\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/oddspapi.io\/blog\/world-series-odds-api\/\",\"url\":\"https:\/\/oddspapi.io\/blog\/world-series-odds-api\/\",\"name\":\"World Series Odds API: Price the Next Game 65 Hours Early | OddsPapi Blog\",\"isPartOf\":{\"@id\":\"https:\/\/oddspapi.io\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/oddspapi.io\/blog\/world-series-odds-api\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/oddspapi.io\/blog\/world-series-odds-api\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/10\/world-series-odds-api.webp\",\"datePublished\":\"2026-10-28T10:00:00+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/oddspapi.io\/blog\/world-series-odds-api\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/oddspapi.io\/blog\/world-series-odds-api\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/oddspapi.io\/blog\/world-series-odds-api\/#primaryimage\",\"url\":\"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/10\/world-series-odds-api.webp\",\"contentUrl\":\"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/10\/world-series-odds-api.webp\",\"width\":1200,\"height\":675,\"caption\":\"World Series Odds API\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/oddspapi.io\/blog\/world-series-odds-api\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/oddspapi.io\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"World Series Odds API: Price the Next Game 65 Hours Early\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/oddspapi.io\/blog\/#website\",\"url\":\"https:\/\/oddspapi.io\/blog\/\",\"name\":\"OddsPapi\",\"description\":\"Sports Odds API Tutorials &amp; Guides\",\"publisher\":{\"@id\":\"https:\/\/oddspapi.io\/blog\/#organization\"},\"alternateName\":\"Odds Papi\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/oddspapi.io\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/oddspapi.io\/blog\/#organization\",\"name\":\"OddsPapi\",\"url\":\"https:\/\/oddspapi.io\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/oddspapi.io\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2025\/11\/oddspapi.png\",\"contentUrl\":\"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2025\/11\/oddspapi.png\",\"width\":135,\"height\":135,\"caption\":\"OddsPapi\"},\"image\":{\"@id\":\"https:\/\/oddspapi.io\/blog\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/x.com\/oddspapiapi\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/oddspapi.io\/blog\/#\/schema\/person\/b6f21e649c4f556f0a95c23a0f1efa13\",\"name\":\"Odds API Writer\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/oddspapi.io\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/33b204f24af3d02e35b25ae730c0536121ca6a783fdb196e7611c9e49fcd13eb?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/33b204f24af3d02e35b25ae730c0536121ca6a783fdb196e7611c9e49fcd13eb?s=96&d=mm&r=g\",\"caption\":\"Odds API Writer\"},\"url\":\"https:\/\/oddspapi.io\/blog\/author\/andy-lavelle\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"World Series Odds API: Price the Next Game 65 Hours Early | OddsPapi Blog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/oddspapi.io\/blog\/world-series-odds-api\/","og_locale":"en_US","og_type":"article","og_title":"World Series Odds API: Price the Next Game 65 Hours Early | OddsPapi Blog","og_description":"World Series odds API data: sportsbooks opened each 2026 playoff game 41 minutes after the last one ended, and Kalshi opened it 65 hours sooner.","og_url":"https:\/\/oddspapi.io\/blog\/world-series-odds-api\/","og_site_name":"OddsPapi Blog","article_published_time":"2026-10-28T10:00:00+00:00","og_image":[{"width":1200,"height":675,"url":"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/10\/world-series-odds-api.webp","type":"image\/webp"}],"author":"Odds API Writer","twitter_card":"summary_large_image","twitter_image":"https:\/\/oddspapi.io\/logo-v2.webp","twitter_creator":"@oddspapiapi","twitter_site":"@oddspapiapi","twitter_misc":{"Written by":"Odds API Writer","Est. reading time":"15 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/oddspapi.io\/blog\/world-series-odds-api\/#article","isPartOf":{"@id":"https:\/\/oddspapi.io\/blog\/world-series-odds-api\/"},"author":{"name":"Odds API Writer","@id":"https:\/\/oddspapi.io\/blog\/#\/schema\/person\/b6f21e649c4f556f0a95c23a0f1efa13"},"headline":"World Series Odds API: Price the Next Game 65 Hours Early","datePublished":"2026-10-28T10:00:00+00:00","mainEntityOfPage":{"@id":"https:\/\/oddspapi.io\/blog\/world-series-odds-api\/"},"wordCount":1693,"commentCount":0,"publisher":{"@id":"https:\/\/oddspapi.io\/blog\/#organization"},"image":{"@id":"https:\/\/oddspapi.io\/blog\/world-series-odds-api\/#primaryimage"},"thumbnailUrl":"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/10\/world-series-odds-api.webp","keywords":["Baseball","historical odds","Kalshi","MLB","Odds API","Prediction Markets","Python","Sports Betting API"],"articleSection":["How To Guides"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/oddspapi.io\/blog\/world-series-odds-api\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/oddspapi.io\/blog\/world-series-odds-api\/","url":"https:\/\/oddspapi.io\/blog\/world-series-odds-api\/","name":"World Series Odds API: Price the Next Game 65 Hours Early | OddsPapi Blog","isPartOf":{"@id":"https:\/\/oddspapi.io\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/oddspapi.io\/blog\/world-series-odds-api\/#primaryimage"},"image":{"@id":"https:\/\/oddspapi.io\/blog\/world-series-odds-api\/#primaryimage"},"thumbnailUrl":"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/10\/world-series-odds-api.webp","datePublished":"2026-10-28T10:00:00+00:00","breadcrumb":{"@id":"https:\/\/oddspapi.io\/blog\/world-series-odds-api\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/oddspapi.io\/blog\/world-series-odds-api\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/oddspapi.io\/blog\/world-series-odds-api\/#primaryimage","url":"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/10\/world-series-odds-api.webp","contentUrl":"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/10\/world-series-odds-api.webp","width":1200,"height":675,"caption":"World Series Odds API"},{"@type":"BreadcrumbList","@id":"https:\/\/oddspapi.io\/blog\/world-series-odds-api\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/oddspapi.io\/blog\/"},{"@type":"ListItem","position":2,"name":"World Series Odds API: Price the Next Game 65 Hours Early"}]},{"@type":"WebSite","@id":"https:\/\/oddspapi.io\/blog\/#website","url":"https:\/\/oddspapi.io\/blog\/","name":"OddsPapi","description":"Sports Odds API Tutorials &amp; Guides","publisher":{"@id":"https:\/\/oddspapi.io\/blog\/#organization"},"alternateName":"Odds Papi","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/oddspapi.io\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/oddspapi.io\/blog\/#organization","name":"OddsPapi","url":"https:\/\/oddspapi.io\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/oddspapi.io\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2025\/11\/oddspapi.png","contentUrl":"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2025\/11\/oddspapi.png","width":135,"height":135,"caption":"OddsPapi"},"image":{"@id":"https:\/\/oddspapi.io\/blog\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/x.com\/oddspapiapi"]},{"@type":"Person","@id":"https:\/\/oddspapi.io\/blog\/#\/schema\/person\/b6f21e649c4f556f0a95c23a0f1efa13","name":"Odds API Writer","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/oddspapi.io\/blog\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/33b204f24af3d02e35b25ae730c0536121ca6a783fdb196e7611c9e49fcd13eb?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/33b204f24af3d02e35b25ae730c0536121ca6a783fdb196e7611c9e49fcd13eb?s=96&d=mm&r=g","caption":"Odds API Writer"},"url":"https:\/\/oddspapi.io\/blog\/author\/andy-lavelle\/"}]}},"_links":{"self":[{"href":"https:\/\/oddspapi.io\/blog\/wp-json\/wp\/v2\/posts\/5329","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/oddspapi.io\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/oddspapi.io\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/oddspapi.io\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/oddspapi.io\/blog\/wp-json\/wp\/v2\/comments?post=5329"}],"version-history":[{"count":1,"href":"https:\/\/oddspapi.io\/blog\/wp-json\/wp\/v2\/posts\/5329\/revisions"}],"predecessor-version":[{"id":5331,"href":"https:\/\/oddspapi.io\/blog\/wp-json\/wp\/v2\/posts\/5329\/revisions\/5331"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/oddspapi.io\/blog\/wp-json\/wp\/v2\/media\/5330"}],"wp:attachment":[{"href":"https:\/\/oddspapi.io\/blog\/wp-json\/wp\/v2\/media?parent=5329"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/oddspapi.io\/blog\/wp-json\/wp\/v2\/categories?post=5329"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/oddspapi.io\/blog\/wp-json\/wp\/v2\/tags?post=5329"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}