{"id":4992,"date":"2026-10-20T10:00:00","date_gmt":"2026-10-20T10:00:00","guid":{"rendered":"https:\/\/oddspapi.io\/blog\/?p=4992"},"modified":"2026-10-12T13:25:52","modified_gmt":"2026-10-12T13:25:52","slug":"nba-prediction-market-api","status":"publish","type":"post","link":"https:\/\/oddspapi.io\/blog\/nba-prediction-market-api\/","title":{"rendered":"NBA Prediction Market API: Pinnacle Holds 3x the Spread Depth"},"content":{"rendered":"<p>The NBA tips off on 20 October 2026, and six exchange venues already price the opener: Kalshi, Polymarket US, Novig, Betfair Exchange, SX Bet and Duel. On 21 September Novig, Betfair Exchange, Polymarket and ProphetX had no NBA price at all; Kalshi and SX Bet did. If you plan to trade NBA on a prediction market this season, the question is where the depth sits, because the price alone will not tell you.<\/p>\n<p>We pulled every priced board for opening week, 18 fixtures from 20 to 24 October, through one OddsPapi key on 12 October at 13:13 UTC, eight days before the first tip. On the moneyline, the exchanges rival the sharpest sportsbook: Kalshi&#8217;s ladder holds 1,474 on the thin side against Pinnacle&#8217;s 1,350 limit. On the spread, the market NBA bettors live on, the deepest exchange rung holds 702 and Pinnacle takes 2,341. Every number below comes from those calls.<\/p>\n<h2>The Finding in One Table<\/h2>\n<p>For each venue and each of the three main markets, this is the median stake you could place on the thinner side of the main rung, across the opening-week boards where the venue had a two-sided active quote. &#8220;Thin side&#8221; means the worse of the two outcomes, because that side caps a hedge or an arbitrage. The count in brackets is the number of boards. Pinnacle is the sportsbook benchmark; its number is the <code>limit<\/code> field, the largest stake it accepts in one bet.<\/p>\n<figure class=\"wp-block-table\">\n<table>\n<thead>\n<tr>\n<th>Venue<\/th>\n<th>Moneyline<\/th>\n<th>Spread<\/th>\n<th>Total<\/th>\n<th>Ladder levels<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>kalshi<\/code><\/td>\n<td>1,474 (3)<\/td>\n<td>no market<\/td>\n<td>no market<\/td>\n<td>3<\/td>\n<\/tr>\n<tr>\n<td><code>pinnacle<\/code><\/td>\n<td>1,350 (12)<\/td>\n<td>2,341 (12)<\/td>\n<td>894 (12)<\/td>\n<td>limit only<\/td>\n<\/tr>\n<tr>\n<td><code>novig.us<\/code><\/td>\n<td>587 (14)<\/td>\n<td>702 (14)<\/td>\n<td>648 (13)<\/td>\n<td>1 to 2<\/td>\n<\/tr>\n<tr>\n<td><code>sx.bet<\/code><\/td>\n<td>400 (11)<\/td>\n<td>78 (12)<\/td>\n<td>290 (11)<\/td>\n<td>1<\/td>\n<\/tr>\n<tr>\n<td><code>betfair-ex<\/code><\/td>\n<td>376 (16)<\/td>\n<td>91 (16)<\/td>\n<td>211 (15)<\/td>\n<td>3<\/td>\n<\/tr>\n<tr>\n<td><code>polymarket.us<\/code><\/td>\n<td>0 (13)<\/td>\n<td>0 (8)<\/td>\n<td>0 (4)<\/td>\n<td>1<\/td>\n<\/tr>\n<tr>\n<td><code>duel<\/code><\/td>\n<td>not published (18)<\/td>\n<td>not published (18)<\/td>\n<td>not published (18)<\/td>\n<td>none<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/figure>\n<p>Read the moneyline column first. Kalshi beats Pinnacle on the three boards it prices, and Novig came within reach on the three opening-night boards (832, 1,400 and 1,710). Then read the spread column. Novig&#8217;s 702 is the best any exchange offers, and Pinnacle takes 3.3 times that. Betfair lists around 50 spread rungs a board, and its main rung holds a median 91 on the thin side. SX Bet holds 78. Kalshi lists no NBA spread at all eight days out.<\/p>\n<p>So the NBA exchange board is a moneyline board. If your model prices the spread, the size is still at the sportsbook, and the <a href=\"https:\/\/oddspapi.io\/blog\/nba-opening-night-odds-api\/\">opening-night board of 217 books<\/a> is where you shop it.<\/p>\n<h2>Why a Price Feed Hides This<\/h2>\n<p>Most odds feeds return one price per outcome per venue. A prediction market can post a tight number with ten dollars behind it, and the feed reports the tight number. Polymarket US quotes the opener&#8217;s moneyline at a 4.00% overround and every rung of its ladder carries a stake of zero. Duel posts 321 spread rungs at a 3.10% margin and publishes no depth field at all. A price-only screener ranks both of them above Pinnacle.<\/p>\n<p>OddsPapi returns the venue&#8217;s own ladder next to the price, under <code>exchangeMeta<\/code>, and the sportsbook&#8217;s maximum stake under <code>limit<\/code>. Three ladder shapes ship on the v4 feed, and each venue sticks to one:<\/p>\n<ul>\n<li><strong>Betfair network<\/strong> (<code>betfair-ex<\/code>): <code>availableToBack<\/code> and <code>availableToLay<\/code>, each level <code>{price, size}<\/code>. <code>size<\/code> is the stake available.<\/li>\n<li><strong>Prediction markets<\/strong> (<code>kalshi<\/code>, <code>novig.us<\/code>, <code>polymarket.us<\/code>): <code>back<\/code> and <code>lay<\/code>, each level <code>{cents, limit, price, size}<\/code>. <code>limit<\/code> is the stake, <code>size<\/code> is the payout, <code>cents<\/code> is the share price.<\/li>\n<li><strong>Limit only<\/strong> (<code>sx.bet<\/code>): <code>back<\/code> and <code>lay<\/code> with <code>{cents, limit, price}<\/code> and no <code>size<\/code>.<\/li>\n<\/ul>\n<p>On the opener Kalshi&#8217;s Celtics side reads 1.923 for 606, then 1.887 for 1,149, then 1.852 for 333. Novig&#8217;s Celtics side reads 1.852 for 1,829 and 1.786 for 756. Betfair&#8217;s Pistons side reads 2.02 for 284, 2.00 for 358 and 1.90 for 21. One parser handles all three shapes, and it is the first thing in the tutorial below.<\/p>\n<figure class=\"wp-block-table\">\n<table>\n<thead>\n<tr>\n<th>Job<\/th>\n<th>Venue APIs one by one<\/th>\n<th>OddsPapi<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Opening-week NBA slate<\/td>\n<td>One schedule per venue, matched by hand<\/td>\n<td>One <code>\/fixtures<\/code> call on <code>tournamentId<\/code> 132<\/td>\n<\/tr>\n<tr>\n<td>Prices on one fixture<\/td>\n<td>Six venue calls, six auth schemes<\/td>\n<td>258 bookmakers in one <code>\/odds<\/code> response<\/td>\n<\/tr>\n<tr>\n<td>Depth behind the price<\/td>\n<td>Kalshi order book, Betfair <code>listMarketBook<\/code>, Polymarket CLOB, Novig signed REST<\/td>\n<td><code>exchangeMeta<\/code> ladder on the same price object<\/td>\n<\/tr>\n<tr>\n<td>Sportsbook benchmark<\/td>\n<td>Pinnacle&#8217;s API needs a commercial account<\/td>\n<td><code>pinnacle<\/code> with its <code>limit<\/code>, same call<\/td>\n<\/tr>\n<tr>\n<td>Price moves during the game<\/td>\n<td>Poll each venue<\/td>\n<td><a href=\"https:\/\/oddspapi.io\/blog\/websocket-odds-api-real-time-betting-data\/\">WebSocket<\/a> push<\/td>\n<\/tr>\n<tr>\n<td>Cost<\/td>\n<td>Exchange API keys, Betfair app key, Pinnacle account<\/td>\n<td>Free tier<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/figure>\n<h2>Step 1: Find the Opening-Week Board<\/h2>\n<p>Basketball is <code>sportId<\/code> 11 and the NBA is <code>tournamentId<\/code> 132. Pass both to <code>\/fixtures<\/code>. The <code>to<\/code> date is a midnight-UTC instant, so ask for the day after the last day you want. The first call also pulls the opener&#8217;s full board without a bookmaker filter, which is how you learn which exchange venues have opened a fixture: pass a slug the venue has not priced and the response comes back 200 with the slug missing, so a presence check on the unfiltered board is the cheaper test.<\/p>\n<pre class=\"wp-block-code\"><code>import os, requests\n\nAPI_KEY = os.environ[&quot;ODDSPAPI_API_KEY&quot;]\nBASE = &quot;https:\/\/api.oddspapi.io\/v4&quot;\nEXCHANGES = [&quot;kalshi&quot;, &quot;polymarket&quot;, &quot;polymarket.us&quot;, &quot;novig.us&quot;,\n             &quot;prophetx&quot;, &quot;betfair-ex&quot;, &quot;sx.bet&quot;, &quot;duel&quot;, &quot;myriad&quot;]\n\n# NBA is tournamentId 132 inside basketball (sportId 11).\nfixtures = requests.get(f&quot;{BASE}\/fixtures&quot;, params={\n    &quot;apiKey&quot;: API_KEY, &quot;sportId&quot;: 11, &quot;tournamentId&quot;: 132,\n    &quot;from&quot;: &quot;2026-10-20&quot;, &quot;to&quot;: &quot;2026-10-25&quot;,   # &quot;to&quot; is a midnight-UTC instant\n}).json()\nboard = sorted((f for f in fixtures if f[&quot;hasOdds&quot;]), key=lambda f: f[&quot;startTime&quot;])\nprint(len(board), &quot;priced NBA fixtures, 20 to 24 October&quot;)\n\nopener = board[0]\nodds = requests.get(f&quot;{BASE}\/odds&quot;, params={\n    &quot;apiKey&quot;: API_KEY, &quot;fixtureId&quot;: opener[&quot;fixtureId&quot;], &quot;oddsFormat&quot;: &quot;decimal&quot;,\n}).json()\nbooks = {s: b for s, b in odds[&quot;bookmakerOdds&quot;].items() if &quot;+&quot; not in s and s != &quot;demo&quot;}\nprint(opener[&quot;participant1Name&quot;], &quot;v&quot;, opener[&quot;participant2Name&quot;], opener[&quot;startTime&quot;])\nprint(len(books), &quot;bookmakers on the opener&quot;)\nprint(&quot;exchange venues present:&quot;, [s for s in EXCHANGES if s in books])<\/code><\/pre>\n<pre class=\"wp-block-code\"><code>18 priced NBA fixtures, 20 to 24 October\nDetroit Pistons v Boston Celtics 2026-10-20T19:00:00.000Z\n258 bookmakers on the opener\nexchange venues present: [&#x27;kalshi&#x27;, &#x27;polymarket.us&#x27;, &#x27;novig.us&#x27;, &#x27;betfair-ex&#x27;, &#x27;sx.bet&#x27;, &#x27;duel&#x27;]<\/code><\/pre>\n<p>Three venues the catalogue lists did not appear on any of the 18 boards: <code>polymarket<\/code>, <code>prophetx<\/code> and <code>myriad<\/code>. Each returns 200 with the slug missing, which is the venue&#8217;s own opening schedule rather than a gated feed. A gated slug returns 403 and a misspelled one 400, so read the status code before you conclude anything about coverage.<\/p>\n<h2>Step 2: Parse the Three Ladder Shapes<\/h2>\n<p>Save this file as <code>s2_ladder.py<\/code>; the later steps import from it. <code>read_ladder<\/code> takes the price object at <code>players[\"0\"]<\/code> and returns the back ladder as a list of <code>(price, stake)<\/code> pairs, best price first, plus a label for the shape it found. The <code>get<\/code> helper honours the <code>retryMs<\/code> the API sends on a 429.<\/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;\nFIXTURE = &quot;id1100013273682354&quot;   # Detroit v Boston, 20 Oct 19:00 UTC\nVENUES = [&quot;kalshi&quot;, &quot;polymarket.us&quot;, &quot;novig.us&quot;, &quot;betfair-ex&quot;, &quot;sx.bet&quot;, &quot;duel&quot;]\n\n\ndef get(path, **params):\n    &quot;&quot;&quot;GET with the 429 retry the API asks for (retryMs in the error body).&quot;&quot;&quot;\n    while True:\n        r = requests.get(f&quot;{BASE}{path}&quot;, params={&quot;apiKey&quot;: API_KEY, **params})\n        if r.status_code != 429:\n            return r.json()\n        time.sleep(r.json()[&quot;error&quot;].get(&quot;retryMs&quot;, 2000) \/ 1000 + 0.5)\n\n\ndef read_ladder(price_obj):\n    &quot;&quot;&quot;Return (levels, shape). levels = [(price, stake), ...], best price first.\n\n    Three ladder shapes ship on v4, and each venue sticks to one:\n      Betfair network : availableToBack \/ availableToLay, each level {price, size}\n      prediction market: back \/ lay, each level {cents, limit, price, size}\n      limit-only       : back \/ lay, each level {cents, limit, price}, no size\n    &quot;stake&quot; is the money you can put down at that level: Betfair publishes it as\n    size, the prediction markets as limit.\n    &quot;&quot;&quot;\n    meta = price_obj.get(&quot;exchangeMeta&quot;) or {}\n    if &quot;availableToBack&quot; in meta:\n        return [(l[&quot;price&quot;], l.get(&quot;size&quot;) or 0.0) for l in meta[&quot;availableToBack&quot;]], &quot;betfair&quot;\n    if &quot;back&quot; in meta:\n        levels = meta[&quot;back&quot;]\n        shape = &quot;prediction&quot; if levels and &quot;size&quot; in levels[0] else &quot;limit-only&quot;\n        return [(l[&quot;price&quot;], l.get(&quot;limit&quot;) or 0.0) for l in levels], shape\n    return [], &quot;none&quot;\n\n\nif __name__ == &quot;__main__&quot;:\n    odds = get(&quot;\/odds&quot;, fixtureId=FIXTURE, oddsFormat=&quot;decimal&quot;, bookmakers=&quot;,&quot;.join(VENUES))\n    print(f&quot;{&#x27;venue&#x27;:14s} {&#x27;shape&#x27;:11s} {&#x27;home&#x27;:&gt;6s} {&#x27;away&#x27;:&gt;6s} {&#x27;margin&#x27;:&gt;7s} {&#x27;thin top&#x27;:&gt;9s} {&#x27;thin ladder&#x27;:&gt;12s}&quot;)\n    for venue in VENUES:\n        book = odds[&quot;bookmakerOdds&quot;].get(venue)\n        if not book or &quot;111&quot; not in book[&quot;markets&quot;]:\n            continue\n        legs = []\n        for outcome in book[&quot;markets&quot;][&quot;111&quot;][&quot;outcomes&quot;].values():\n            p = outcome[&quot;players&quot;][&quot;0&quot;]          # game markets key the price object &quot;0&quot;\n            levels, shape = read_ladder(p)\n            legs.append((p[&quot;price&quot;], levels[0][1] if levels else None,\n                         sum(s for _, s in levels) if levels else None, shape))\n        home, away = sorted(legs, key=lambda l: l[0])  # just for a stable print order\n        margin = (1 \/ home[0] + 1 \/ away[0] - 1) * 100\n        thin_top = min(l[1] for l in legs) if None not in [l[1] for l in legs] else None\n        thin_full = min(l[2] for l in legs) if None not in [l[2] for l in legs] else None\n        fmt = lambda v: f&quot;{v:,.2f}&quot; if v is not None else &quot;n\/a&quot;\n        print(f&quot;{venue:14s} {home[3]:11s} {home[0]:6.3f} {away[0]:6.3f} {margin:6.2f}% {fmt(thin_top):&gt;9s} {fmt(thin_full):&gt;12s}&quot;)<\/code><\/pre>\n<pre class=\"wp-block-code\"><code>venue          shape         home   away  margin  thin top  thin ladder\nkalshi         prediction   1.923  2.041   1.00%    120.54       688.06\npolymarket.us  prediction   1.818  2.041   4.00%      0.00         0.00\nnovig.us       prediction   1.852  1.961   4.99%    831.50       831.50\nbetfair-ex     betfair      1.870  2.020   2.98%      3.50       291.02\nsx.bet         limit-only   1.706  1.923  10.62%    430.13       430.13\nduel           none         1.840  2.100   1.97%       n\/a          n\/a<\/code><\/pre>\n<p>Kalshi&#8217;s 1.00% is the tightest moneyline on the whole 258-book opener, and the thin side holds 688 over three levels. Betfair&#8217;s 2.98% is the next tightest exchange, with 3.50 at the top of the Pistons ladder and 291 once you take all three levels. SX Bet&#8217;s 10.62% is the price of a single resting order per side. Novig&#8217;s 4.99% at 832 a side was two levels deep on one outcome and one on the other.<\/p>\n<h3>The guard that drops Kalshi<\/h3>\n<p>On the opener Kalshi&#8217;s moneyline market carries <code>marketActive: false<\/code> while both prices are <code>active: true<\/code>, the ladder holds stake on every level, and <code>changedAt<\/code> is seconds old. The same pattern shows on 8 of the 240 two-sided exchange and Pinnacle quotes across the slate, 3 on Kalshi and 5 on Novig. A guard built for a sportsbook board, where <code>marketActive<\/code> is the flag that separates a parked line from a traded one, drops the tightest quote on the board. On an exchange, read the ladder and the age of the quote instead: a populated ladder with a fresh <code>changedAt<\/code> is live.<\/p>\n<h2>Step 3: Score Depth by Market Family<\/h2>\n<p>The moneyline is one market ID, 111. The spread and the total are ladders of rungs, one market ID each, and the line lives in the <code>handicap<\/code> field of <code>\/markets<\/code>. Basketball ships the second half and the fourth quarter on two clocks, so key every definition on <code>(period, handicap)<\/code> and select the full-game families on <code>period == \"result\"<\/code>. The main rung is each venue&#8217;s most balanced two-sided quote inside a 1.5 to 2.6 price band; never trust the <code>mainLine<\/code> flag, because a venue sets it on its own schedule. The <a href=\"https:\/\/oddspapi.io\/blog\/nba-alternate-lines-api\/\">NBA alternate lines post<\/a> covers the 722-rung ladders in full.<\/p>\n<pre class=\"wp-block-code\"><code># s3_family.py\nimport os, requests\nfrom s2_ladder import read_ladder, get\n\nAPI_KEY = os.environ[&quot;ODDSPAPI_API_KEY&quot;]\nBASE = &quot;https:\/\/api.oddspapi.io\/v4&quot;\nFIXTURE = &quot;id1100013273682354&quot;\nVENUES = [&quot;kalshi&quot;, &quot;polymarket.us&quot;, &quot;novig.us&quot;, &quot;betfair-ex&quot;, &quot;sx.bet&quot;, &quot;pinnacle&quot;]\n\n# Key every basketball definition on (period, handicap). Basketball ships the second\n# half and the fourth quarter on two clocks, so the market name alone is not enough.\ndefs = {d[&quot;marketId&quot;]: d for d in get(&quot;\/markets&quot;) if d[&quot;sportId&quot;] == 11}\nFAMILY = {\n    &quot;moneyline&quot;: lambda d: d[&quot;marketId&quot;] == 111,\n    &quot;spread&quot;:    lambda d: d[&quot;marketName&quot;] == &quot;Handicap (incl. overtime)&quot; and d[&quot;period&quot;] == &quot;result&quot;,\n    &quot;total&quot;:     lambda d: d[&quot;marketName&quot;] == &quot;Over Under (incl. overtime)&quot; and d[&quot;period&quot;] == &quot;result&quot;,\n}\n\n\ndef two_sided(market):\n    legs = [o[&quot;players&quot;][&quot;0&quot;] for o in market[&quot;outcomes&quot;].values()]\n    return legs if len(legs) == 2 and all(l[&quot;active&quot;] and l[&quot;price&quot;] &gt; 1 for l in legs) else None\n\n\ndef main_rung(book, family):\n    &quot;&quot;&quot;The venue&#x27;s most balanced rung inside a [1.5, 2.6] price band. Never mainLine.&quot;&quot;&quot;\n    rungs = []\n    for mid, market in book[&quot;markets&quot;].items():\n        d = defs.get(int(mid))\n        legs = two_sided(market) if d and FAMILY[family](d) else None\n        if legs and (family == &quot;moneyline&quot; or all(1.5 &lt;= l[&quot;price&quot;] &lt;= 2.6 for l in legs)):\n            rungs.append((abs(legs[0][&quot;price&quot;] - legs[1][&quot;price&quot;]), d[&quot;handicap&quot;], legs))\n    return min(rungs)[1:] if rungs else (None, None)\n\n\ndef thin_side(legs):\n    &quot;&quot;&quot;Stake on the thinner side: the exchange ladder summed, or the sportsbook limit.&quot;&quot;&quot;\n    depth = []\n    for l in legs:\n        levels, _ = read_ladder(l)\n        depth.append(sum(s for _, s in levels) if levels else l.get(&quot;limit&quot;))\n    return min(depth) if None not in depth else None\n\n\nif __name__ == &quot;__main__&quot;:\n    odds = get(&quot;\/odds&quot;, fixtureId=FIXTURE, oddsFormat=&quot;decimal&quot;, bookmakers=&quot;,&quot;.join(VENUES))\n    print(f&quot;{&#x27;venue&#x27;:14s} {&#x27;family&#x27;:10s} {&#x27;line&#x27;:&gt;6s} {&#x27;margin&#x27;:&gt;7s} {&#x27;thin-side stake&#x27;:&gt;16s}&quot;)\n    for venue in VENUES:\n        book = odds[&quot;bookmakerOdds&quot;].get(venue)\n        if not book:\n            continue\n        for family in FAMILY:\n            line, legs = main_rung(book, family)\n            if legs is None:\n                print(f&quot;{venue:14s} {family:10s} {&#x27;-&#x27;:&gt;6s} {&#x27;-&#x27;:&gt;7s} {&#x27;no two-sided rung&#x27;:&gt;16s}&quot;)\n                continue\n            margin = (1 \/ legs[0][&quot;price&quot;] + 1 \/ legs[1][&quot;price&quot;] - 1) * 100\n            stake = thin_side(legs)\n            print(f&quot;{venue:14s} {family:10s} {line:6.1f} {margin:6.2f}% {stake if stake is None else f&#x27;{stake:,.0f}&#x27;:&gt;16}&quot;)<\/code><\/pre>\n<pre class=\"wp-block-code\"><code>venue          family       line  margin  thin-side stake\nkalshi         moneyline     0.0   1.00%              688\nkalshi         spread          -       - no two-sided rung\nkalshi         total           -       - no two-sided rung\npolymarket.us  moneyline     0.0   4.00%                0\npolymarket.us  spread          -       - no two-sided rung\npolymarket.us  total           -       - no two-sided rung\nnovig.us       moneyline     0.0   4.99%              832\nnovig.us       spread       -1.5   7.49%              679\nnovig.us       total       221.5   7.99%              567\nbetfair-ex     moneyline     0.0   2.98%              291\nbetfair-ex     spread       -2.0  10.82%               43\nbetfair-ex     total       221.5  10.80%              345\nsx.bet         moneyline     0.0  10.62%              430\nsx.bet         spread       -1.5  10.61%               48\nsx.bet         total       221.5  10.62%              297\npinnacle       moneyline     0.0   2.86%            1,350\npinnacle       spread       -2.0   2.93%            2,319\npinnacle       total       221.5   3.41%              894<\/code><\/pre>\n<p>This is the opener on its own, and the pattern of the slate is already visible. Novig lists five spread rungs and holds 679 on the thin side at -1.5. Betfair lists 24 spread rungs on this board and its main rung at -2.0 holds 43 on one side and 45 on the other, a single level each. Pinnacle sits at -2.0 for 2,319. On the total, every venue agrees on 221.5, and the stake runs 567 at Novig, 345 at Betfair, 297 at SX Bet and 894 at Pinnacle.<\/p>\n<h2>Step 4: Run the Slate<\/h2>\n<p>Eighteen boards, one call each with a bookmaker filter, one second apart. The API rate-limits parallel calls to <code>\/odds<\/code>, so loop; the filtered payloads are small and the whole run takes under a minute.<\/p>\n<pre class=\"wp-block-code\"><code># s4_slate.py\nimport os, time, statistics, requests\nfrom s2_ladder import read_ladder, get\nfrom s3_family import main_rung, thin_side, FAMILY, BASE, API_KEY\n\nVENUES = [&quot;kalshi&quot;, &quot;polymarket.us&quot;, &quot;novig.us&quot;, &quot;betfair-ex&quot;, &quot;sx.bet&quot;, &quot;pinnacle&quot;]\nfixtures = get(&quot;\/fixtures&quot;, sportId=11, tournamentId=132, **{&quot;from&quot;: &quot;2026-10-20&quot;, &quot;to&quot;: &quot;2026-10-25&quot;})\nboard = [f for f in fixtures if f[&quot;hasOdds&quot;]]\n\nstakes = {}   # (venue, family) -&gt; [thin-side stake per board]\nfor f in board:\n    odds = get(&quot;\/odds&quot;, fixtureId=f[&quot;fixtureId&quot;], oddsFormat=&quot;decimal&quot;, bookmakers=&quot;,&quot;.join(VENUES))\n    for venue, book in odds.get(&quot;bookmakerOdds&quot;, {}).items():\n        for family in FAMILY:\n            _, legs = main_rung(book, family)\n            if legs:\n                stake = thin_side(legs)\n                if stake is not None:\n                    stakes.setdefault((venue, family), []).append(stake)\n    time.sleep(1.0)   # never parallelise \/odds\n\nprint(f&quot;{len(board)} boards. Median thin-side stake on the main rung (boards with a two-sided quote)&quot;)\nprint(f&quot;{&#x27;venue&#x27;:14s} {&#x27;moneyline&#x27;:&gt;14s} {&#x27;spread&#x27;:&gt;14s} {&#x27;total&#x27;:&gt;14s}&quot;)\nfor venue in VENUES:\n    cells = []\n    for family in FAMILY:\n        v = stakes.get((venue, family), [])\n        cells.append(f&quot;{statistics.median(v):,.0f} ({len(v)})&quot; if v else &quot;-&quot;)\n    print(f&quot;{venue:14s} {cells[0]:&gt;14s} {cells[1]:&gt;14s} {cells[2]:&gt;14s}&quot;)<\/code><\/pre>\n<pre class=\"wp-block-code\"><code>18 boards. Median thin-side stake on the main rung (boards with a two-sided quote)\nvenue               moneyline         spread          total\nkalshi              1,474 (3)              -              -\npolymarket.us          0 (13)          0 (8)          0 (4)\nnovig.us             587 (14)       702 (14)       648 (13)\nbetfair-ex           376 (16)        91 (16)       211 (15)\nsx.bet               400 (11)        78 (12)       290 (11)\npinnacle           1,350 (12)     2,341 (12)       894 (12)<\/code><\/pre>\n<p>That output is the table at the top of the post. Three details from the slate are worth writing down before you build on it.<\/p>\n<p><strong>Kalshi opened the three opening-night games and nothing else.<\/strong> Detroit v Boston, New York v Philadelphia and San Antonio v Oklahoma City carry a Kalshi moneyline; the eleven games on 21 October and the four after them do not, eight days out. Novig was on 14 boards, Betfair on 16, SX Bet on 12 and Duel on all 18. Four boards drew 146 to 151 bookmakers against 240 to 258 on the rest, and Pinnacle, Novig and SX Bet were absent from all four. The books open the slate fixture by fixture, so re-run the presence check the day before each tip.<\/p>\n<p><strong>Pinnacle&#8217;s limits are flat pre-season defaults.<\/strong> The moneyline limit is 1,350 on all 12 boards. The spread limit runs 2,295 to 2,363 and the total 886 to 903. Those numbers will move once the board gets traded, so treat them as the floor of what the sharp book takes, and read them again on game day.<\/p>\n<p><strong>Two venues ship a price with no usable depth.<\/strong> Polymarket US quotes 13 boards and every rung carries <code>limit: 0<\/code> and <code>size: 0<\/code>, with the venue flagged <code>bookmakerIsActive: false<\/code>. Duel quotes 663 market IDs on the opener, the full ladder the crypto and offshore sportsbooks post, with no <code>limit<\/code> and no <code>exchangeMeta<\/code>. Score both on price if you like, but do not size a position off either.<\/p>\n<h2>Where the Exchanges Sit Among 258 Books<\/h2>\n<p>Run the full opener board through the sportsbook guard (<code>suspended<\/code>, <code>bookmakerIsActive<\/code>, <code>marketActive<\/code> and the price-level <code>active<\/code> flag) and 122 books survive on the moneyline. Dedupe on the price pair and those 122 collapse to 28 distinct quotes. Pinnacle is sixth at 2.86%, level with seven feeds that mirror it. Betfair Exchange is ninth at 2.98%, with four Asian feeds that clone its book. Novig is 48th, SX Bet 120th. Kalshi, Polymarket US and Duel fall out of the guard, Kalshi on <code>marketActive<\/code> and the other two on <code>bookmakerIsActive<\/code>. The <a href=\"https:\/\/oddspapi.io\/blog\/nfl-prediction-market-liquidity\/\">NFL version of this study<\/a> found depth rankings close to the reverse of price rankings. On NBA, the exchange that leads on price is also the one that leads on moneyline depth, and the inversion sits between the moneyline and the spread instead.<\/p>\n<p>If you size stakes off a sharp price, the <a href=\"https:\/\/oddspapi.io\/blog\/betting-limits-api-stake-sizing\/\">betting limits guide<\/a> explains what <code>limit<\/code> means book by book, and the <a href=\"https:\/\/oddspapi.io\/blog\/novig-api-odds-access\/\">Novig API post<\/a> walks the <code>novig.us<\/code> ladder on a 191-market NFL board, where the same venue quoted a 0.50% moneyline. Its NBA pre-season board sits at 7.0%, which is what a resting-order book looks like before the flow arrives.<\/p>\n<h2>What This Looks Like on Game Day<\/h2>\n<p>The ladder is live only. Once a fixture tips and settles, <code>\/historical-odds<\/code> keeps every price snapshot and the <code>limit<\/code> on each, but <code>exchangeMeta<\/code> comes back null on history. We checked on Game 5 of the June 2026 Finals: Novig&#8217;s history holds 83 markets, a <code>limit<\/code> on every snapshot (1,909 to 3,847 on the first six moneyline prices) and a null ladder throughout. So the ramp from eight days out to tip-off is one number wide per venue. Store the ladder yourself if you want it: poll <code>\/odds<\/code> with the venue filter, or take the <a href=\"https:\/\/oddspapi.io\/blog\/websocket-odds-api-real-time-betting-data\/\">WebSocket<\/a> and write each change as it lands. On opening night, that is the dataset no venue will sell you afterwards.<\/p>\n<h2>Read the Ladder Before the First Tip<\/h2>\n<p>One free OddsPapi key returns 258 bookmakers on the NBA opener, six exchange venues with their order-book ladders, Pinnacle with its limit, and the history to grade all of it after the game. <a href=\"https:\/\/oddspapi.io\/en\/sign-up\">Get a free API key<\/a>, run the slate script on 19 October, and know where the size is before the Celtics and Pistons walk out.<\/p>\n<h2>FAQ<\/h2>\n<h3>Which prediction markets have NBA odds through the API?<\/h3>\n<p>On 12 October 2026, eight days before the opener, six exchange venues priced NBA fixtures on OddsPapi: Kalshi, Polymarket US, Novig, Betfair Exchange, SX Bet and Duel. Kalshi quoted the three opening-night games, Betfair 16 of the 18 priced boards, Novig 14, Polymarket US 13, SX Bet 12 and Duel all 18.<\/p>\n<h3>Does Kalshi offer NBA spreads and totals?<\/h3>\n<p>Eight days before opening night Kalshi listed one NBA market per fixture, the moneyline, on the three opening-night games. Its ladder ran three levels deep and held a median 1,474 on the thin side, more than Pinnacle&#8217;s 1,350 limit. Spreads and totals on the exchanges came from Novig, Betfair Exchange and SX Bet.<\/p>\n<h3>How does Novig&#8217;s NBA liquidity compare with Kalshi&#8217;s?<\/h3>\n<p>On the three opening-night boards both venues priced, Novig held 832, 1,400 and 1,710 on the thin side of the moneyline against Kalshi&#8217;s median 1,474, at a wider price: Novig 5.0% to 7.0% overround on a one- or two-level ladder, Kalshi 1.0% on three levels. Novig also lists five spread rungs and seven total rungs, which Kalshi does not.<\/p>\n<h3>Which API streams consolidated order-book depth across sports in real time?<\/h3>\n<p>OddsPapi returns the back and lay ladder of each exchange venue under exchangeMeta on the same price object as the sportsbook quotes, across every sport the venue lists, and pushes each change over a WebSocket. The ladder is live only; historical snapshots keep the price and the limit field.<\/p>\n<h3>How do I measure the depth of a betting market from an odds API?<\/h3>\n<p>Take the main rung of each market, read the back ladder on both outcomes, sum the stake across the levels, and keep the smaller side. That thin-side stake is what caps a hedge or an arbitrage. Compare it with the sportsbook&#8217;s limit field on the same rung; on the NBA opener Pinnacle&#8217;s spread limit was 2,341 and the deepest exchange spread rung held 679.<\/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\": \"Which prediction markets have NBA odds through the API?\",\n      \"acceptedAnswer\": {\n        \"@type\": \"Answer\",\n        \"text\": \"On 12 October 2026, eight days before the opener, six exchange venues priced NBA fixtures on OddsPapi: Kalshi, Polymarket US, Novig, Betfair Exchange, SX Bet and Duel. Kalshi quoted the three opening-night games, Betfair 16 of the 18 priced boards, Novig 14, Polymarket US 13, SX Bet 12 and Duel all 18.\"\n      }\n    },\n    {\n      \"@type\": \"Question\",\n      \"name\": \"Does Kalshi offer NBA spreads and totals?\",\n      \"acceptedAnswer\": {\n        \"@type\": \"Answer\",\n        \"text\": \"Eight days before opening night Kalshi listed one NBA market per fixture, the moneyline, on the three opening-night games. Its ladder ran three levels deep and held a median 1,474 on the thin side, more than Pinnacle's 1,350 limit. Spreads and totals on the exchanges came from Novig, Betfair Exchange and SX Bet.\"\n      }\n    },\n    {\n      \"@type\": \"Question\",\n      \"name\": \"How does Novig's NBA liquidity compare with Kalshi's?\",\n      \"acceptedAnswer\": {\n        \"@type\": \"Answer\",\n        \"text\": \"On the three opening-night boards both venues priced, Novig held 832, 1,400 and 1,710 on the thin side of the moneyline against Kalshi's median 1,474, at a wider price: Novig 5.0% to 7.0% overround on a one- or two-level ladder, Kalshi 1.0% on three levels. Novig also lists five spread rungs and seven total rungs, which Kalshi does not.\"\n      }\n    },\n    {\n      \"@type\": \"Question\",\n      \"name\": \"Which API streams consolidated order-book depth across sports in real time?\",\n      \"acceptedAnswer\": {\n        \"@type\": \"Answer\",\n        \"text\": \"OddsPapi returns the back and lay ladder of each exchange venue under exchangeMeta on the same price object as the sportsbook quotes, across every sport the venue lists, and pushes each change over a WebSocket. The ladder is live only; historical snapshots keep the price and the limit field.\"\n      }\n    },\n    {\n      \"@type\": \"Question\",\n      \"name\": \"How do I measure the depth of a betting market from an odds API?\",\n      \"acceptedAnswer\": {\n        \"@type\": \"Answer\",\n        \"text\": \"Take the main rung of each market, read the back ladder on both outcomes, sum the stake across the levels, and keep the smaller side. That thin-side stake is what caps a hedge or an arbitrage. Compare it with the sportsbook's limit field on the same rung; on the NBA opener Pinnacle's spread limit was 2,341 and the deepest exchange spread rung held 679.\"\n      }\n    }\n  ]\n}\n<\/script><\/p>\n<p><!--\nSEO\nFocus keyphrase: nba prediction market api\nTitle: NBA Prediction Market API: Pinnacle Holds 3x the Spread Depth\nMeta description: Depth from an NBA prediction market API on 18 opening boards: Kalshi holds 1,474 a side on the moneyline, Pinnacle 1,350, the best exchange spread rung 702.\nSlug: nba-prediction-market-api\n--><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Depth from an NBA prediction market API on 18 opening boards: Kalshi holds 1,474 a side on the moneyline, Pinnacle 1,350, the best exchange spread rung 702.<\/p>\n","protected":false},"author":2,"featured_media":4993,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7],"tags":[75,101,16,9,34,11,10],"class_list":["post-4992","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-how-to-guides","tag-basketball","tag-betting-exchange","tag-nba","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>NBA Prediction Market API: Pinnacle Holds 3x the Spread Depth | 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\/nba-prediction-market-api\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"NBA Prediction Market API: Pinnacle Holds 3x the Spread Depth | OddsPapi Blog\" \/>\n<meta property=\"og:description\" content=\"Depth from an NBA prediction market API on 18 opening boards: Kalshi holds 1,474 a side on the moneyline, Pinnacle 1,350, the best exchange spread rung 702.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/oddspapi.io\/blog\/nba-prediction-market-api\/\" \/>\n<meta property=\"og:site_name\" content=\"OddsPapi Blog\" \/>\n<meta property=\"article:published_time\" content=\"2026-10-20T10:00:00+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/10\/nba-prediction-market-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=\"19 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/oddspapi.io\/blog\/nba-prediction-market-api\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/oddspapi.io\/blog\/nba-prediction-market-api\/\"},\"author\":{\"name\":\"Odds API Writer\",\"@id\":\"https:\/\/oddspapi.io\/blog\/#\/schema\/person\/b6f21e649c4f556f0a95c23a0f1efa13\"},\"headline\":\"NBA Prediction Market API: Pinnacle Holds 3x the Spread Depth\",\"datePublished\":\"2026-10-20T10:00:00+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/oddspapi.io\/blog\/nba-prediction-market-api\/\"},\"wordCount\":2110,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/oddspapi.io\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/oddspapi.io\/blog\/nba-prediction-market-api\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/10\/nba-prediction-market-api.webp\",\"keywords\":[\"Basketball\",\"Betting Exchange\",\"NBA\",\"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\/nba-prediction-market-api\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/oddspapi.io\/blog\/nba-prediction-market-api\/\",\"url\":\"https:\/\/oddspapi.io\/blog\/nba-prediction-market-api\/\",\"name\":\"NBA Prediction Market API: Pinnacle Holds 3x the Spread Depth | OddsPapi Blog\",\"isPartOf\":{\"@id\":\"https:\/\/oddspapi.io\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/oddspapi.io\/blog\/nba-prediction-market-api\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/oddspapi.io\/blog\/nba-prediction-market-api\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/10\/nba-prediction-market-api.webp\",\"datePublished\":\"2026-10-20T10:00:00+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/oddspapi.io\/blog\/nba-prediction-market-api\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/oddspapi.io\/blog\/nba-prediction-market-api\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/oddspapi.io\/blog\/nba-prediction-market-api\/#primaryimage\",\"url\":\"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/10\/nba-prediction-market-api.webp\",\"contentUrl\":\"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/10\/nba-prediction-market-api.webp\",\"width\":1200,\"height\":675,\"caption\":\"NBA Prediction Market API: Pinnacle Holds 3x the Spread Depth\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/oddspapi.io\/blog\/nba-prediction-market-api\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/oddspapi.io\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"NBA Prediction Market API: Pinnacle Holds 3x the Spread Depth\"}]},{\"@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":"NBA Prediction Market API: Pinnacle Holds 3x the Spread Depth | 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\/nba-prediction-market-api\/","og_locale":"en_US","og_type":"article","og_title":"NBA Prediction Market API: Pinnacle Holds 3x the Spread Depth | OddsPapi Blog","og_description":"Depth from an NBA prediction market API on 18 opening boards: Kalshi holds 1,474 a side on the moneyline, Pinnacle 1,350, the best exchange spread rung 702.","og_url":"https:\/\/oddspapi.io\/blog\/nba-prediction-market-api\/","og_site_name":"OddsPapi Blog","article_published_time":"2026-10-20T10:00:00+00:00","og_image":[{"width":1200,"height":675,"url":"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/10\/nba-prediction-market-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":"19 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/oddspapi.io\/blog\/nba-prediction-market-api\/#article","isPartOf":{"@id":"https:\/\/oddspapi.io\/blog\/nba-prediction-market-api\/"},"author":{"name":"Odds API Writer","@id":"https:\/\/oddspapi.io\/blog\/#\/schema\/person\/b6f21e649c4f556f0a95c23a0f1efa13"},"headline":"NBA Prediction Market API: Pinnacle Holds 3x the Spread Depth","datePublished":"2026-10-20T10:00:00+00:00","mainEntityOfPage":{"@id":"https:\/\/oddspapi.io\/blog\/nba-prediction-market-api\/"},"wordCount":2110,"commentCount":0,"publisher":{"@id":"https:\/\/oddspapi.io\/blog\/#organization"},"image":{"@id":"https:\/\/oddspapi.io\/blog\/nba-prediction-market-api\/#primaryimage"},"thumbnailUrl":"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/10\/nba-prediction-market-api.webp","keywords":["Basketball","Betting Exchange","NBA","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\/nba-prediction-market-api\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/oddspapi.io\/blog\/nba-prediction-market-api\/","url":"https:\/\/oddspapi.io\/blog\/nba-prediction-market-api\/","name":"NBA Prediction Market API: Pinnacle Holds 3x the Spread Depth | OddsPapi Blog","isPartOf":{"@id":"https:\/\/oddspapi.io\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/oddspapi.io\/blog\/nba-prediction-market-api\/#primaryimage"},"image":{"@id":"https:\/\/oddspapi.io\/blog\/nba-prediction-market-api\/#primaryimage"},"thumbnailUrl":"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/10\/nba-prediction-market-api.webp","datePublished":"2026-10-20T10:00:00+00:00","breadcrumb":{"@id":"https:\/\/oddspapi.io\/blog\/nba-prediction-market-api\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/oddspapi.io\/blog\/nba-prediction-market-api\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/oddspapi.io\/blog\/nba-prediction-market-api\/#primaryimage","url":"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/10\/nba-prediction-market-api.webp","contentUrl":"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/10\/nba-prediction-market-api.webp","width":1200,"height":675,"caption":"NBA Prediction Market API: Pinnacle Holds 3x the Spread Depth"},{"@type":"BreadcrumbList","@id":"https:\/\/oddspapi.io\/blog\/nba-prediction-market-api\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/oddspapi.io\/blog\/"},{"@type":"ListItem","position":2,"name":"NBA Prediction Market API: Pinnacle Holds 3x the Spread Depth"}]},{"@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\/4992","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=4992"}],"version-history":[{"count":2,"href":"https:\/\/oddspapi.io\/blog\/wp-json\/wp\/v2\/posts\/4992\/revisions"}],"predecessor-version":[{"id":4995,"href":"https:\/\/oddspapi.io\/blog\/wp-json\/wp\/v2\/posts\/4992\/revisions\/4995"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/oddspapi.io\/blog\/wp-json\/wp\/v2\/media\/4993"}],"wp:attachment":[{"href":"https:\/\/oddspapi.io\/blog\/wp-json\/wp\/v2\/media?parent=4992"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/oddspapi.io\/blog\/wp-json\/wp\/v2\/categories?post=4992"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/oddspapi.io\/blog\/wp-json\/wp\/v2\/tags?post=4992"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}