{"id":4352,"date":"2026-09-30T10:00:00","date_gmt":"2026-09-30T10:00:00","guid":{"rendered":"https:\/\/oddspapi.io\/blog\/?p=4352"},"modified":"2026-09-21T13:26:53","modified_gmt":"2026-09-21T13:26:53","slug":"nba-second-half-odds-api","status":"publish","type":"post","link":"https:\/\/oddspapi.io\/blog\/nba-second-half-odds-api\/","title":{"rendered":"NBA Second Half Odds API: 90 Lines Carry Two Settlement Rules"},"content":{"rendered":"<p>An NBA second-half total of 104.5 is two different bets. One settles on the points scored in the third and fourth quarters. The other counts overtime as well. Both carry the line number 104.5, both read as a totals market, and different bookmakers quote different ones.<\/p>\n<p>The OddsPapi catalogue separates them with a field called <code>period<\/code>. Read it and the two bets separate. Skip it and a cross-book comparison lines up a regulation bet against an overtime bet and calls the gap an edge. Every number below comes from a call made on 21 September 2026.<\/p>\n<h2>Basketball Runs on Ten Clocks<\/h2>\n<p>One call to <code>\/v4\/markets<\/code> returns 33,115 definitions across every sport. Filter on <code>sportId: 11<\/code> and 4,902 of them are basketball. Group those by <code>period<\/code>.<\/p>\n<figure class=\"wp-block-table\">\n<table>\n<thead>\n<tr>\n<th><code>period<\/code><\/th>\n<th>Settles on<\/th>\n<th>Definitions<\/th>\n<th>What lives there<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>result<\/code><\/td>\n<td>the final score, overtime included<\/td>\n<td>1,205<\/td>\n<td>the two-way Winner, 401 totals, 321 spreads, every player prop<\/td>\n<\/tr>\n<tr>\n<td><code>p3+p4+overtime<\/code><\/td>\n<td>the second half plus overtime<\/td>\n<td>781<\/td>\n<td>180 totals, 201 spreads, 400 team totals<\/td>\n<\/tr>\n<tr>\n<td><code>p1+p2<\/code><\/td>\n<td>the first half<\/td>\n<td>691<\/td>\n<td>90 totals, 201 spreads, 400 team totals<\/td>\n<\/tr>\n<tr>\n<td><code>p1<\/code><\/td>\n<td>the first quarter<\/td>\n<td>609<\/td>\n<td>totals, spreads, team totals, first-quarter player props<\/td>\n<\/tr>\n<tr>\n<td><code>p4+overtime<\/code><\/td>\n<td>the fourth quarter plus overtime<\/td>\n<td>521<\/td>\n<td>100 totals, 141 spreads, 280 team totals<\/td>\n<\/tr>\n<tr>\n<td><code>p2<\/code><\/td>\n<td>the second quarter<\/td>\n<td>473<\/td>\n<td>totals, spreads, team totals<\/td>\n<\/tr>\n<tr>\n<td><code>p3<\/code><\/td>\n<td>the third quarter<\/td>\n<td>473<\/td>\n<td>totals, spreads, team totals<\/td>\n<\/tr>\n<tr>\n<td><code>p3+p4<\/code><\/td>\n<td>the second half, 48 minutes only<\/td>\n<td>90<\/td>\n<td>totals and nothing else<\/td>\n<\/tr>\n<tr>\n<td><code>p4<\/code><\/td>\n<td>the fourth quarter, 48 minutes only<\/td>\n<td>52<\/td>\n<td>50 totals, a three-way result, a two-way winner<\/td>\n<\/tr>\n<tr>\n<td><code>fulltime<\/code><\/td>\n<td>the score after 48 minutes<\/td>\n<td>1<\/td>\n<td>market <code>113<\/code>, Regular Time Result, with a draw leg<\/td>\n<\/tr>\n<tr>\n<td><code>null<\/code><\/td>\n<td>unset<\/td>\n<td>6<\/td>\n<td>First Half Result, Second Half Result and four others<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/figure>\n<p>Two rows in that table shadow two other rows. <code>p3+p4<\/code> is the second half without overtime and <code>p3+p4+overtime<\/code> is the second half with it. <code>p4<\/code> and <code>p4+overtime<\/code> do the same job for the fourth quarter. The first half needs no twin, because overtime cannot reach it.<\/p>\n<h3>Every Regulation Line Number Has an Overtime Twin<\/h3>\n<p>Pull the handicap values off both ladders and the collision is total.<\/p>\n<figure class=\"wp-block-table\">\n<table>\n<thead>\n<tr>\n<th>Ladder<\/th>\n<th>Rungs<\/th>\n<th>Span<\/th>\n<th>Step<\/th>\n<th>Line numbers shared with the twin<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Over Under Second Half<\/td>\n<td>90<\/td>\n<td>40.5 to 129.5<\/td>\n<td>1.0<\/td>\n<td>90 of 90<\/td>\n<\/tr>\n<tr>\n<td>Over Under Second Half (incl. overtime)<\/td>\n<td>180<\/td>\n<td>40.5 to 130.0<\/td>\n<td>0.5<\/td>\n<td>90 of 180<\/td>\n<\/tr>\n<tr>\n<td>Over Under Fourth Quarter<\/td>\n<td>50<\/td>\n<td>20.5 to 69.5<\/td>\n<td>1.0<\/td>\n<td>50 of 50<\/td>\n<\/tr>\n<tr>\n<td>Over Under Fourth Quarter (incl. overtime)<\/td>\n<td>100<\/td>\n<td>20.5 to 70.0<\/td>\n<td>0.5<\/td>\n<td>50 of 100<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/figure>\n<p>The regulation ladders are half-point rungs in steps of a full point. The overtime ladders take the same half-point rungs and add the whole numbers between them. Sort a merged board by line number and the two clocks interleave without a single duplicate to warn you.<\/p>\n<p>The market name does carry the clock, in the suffix <code>(incl. overtime)<\/code>. That suffix is the only thing separating the names, so any normaliser that strips parentheses, lowercases and trims will fuse the two ladders into one. Match on <code>period<\/code>, which is a short enum, rather than on a string you have to clean.<\/p>\n<h3>Old Way vs OddsPapi<\/h3>\n<figure class=\"wp-block-table\">\n<table>\n<thead>\n<tr>\n<th>Job<\/th>\n<th>Scraping or a single-book feed<\/th>\n<th>OddsPapi<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Tell a regulation half from an overtime half<\/td>\n<td>Parse the market&#8217;s display name and hope<\/td>\n<td>Read <code>period<\/code> on <code>\/v4\/markets<\/code><\/td>\n<\/tr>\n<tr>\n<td>List every second-half line a book offers<\/td>\n<td>Walk one sportsbook&#8217;s markup<\/td>\n<td>Filter 4,902 definitions on two enum values<\/td>\n<\/tr>\n<tr>\n<td>Compare the 104.5 across books<\/td>\n<td>Match on the number and merge two bets<\/td>\n<td>Key on <code>(period, handicap)<\/code><\/td>\n<\/tr>\n<tr>\n<td>Check what a closed market paid<\/td>\n<td>No history, so no check<\/td>\n<td><code>\/historical-odds<\/code> on the free tier<\/td>\n<\/tr>\n<tr>\n<td>Grade it after the buzzer<\/td>\n<td>Scrape a scoreboard<\/td>\n<td><code>\/v4\/scores<\/code> returns every quarter as its own key<\/td>\n<\/tr>\n<tr>\n<td>Price<\/td>\n<td>Proxies, breakage, legal risk<\/td>\n<td>Free tier, 250 requests a month, no card<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/figure>\n<h2>Step 1: Print the Clock Map<\/h2>\n<p>Authentication is a query parameter. The key rides on <code>?apiKey=<\/code> and never in a header.<\/p>\n<pre class=\"wp-block-code\"><code>import os, requests, collections\n\nAPI_KEY = os.environ[\"ODDSPAPI_API_KEY\"]\nBASE_URL = \"https:\/\/api.oddspapi.io\/v4\"\n\nmarkets = requests.get(f\"{BASE_URL}\/markets\", params={\"apiKey\": API_KEY}).json()\nbasketball = [m for m in markets if m[\"sportId\"] == 11]\n\nclocks = collections.Counter(str(m[\"period\"]) for m in basketball)\nfor period, count in clocks.most_common():\n    print(f\"{period:18} {count:>5} market definitions\")\n\nprint(f\"\\n{len(basketball)} basketball market definitions in all\")<\/code><\/pre>\n<pre class=\"wp-block-code\"><code>result              1205 market definitions\np3+p4+overtime       781 market definitions\np1+p2                691 market definitions\np1                   609 market definitions\np4+overtime          521 market definitions\np2                   473 market definitions\np3                   473 market definitions\np3+p4                 90 market definitions\np4                    52 market definitions\nNone                   6 market definitions\nfulltime               1 market definitions\n\n4902 basketball market definitions in all<\/code><\/pre>\n<p><code>\/v4\/markets<\/code> ignores a <code>sportId<\/code> parameter and hands back all 33,115 definitions, so filter on the client. Six of the basketball definitions carry <code>period: None<\/code>, among them Second Half Result and First Half Result. A dictionary keyed straight on <code>period<\/code> will trip over those six, so coerce the value before you use it as a key.<\/p>\n<h2>Step 2: Find the Twin Ladders<\/h2>\n<p>Group the definitions by <code>marketName<\/code>, then look for any name that also exists with the <code>(incl. overtime)<\/code> suffix.<\/p>\n<pre class=\"wp-block-code\"><code>ladders = collections.defaultdict(set)\nfor m in basketball:\n    ladders[m[\"marketName\"]].add(m[\"handicap\"])\n\nSUFFIX = \" (incl. overtime)\"\nfor name in sorted(ladders):\n    twin = name + SUFFIX\n    if twin not in ladders:\n        continue\n    regulation, overtime = ladders[name], ladders[twin]\n    print(f\"{name}\")\n    print(f\"  regulation clock : {len(regulation):>3} lines, {min(regulation)} to {max(regulation)}\")\n    print(f\"  overtime clock   : {len(overtime):>3} lines, {min(overtime)} to {max(overtime)}\")\n    print(f\"  line numbers on both: {len(regulation &amp; overtime)}\\n\")<\/code><\/pre>\n<pre class=\"wp-block-code\"><code>Over Under Fourth Quarter\n  regulation clock :  50 lines, 20.5 to 69.5\n  overtime clock   : 100 lines, 20.5 to 70.0\n  line numbers on both: 50\n\nOver Under Second Half\n  regulation clock :  90 lines, 40.5 to 129.5\n  overtime clock   : 180 lines, 40.5 to 130.0\n  line numbers on both: 90<\/code><\/pre>\n<p>Two ladders, 140 regulation line numbers, and all 140 appear again on the overtime clock. Spreads and team totals dodge the problem by existing on the overtime clock alone: <code>p3+p4<\/code> carries 90 totals and nothing else, and <code>p4<\/code> carries 50 totals plus a three-way result and a two-way winner. Ask for a regulation second-half spread and no book has one to sell you.<\/p>\n<h2>Step 3: Split a Live Board by Clock<\/h2>\n<p>Detroit Pistons v Boston Celtics opens the 2026-27 season on 20 October. One unfiltered <code>\/v4\/odds<\/code> call on it returned 9.23 MB at 13:09 UTC on 21 September, 29 days out.<\/p>\n<pre class=\"wp-block-code\"><code>FIXTURE = \"id1100013273682354\"   # Detroit Pistons v Boston Celtics, 20 Oct 2026\n\nclock = {str(m[\"marketId\"]): m[\"period\"] for m in basketball}\n\nboard = requests.get(f\"{BASE_URL}\/odds\",\n                     params={\"apiKey\": API_KEY, \"fixtureId\": FIXTURE}).json()\n\nids = collections.defaultdict(set)\nbooks = collections.defaultdict(set)\nfor slug, book in board[\"bookmakerOdds\"].items():\n    for market_id in book.get(\"markets\", {}):\n        period = clock.get(market_id, \"UNKNOWN\") or \"null\"   # 6 definitions ship period None\n        ids[period].add(market_id)\n        books[period].add(slug)\n\nprint(f\"{len(board['bookmakerOdds'])} bookmakers on the fixture\\n\")\nfor period in sorted(ids, key=lambda p: -len(ids[p])):\n    print(f\"{period:14} {len(ids[period]):>4} market IDs  {len(books[period]):>4} bookmakers\")<\/code><\/pre>\n<pre class=\"wp-block-code\"><code>221 bookmakers on the fixture\n\nresult          526 market IDs   220 bookmakers\np1+p2             4 market IDs     4 bookmakers\nfulltime          1 market IDs    65 bookmakers<\/code><\/pre>\n<p>Twenty-nine days out, four market IDs sit on a half or quarter clock. The <code>result<\/code> clock holds 526 of the 531 priced IDs and 220 of the 221 books. Market <code>113<\/code>, Regular Time Result, draws 65 books on its own: that is the three-way bet on the 48-minute score, draw leg included, and it settles differently from the two-way Winner that 220 books quote on the same fixture. Both markets read the same scoreline and they pay out under different rules.<\/p>\n<p>The quarter and half ladders fill in during the days before tip-off, which is where the trap sits. A resolver written against a T-29d board never meets the twin clocks, then meets both of them an hour before the first jump ball. Build the branch now and test it on a fixture that has already finished.<\/p>\n<h2>Step 4: Read the Twins on a Played Fixture<\/h2>\n<p>A live board outside the market-open window reports a false zero, so test coverage on a game that has been played. San Antonio Spurs v New York Knicks, Game 5 of the 2026 Finals, tipped at 00:30 UTC on 14 June. <code>\/historical-odds<\/code> keeps the full menu after the buzzer and takes at most three bookmaker slugs a call.<\/p>\n<pre class=\"wp-block-code\"><code>FIXTURE = \"id1100013270505012\"   # San Antonio v New York, tipped 14 Jun 2026 00:30 UTC\nTIP_OFF = \"2026-06-14T00:30:00.000Z\"\nNAMES = (\"Over Under Second Half\", \"Over Under Second Half (incl. overtime)\")\n\ndefs = {str(m[\"marketId\"]): m for m in basketball}\n\nhistory = requests.get(f\"{BASE_URL}\/historical-odds\",\n                       params={\"apiKey\": API_KEY, \"fixtureId\": FIXTURE,\n                               \"bookmakers\": \"caesars,betrivers,draftkings\"}).json()\n\ndef closing(snapshots):\n    live = [s for s in snapshots if s[\"active\"] and s[\"createdAt\"] &lt; TIP_OFF]\n    return live[-1][\"price\"] if live else None\n\nrows = collections.defaultdict(dict)\nfor slug, book in history[\"bookmakers\"].items():\n    for market_id, market in book.get(\"markets\", {}).items():\n        spec = defs.get(market_id)\n        if not spec or spec[\"marketName\"] not in NAMES:\n            continue\n        labels = {str(o[\"outcomeId\"]): o[\"outcomeName\"] for o in spec[\"outcomes\"]}\n        quote = {}\n        for outcome_id, outcome in market.get(\"outcomes\", {}).items():\n            price = closing(outcome[\"players\"][\"0\"])   # a LIST on this endpoint\n            if price:\n                quote[labels[outcome_id]] = price\n        if len(quote) == 2:\n            rows[spec[\"handicap\"]][slug] = (spec[\"period\"], quote)\n\nfor line in sorted(rows):\n    for slug, (period, quote) in sorted(rows[line].items()):\n        print(f\"{line:>6}  {slug:&lt;11} {period:&lt;15} Over {quote['Over']:&lt;6} Under {quote['Under']}\")<\/code><\/pre>\n<pre class=\"wp-block-code\"><code> 103.5  caesars     p3+p4           Over 1.833  Under 1.909\n 104.5  betrivers   p3+p4+overtime  Over 1.84   Under 1.92\n 104.5  caesars     p3+p4           Over 1.909  Under 1.833\n 105.5  betrivers   p3+p4+overtime  Over 1.92   Under 1.84\n 105.5  caesars     p3+p4           Over 1.909  Under 1.833\n 106.5  betrivers   p3+p4+overtime  Over 1.93   Under 1.83<\/code><\/pre>\n<p>Caesars closed 104.5 on the regulation clock at 1.909 and BetRivers closed 104.5 on the overtime clock at 1.84. Merge on the line number and Caesars reads as a 3.8% better price on the Over. The two quotes are not competing, because they settle on different scores. Caesars ran 6.94% overround across all three of its rungs and BetRivers ran 6.43%, so the margin gap does not explain the price gap either.<\/p>\n<p>The split runs deeper than one line. Across the eleven books read on that fixture, DraftKings priced the second half on both clocks, 25 market IDs on <code>p3+p4<\/code> and 24 on <code>p3+p4+overtime<\/code>. Pinnacle priced 17 second-half IDs and 27 fourth-quarter IDs, every one of them on the overtime clock and none on regulation. Caesars went the other way on the second half. Rank a second-half board across those three books without branching and you rank three different bets.<\/p>\n<h2>Step 5: Grade Both Clocks<\/h2>\n<p><code>\/v4\/scores<\/code> returns each quarter under its own key, so you can build either settlement figure yourself.<\/p>\n<pre class=\"wp-block-code\"><code>periods = requests.get(f\"{BASE_URL}\/scores\",\n                       params={\"apiKey\": API_KEY, \"fixtureId\": FIXTURE}\n                       ).json()[\"scores\"][\"periods\"]\n\ndef total(key):\n    p = periods[key]\n    return p[\"participant1Score\"] + p[\"participant2Score\"]\n\nq3_q4 = total(\"p3\") + total(\"p4\")                          # p3+p4\nsecond_half_with_ot = total(\"result\") - total(\"p1\") - total(\"p2\")   # p3+p4+overtime\n\nprint(f\"quarters       {total('p1')} \/ {total('p2')} \/ {total('p3')} \/ {total('p4')}\")\nprint(f\"regulation     {total('fulltime')}\")\nprint(f\"final          {total('result')}\")\nprint(f\"p3+p4          {q3_q4}\")\nprint(f\"p3+p4+overtime {second_half_with_ot}\")\n\nfor line in (103.5, 104.5, 105.5, 106.5):\n    reg = \"Over\" if q3_q4 &gt; line else \"Under\"\n    ot = \"Over\" if second_half_with_ot &gt; line else \"Under\"\n    print(f\"{line:>6}  p3+p4 {reg:&lt;5}  p3+p4+overtime {ot}\")<\/code><\/pre>\n<pre class=\"wp-block-code\"><code>quarters       36 \/ 43 \/ 58 \/ 47\nregulation     184\nfinal          184\np3+p4          105\np3+p4+overtime 105\n 103.5  p3+p4 Over   p3+p4+overtime Over\n 104.5  p3+p4 Over   p3+p4+overtime Over\n 105.5  p3+p4 Under  p3+p4+overtime Under\n 106.5  p3+p4 Under  p3+p4+overtime Under<\/code><\/pre>\n<p>Game 5 finished in regulation, so <code>fulltime<\/code> and <code>result<\/code> both read 184 and the two clocks graded the same way on all four lines. That is the ordinary case, and it is what makes the bug quiet. The clocks only separate when a game goes past 48 minutes, and a resolver that has never met one of those games looks correct for a whole season of backtests.<\/p>\n<p>The detector is one comparison. If <code>fulltime<\/code> and <code>result<\/code> differ, the game went to overtime and every <code>p3+p4<\/code> grade parts company with its <code>p3+p4+overtime<\/code> twin. Add it to your settlement loop and the exceptions surface on their own.<\/p>\n<h2>The Rule<\/h2>\n<p>Key every basketball market on the pair <code>(period, handicap)<\/code>, never on the name and never on the line number. That one change fixes four separate comparisons:<\/p>\n<ul>\n<li>Second-half totals, where 90 line numbers sit on two clocks.<\/li>\n<li>Fourth-quarter totals, where 50 do.<\/li>\n<li>The full-game winner, where market <code>111<\/code> settles after overtime and market <code>113<\/code> settles at 48 minutes with a draw leg.<\/li>\n<li>Any consensus or best-price scan that pools books, because Pinnacle and Caesars sit on opposite clocks for the same headline bet.<\/li>\n<\/ul>\n<p>The same field carries the same weight in <a href=\"https:\/\/oddspapi.io\/blog\/nhl-regulation-overtime-markets\/\">ice hockey, where 118 markets ship in both flavours<\/a>, and in <a href=\"https:\/\/oddspapi.io\/blog\/mlb-first-five-innings-odds-api\/\">baseball, where the result settles under four IDs across three clocks<\/a>. Basketball is the version where the two ladders overlap on every rung.<\/p>\n<h2>Get the Board<\/h2>\n<p>One <code>\/v4\/odds<\/code> call returns every market a fixture carries, both clocks included, from a catalogue of 350+ bookmakers. Historical snapshots come on the same key at no extra cost, which is what makes a played-fixture test cheap enough to run before you trust a resolver. WebSocket delivery and the native market structures, Asian handicaps and player props among them, sit behind the same API.<\/p>\n<p><a href=\"https:\/\/oddspapi.io\/en\/sign-up\">Start on the free tier<\/a>: 250 requests a month, every sport, every bookmaker, no card. Then read <a href=\"https:\/\/oddspapi.io\/blog\/nba-alternate-lines-api\/\">how the full-game ladders sort by the handicap field<\/a>, <a href=\"https:\/\/oddspapi.io\/blog\/nba-opening-night-odds-api\/\">how to rank the books on an NBA board<\/a>, and <a href=\"https:\/\/oddspapi.io\/blog\/nba-odds-api-player-props-spreads\/\">what the NBA player-prop menu holds<\/a>. If you want the wide view first, <a href=\"https:\/\/oddspapi.io\/blog\/free-odds-api-350-bookmakers\/\">the free-tier walkthrough<\/a> covers auth, discovery and pagination in one pass.<\/p>\n<h2>FAQ<\/h2>\n<h3>What does the period field return for basketball?<\/h3>\n<p>Ten values plus a null. <code>result<\/code> is the final score including overtime, <code>fulltime<\/code> is the 48-minute score, <code>p1<\/code> to <code>p4<\/code> are single quarters, <code>p1+p2<\/code> is the first half, <code>p3+p4<\/code> is the regulation second half and <code>p3+p4+overtime<\/code> is the second half with overtime. <code>p4+overtime<\/code> covers the fourth quarter with overtime. Six definitions, including Second Half Result, ship <code>period: null<\/code>.<\/p>\n<h3>How do I tell a regulation second-half total from an overtime one?<\/h3>\n<p>Read <code>period<\/code> on <code>\/v4\/markets<\/code>. <code>p3+p4<\/code> settles on the third and fourth quarters alone; <code>p3+p4+overtime<\/code> adds anything scored after 48 minutes. The market name carries the same information in the suffix <code>(incl. overtime)<\/code>, but a name normaliser that strips parentheses will merge the two ladders, so branch on the enum.<\/p>\n<h3>Do the two second-half ladders use the same line numbers?<\/h3>\n<p>Yes. Over Under Second Half holds 90 rungs from 40.5 to 129.5 in steps of a full point. Over Under Second Half (incl. overtime) holds 180 rungs from 40.5 to 130.0 in steps of half a point, and all 90 regulation rungs appear in it. Fourth-quarter totals behave the same way at 50 and 100 rungs.<\/p>\n<h3>Which bookmakers quote which clock?<\/h3>\n<p>It varies by book and by market. On San Antonio v New York on 14 June 2026, DraftKings priced the second half on both clocks, 25 market IDs on <code>p3+p4<\/code> and 24 on <code>p3+p4+overtime<\/code>. Pinnacle quoted 17 second-half and 27 fourth-quarter IDs and used the overtime clock for all of them. Measure it per fixture rather than caching a map.<\/p>\n<h3>Can I get a regulation second-half spread?<\/h3>\n<p>The catalogue holds 90 second-half totals on the regulation clock and no spread or team total there. Handicap Second Half and the team totals exist on <code>p3+p4+overtime<\/code> with 201 and 400 definitions. The fourth quarter follows the same pattern, with a three-way result and a two-way winner added on <code>p4<\/code>.<\/p>\n<h3>How do I check a settled fixture for free?<\/h3>\n<p><code>\/historical-odds<\/code> returns the snapshot history for a played fixture on the free tier, capped at three bookmaker slugs a call, and <code>\/v4\/scores<\/code> returns each quarter as its own key. Together they let you replay a closing board and grade it on both clocks before you trust the resolver on a live game.<\/p>\n<p><script type=\"application\/ld+json\">\n{\n  \"@context\": \"https:\/\/schema.org\",\n  \"@type\": \"FAQPage\",\n  \"mainEntity\": [\n    {\"@type\":\"Question\",\"name\":\"What does the period field return for basketball?\",\"acceptedAnswer\":{\"@type\":\"Answer\",\"text\":\"Ten values plus a null. result is the final score including overtime, fulltime is the 48-minute score, p1 to p4 are single quarters, p1+p2 is the first half, p3+p4 is the regulation second half and p3+p4+overtime is the second half with overtime. p4+overtime covers the fourth quarter with overtime. Six definitions, including Second Half Result, ship period: null.\"}},\n    {\"@type\":\"Question\",\"name\":\"How do I tell a regulation second-half total from an overtime one?\",\"acceptedAnswer\":{\"@type\":\"Answer\",\"text\":\"Read period on \/v4\/markets. p3+p4 settles on the third and fourth quarters alone; p3+p4+overtime adds anything scored after 48 minutes. The market name carries the same information in the suffix (incl. overtime), but a name normaliser that strips parentheses will merge the two ladders, so branch on the enum.\"}},\n    {\"@type\":\"Question\",\"name\":\"Do the two second-half ladders use the same line numbers?\",\"acceptedAnswer\":{\"@type\":\"Answer\",\"text\":\"Yes. Over Under Second Half holds 90 rungs from 40.5 to 129.5 in steps of a full point. Over Under Second Half (incl. overtime) holds 180 rungs from 40.5 to 130.0 in steps of half a point, and all 90 regulation rungs appear in it. Fourth-quarter totals behave the same way at 50 and 100 rungs.\"}},\n    {\"@type\":\"Question\",\"name\":\"Which bookmakers quote which clock?\",\"acceptedAnswer\":{\"@type\":\"Answer\",\"text\":\"It varies by book and by market. On San Antonio v New York on 14 June 2026, DraftKings priced the second half on both clocks, 25 market IDs on p3+p4 and 24 on p3+p4+overtime. Pinnacle quoted 17 second-half and 27 fourth-quarter IDs and used the overtime clock for all of them. Measure it per fixture rather than caching a map.\"}},\n    {\"@type\":\"Question\",\"name\":\"Can I get a regulation second-half spread?\",\"acceptedAnswer\":{\"@type\":\"Answer\",\"text\":\"The catalogue holds 90 second-half totals on the regulation clock and no spread or team total there. Handicap Second Half and the team totals exist on p3+p4+overtime with 201 and 400 definitions. The fourth quarter follows the same pattern, with a three-way result and a two-way winner added on p4.\"}},\n    {\"@type\":\"Question\",\"name\":\"How do I check a settled fixture for free?\",\"acceptedAnswer\":{\"@type\":\"Answer\",\"text\":\"\/historical-odds returns the snapshot history for a played fixture on the free tier, capped at three bookmaker slugs a call, and \/v4\/scores returns each quarter as its own key. Together they let you replay a closing board and grade it on both clocks before you trust the resolver on a live game.\"}}\n  ]\n}\n<\/script><\/p>\n<p><!--\nSEO\nFocus keyphrase: nba second half odds api\nTitle: NBA Second Half Odds API: 90 Lines Carry Two Settlement Rules\nMeta description: Caesars closed the 104.5 second-half total on the regulation clock and BetRivers closed the same number with overtime. Branch on the period field.\nSlug: nba-second-half-odds-api\n--><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Caesars closed the 104.5 second-half total on the regulation clock and BetRivers closed the same number with overtime. Branch on the period field.<\/p>\n","protected":false},"author":2,"featured_media":4353,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7],"tags":[75,16,9,11,10],"class_list":["post-4352","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-how-to-guides","tag-basketball","tag-nba","tag-odds-api","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 Second Half Odds API: 90 Lines Carry Two Settlement Rules | 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-second-half-odds-api\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"NBA Second Half Odds API: 90 Lines Carry Two Settlement Rules | OddsPapi Blog\" \/>\n<meta property=\"og:description\" content=\"Caesars closed the 104.5 second-half total on the regulation clock and BetRivers closed the same number with overtime. Branch on the period field.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/oddspapi.io\/blog\/nba-second-half-odds-api\/\" \/>\n<meta property=\"og:site_name\" content=\"OddsPapi Blog\" \/>\n<meta property=\"article:published_time\" content=\"2026-09-30T10:00:00+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/09\/nba-second-half-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=\"13 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/oddspapi.io\/blog\/nba-second-half-odds-api\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/oddspapi.io\/blog\/nba-second-half-odds-api\/\"},\"author\":{\"name\":\"Odds API Writer\",\"@id\":\"https:\/\/oddspapi.io\/blog\/#\/schema\/person\/b6f21e649c4f556f0a95c23a0f1efa13\"},\"headline\":\"NBA Second Half Odds API: 90 Lines Carry Two Settlement Rules\",\"datePublished\":\"2026-09-30T10:00:00+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/oddspapi.io\/blog\/nba-second-half-odds-api\/\"},\"wordCount\":1732,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/oddspapi.io\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/oddspapi.io\/blog\/nba-second-half-odds-api\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/09\/nba-second-half-odds-api.webp\",\"keywords\":[\"Basketball\",\"NBA\",\"Odds API\",\"Python\",\"Sports Betting API\"],\"articleSection\":[\"How To Guides\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/oddspapi.io\/blog\/nba-second-half-odds-api\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/oddspapi.io\/blog\/nba-second-half-odds-api\/\",\"url\":\"https:\/\/oddspapi.io\/blog\/nba-second-half-odds-api\/\",\"name\":\"NBA Second Half Odds API: 90 Lines Carry Two Settlement Rules | OddsPapi Blog\",\"isPartOf\":{\"@id\":\"https:\/\/oddspapi.io\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/oddspapi.io\/blog\/nba-second-half-odds-api\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/oddspapi.io\/blog\/nba-second-half-odds-api\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/09\/nba-second-half-odds-api.webp\",\"datePublished\":\"2026-09-30T10:00:00+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/oddspapi.io\/blog\/nba-second-half-odds-api\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/oddspapi.io\/blog\/nba-second-half-odds-api\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/oddspapi.io\/blog\/nba-second-half-odds-api\/#primaryimage\",\"url\":\"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/09\/nba-second-half-odds-api.webp\",\"contentUrl\":\"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/09\/nba-second-half-odds-api.webp\",\"width\":1200,\"height\":675,\"caption\":\"NBA Second Half Odds API featured image\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/oddspapi.io\/blog\/nba-second-half-odds-api\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/oddspapi.io\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"NBA Second Half Odds API: 90 Lines Carry Two Settlement Rules\"}]},{\"@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 Second Half Odds API: 90 Lines Carry Two Settlement Rules | 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-second-half-odds-api\/","og_locale":"en_US","og_type":"article","og_title":"NBA Second Half Odds API: 90 Lines Carry Two Settlement Rules | OddsPapi Blog","og_description":"Caesars closed the 104.5 second-half total on the regulation clock and BetRivers closed the same number with overtime. Branch on the period field.","og_url":"https:\/\/oddspapi.io\/blog\/nba-second-half-odds-api\/","og_site_name":"OddsPapi Blog","article_published_time":"2026-09-30T10:00:00+00:00","og_image":[{"width":1200,"height":675,"url":"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/09\/nba-second-half-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":"13 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/oddspapi.io\/blog\/nba-second-half-odds-api\/#article","isPartOf":{"@id":"https:\/\/oddspapi.io\/blog\/nba-second-half-odds-api\/"},"author":{"name":"Odds API Writer","@id":"https:\/\/oddspapi.io\/blog\/#\/schema\/person\/b6f21e649c4f556f0a95c23a0f1efa13"},"headline":"NBA Second Half Odds API: 90 Lines Carry Two Settlement Rules","datePublished":"2026-09-30T10:00:00+00:00","mainEntityOfPage":{"@id":"https:\/\/oddspapi.io\/blog\/nba-second-half-odds-api\/"},"wordCount":1732,"commentCount":0,"publisher":{"@id":"https:\/\/oddspapi.io\/blog\/#organization"},"image":{"@id":"https:\/\/oddspapi.io\/blog\/nba-second-half-odds-api\/#primaryimage"},"thumbnailUrl":"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/09\/nba-second-half-odds-api.webp","keywords":["Basketball","NBA","Odds API","Python","Sports Betting API"],"articleSection":["How To Guides"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/oddspapi.io\/blog\/nba-second-half-odds-api\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/oddspapi.io\/blog\/nba-second-half-odds-api\/","url":"https:\/\/oddspapi.io\/blog\/nba-second-half-odds-api\/","name":"NBA Second Half Odds API: 90 Lines Carry Two Settlement Rules | OddsPapi Blog","isPartOf":{"@id":"https:\/\/oddspapi.io\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/oddspapi.io\/blog\/nba-second-half-odds-api\/#primaryimage"},"image":{"@id":"https:\/\/oddspapi.io\/blog\/nba-second-half-odds-api\/#primaryimage"},"thumbnailUrl":"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/09\/nba-second-half-odds-api.webp","datePublished":"2026-09-30T10:00:00+00:00","breadcrumb":{"@id":"https:\/\/oddspapi.io\/blog\/nba-second-half-odds-api\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/oddspapi.io\/blog\/nba-second-half-odds-api\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/oddspapi.io\/blog\/nba-second-half-odds-api\/#primaryimage","url":"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/09\/nba-second-half-odds-api.webp","contentUrl":"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/09\/nba-second-half-odds-api.webp","width":1200,"height":675,"caption":"NBA Second Half Odds API featured image"},{"@type":"BreadcrumbList","@id":"https:\/\/oddspapi.io\/blog\/nba-second-half-odds-api\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/oddspapi.io\/blog\/"},{"@type":"ListItem","position":2,"name":"NBA Second Half Odds API: 90 Lines Carry Two Settlement Rules"}]},{"@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\/4352","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=4352"}],"version-history":[{"count":1,"href":"https:\/\/oddspapi.io\/blog\/wp-json\/wp\/v2\/posts\/4352\/revisions"}],"predecessor-version":[{"id":4354,"href":"https:\/\/oddspapi.io\/blog\/wp-json\/wp\/v2\/posts\/4352\/revisions\/4354"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/oddspapi.io\/blog\/wp-json\/wp\/v2\/media\/4353"}],"wp:attachment":[{"href":"https:\/\/oddspapi.io\/blog\/wp-json\/wp\/v2\/media?parent=4352"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/oddspapi.io\/blog\/wp-json\/wp\/v2\/categories?post=4352"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/oddspapi.io\/blog\/wp-json\/wp\/v2\/tags?post=4352"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}