{"id":4902,"date":"2026-10-19T10:00:00","date_gmt":"2026-10-19T10:00:00","guid":{"rendered":"https:\/\/oddspapi.io\/blog\/?p=4902"},"modified":"2026-10-09T14:59:36","modified_gmt":"2026-10-09T14:59:36","slug":"college-basketball-odds-api","status":"publish","type":"post","link":"https:\/\/oddspapi.io\/blog\/college-basketball-odds-api\/","title":{"rendered":"College Basketball Odds API: Mid-Majors Draw 157 Books"},"content":{"rendered":"<p>Men&#8217;s college basketball tips off in the first week of November 2026, and the OddsPapi fixture list already holds 466 men&#8217;s fixtures for 2 to 8 November. Sportsbooks have not posted lines that far out. If you want a college basketball model ready for opening night, you build it now on last season&#8217;s boards.<\/p>\n<p>We replayed one Saturday, 7 February 2026, through <code>\/historical-odds<\/code>. A Missouri Valley fixture, Northern Iowa v Bradley, drew 157 bookmakers. Auburn v Alabama, the biggest fixture of that afternoon, drew 156. Every number below comes from calls made on 9 October 2026.<\/p>\n<h2>Why College Basketball Is Hard to Collect<\/h2>\n<p>The regular season runs four months. One Saturday in February, 7 February 2026, put 256 fixtures on the men&#8217;s tournament feed. Scrape one sportsbook and you get one price per fixture, no history, and no way to tell whether that price was sharp.<\/p>\n<p>A model that needs closing lines from last season needs an archive, or a full season of its own collection. OddsPapi keeps the history on the free tier, so you can pull last February&#8217;s closing board today with the same key you use in November.<\/p>\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>List the season&#8217;s fixtures<\/td>\n<td>Crawl a schedule site per conference<\/td>\n<td>One <code>\/fixtures<\/code> call on <code>tournamentId<\/code> 648<\/td>\n<\/tr>\n<tr>\n<td>Prices per fixture<\/td>\n<td>One book<\/td>\n<td>124 to 157 books on the four fixtures we walked<\/td>\n<\/tr>\n<tr>\n<td>Last season&#8217;s closing line<\/td>\n<td>Gone once the fixture tips<\/td>\n<td><code>\/historical-odds<\/code> on the free tier<\/td>\n<\/tr>\n<tr>\n<td>A sharp reference price<\/td>\n<td>Pinnacle&#8217;s own API needs a commercial account<\/td>\n<td><code>pinnacle<\/code> slug, with the stake limit attached<\/td>\n<\/tr>\n<tr>\n<td>Grade a first-half total<\/td>\n<td>Scrape a box score<\/td>\n<td><code>\/v4\/scores<\/code> returns each half as its own key<\/td>\n<\/tr>\n<tr>\n<td>Live prices in November<\/td>\n<td>Poll and get blocked<\/td>\n<td>REST polling or the WebSocket feed<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/figure>\n<h2>How Deep the Board Runs, Conference by Conference<\/h2>\n<p>We picked four fixtures from the 7 February slate, one per tier: an SEC rivalry, a Missouri Valley fixture, a CAA fixture and a MEAC fixture. For each one we walked the full bookmaker catalogue through <code>\/historical-odds<\/code>, three slugs per call. A book counts when it held at least one active price before tip-off. The closing price is the last active snapshot before the tip.<\/p>\n<figure class=\"wp-block-table\">\n<table>\n<thead>\n<tr>\n<th>Fixture<\/th>\n<th>Conference<\/th>\n<th>Books priced<\/th>\n<th>Books on the moneyline<\/th>\n<th>Distinct moneyline prices<\/th>\n<th>Median margin<\/th>\n<th>Books on the first half<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Auburn v Alabama<\/td>\n<td>SEC<\/td>\n<td>156<\/td>\n<td>146<\/td>\n<td>44<\/td>\n<td>5.65%<\/td>\n<td>117<\/td>\n<\/tr>\n<tr>\n<td>Northern Iowa v Bradley<\/td>\n<td>Missouri Valley<\/td>\n<td>157<\/td>\n<td>146<\/td>\n<td>46<\/td>\n<td>5.49%<\/td>\n<td>119<\/td>\n<\/tr>\n<tr>\n<td>NC A&amp;T v Campbell<\/td>\n<td>CAA<\/td>\n<td>142<\/td>\n<td>140<\/td>\n<td>40<\/td>\n<td>5.21%<\/td>\n<td>86<\/td>\n<\/tr>\n<tr>\n<td>Morgan State v Maryland Eastern Shore<\/td>\n<td>MEAC<\/td>\n<td>124<\/td>\n<td>122<\/td>\n<td>41<\/td>\n<td>5.26%<\/td>\n<td>86<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/figure>\n<p>The mid-major board matched the SEC board book for book. The median moneyline margin stayed between 5.21% and 5.65% on all four. And the 146 moneyline quotes on Auburn v Alabama collapsed to 44 distinct price pairs, a 69.9% collapse, because many slugs resell the same feed. Dedupe on the price pair before you average, or one supplier gets a dozen votes in your consensus. The <a href=\"https:\/\/oddspapi.io\/blog\/consensus-odds-fair-odds-calculator-python\/\">consensus odds tutorial<\/a> covers the dedupe step.<\/p>\n<p>The tightest moneylines came from the exchanges and prediction markets. Prophet Exchange (<code>prophetx<\/code>) ran 1.21% to 2.00% across the four fixtures, and Kalshi (<code>kalshi<\/code>) ran 0.99% to 2.98%. Pinnacle ranked 14th to 17th on the three larger boards at 3.84% to 3.96%.<\/p>\n<h3>The board opens late on small fixtures<\/h3>\n<p>Take the first snapshot each book posted on the moneyline and measure it against the tip. The median book opened 44.2 hours before Auburn v Alabama, 24.2 hours before Northern Iowa v Bradley, 13.1 hours before NC A&amp;T v Campbell and 15.1 hours before Morgan State v Maryland Eastern Shore. Kalshi opened all four more than 52 hours out. If your model wants an opening line on a small-conference fixture, schedule the pull for the morning of the fixture, not two days ahead.<\/p>\n<h2>Pinnacle Posts the Slate in Two Waves<\/h2>\n<p>We then pulled Pinnacle alone on every third men&#8217;s fixture from the 7 February slate, 86 fixtures in all. Most of the fixtures without a Pinnacle price were Division II. Pinnacle held a moneyline on 37 fixtures, and two patterns split those 37 into two groups.<\/p>\n<figure class=\"wp-block-table\">\n<table>\n<thead>\n<tr>\n<th>Wave<\/th>\n<th>Fixtures<\/th>\n<th>First moneyline snapshot (UTC)<\/th>\n<th>Moneyline base limit<\/th>\n<th>Main spread base limit<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Full board<\/td>\n<td>28<\/td>\n<td>13:02 to 13:37<\/td>\n<td>1,500 to 3,211<\/td>\n<td>1,590 to 5,353<\/td>\n<\/tr>\n<tr>\n<td>Small-conference board<\/td>\n<td>9<\/td>\n<td>15:25 to 15:57<\/td>\n<td>250 to 272<\/td>\n<td>525 to 555<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/figure>\n<p>The second wave held fixtures from the MEAC, the SWAC, the Southland, the Big South, the ASUN and the NEC. Pinnacle posts those boards more than two hours after the rest. It accepts about a twelfth of the moneyline stake and about a sixth of the spread stake. The base limit is the limit on the shorter-limit leg. Pinnacle scales the other leg up as the price shortens, which is why Quinnipiac&#8217;s moneyline carried a 27,522 limit on the favourite and 3,000 on Niagara.<\/p>\n<p>Use the limit as a confidence weight. A model that treats Pinnacle&#8217;s close as the truth on every fixture gives the same weight to a 250-limit SWAC line as to a 3,000-limit Big East line. On the small-conference wave, de-vig the deduplicated consensus instead, as the <a href=\"https:\/\/oddspapi.io\/blog\/backtest-betting-model-free-historical-odds\/\">backtesting guide<\/a> does for thin markets.<\/p>\n<h2>Men&#8217;s College Basketball Plays Halves<\/h2>\n<p>The NBA plays four quarters. Men&#8217;s college basketball plays two 20-minute halves. The market catalogue serves both, so the first-half markets carry the NBA label <code>period: \"p1+p2\"<\/code>, meaning quarters one and two. Market <code>111020<\/code>, Over Under First Half 71.5, is one of them.<\/p>\n<p><code>\/v4\/scores<\/code> labels each segment by its own format. On a men&#8217;s college fixture it returns <code>p1<\/code> and <code>p2<\/code>, and each key is one half. We checked 30 men&#8217;s fixtures from that weekend: <code>p1<\/code> plus <code>p2<\/code> equals <code>fulltime<\/code> on all 30. A women&#8217;s college fixture plays quarters and returns <code>p1<\/code> to <code>p4<\/code>.<\/p>\n<p>So a grader that reads <code>\"p1+p2\"<\/code> off the market and sums those two score keys grades a men&#8217;s first-half total on the full regulation score. Mississippi State v Arkansas went 30-43 at the half and 68-88 at the end. The naive grader sees 156 first-half points against a 77.5 line and pays the Over. The correct grader sees 73 and pays the Under. Step 3 below detects the format before it maps a clock to a score key. The <a href=\"https:\/\/oddspapi.io\/blog\/nba-second-half-odds-api\/\">NBA second-half post<\/a> covers the other basketball clock trap, the regulation and overtime twins.<\/p>\n<h2>Step 1: List the Season&#8217;s Fixtures<\/h2>\n<p>Authentication is a query parameter. The key goes on <code>?apiKey=<\/code>, never in a header. Men&#8217;s Division I is <code>tournamentId<\/code> 648, NCAA Regular Season, and the women&#8217;s equivalent is 21384.<\/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\ntournaments = requests.get(f\"{BASE_URL}\/tournaments\",\n                           params={\"apiKey\": API_KEY, \"sportId\": 11}).json()\nfor t in tournaments:\n    if t[\"tournamentSlug\"] in (\"ncaa-regular-season\", \"ncaa-women-regular-season\"):\n        print(t[\"tournamentId\"], t[\"tournamentName\"], t[\"futureFixtures\"], \"future fixtures\")\n\nfixtures = requests.get(f\"{BASE_URL}\/fixtures\", params={\n    \"apiKey\": API_KEY, \"sportId\": 11, \"tournamentId\": 648,\n    \"from\": \"2026-11-02\", \"to\": \"2026-11-09\",\n}).json()\n\nby_day = collections.Counter(f[\"startTime\"][:10] for f in fixtures)\nfor day, n in sorted(by_day.items()):\n    print(day, n, \"fixtures\")\nprint(len(fixtures), \"men's fixtures in the opening week\")<\/code><\/pre>\n<pre class=\"wp-block-code\"><code>648 NCAA, Regular Season 2604 future fixtures\n21384 NCAA Women, Regular Season 2612 future fixtures\n2026-11-02 59 fixtures\n2026-11-03 129 fixtures\n2026-11-04 30 fixtures\n2026-11-05 41 fixtures\n2026-11-06 63 fixtures\n2026-11-07 95 fixtures\n2026-11-08 49 fixtures\n466 men's fixtures in the opening week<\/code><\/pre>\n<p>Dates are UTC, so a 9 pm Eastern tip on 3 November lands on the 4th. Set <code>to<\/code> to the day after the last day you want, because it is a midnight instant. Tournament 648 also carries Division II fixtures, and sportsbooks do not price most of them. Filter on <code>hasOdds<\/code> once the lines open, and on the HTTP status of <code>\/historical-odds<\/code> for played fixtures: a 404 there means the books you asked for hold no history on that fixture.<\/p>\n<h2>Step 2: Pull a Played Fixture&#8217;s Closing Board<\/h2>\n<p><code>\/historical-odds<\/code> returns every snapshot a book posted, capped at three slugs per call. Snapshots run past the tip, so keep only those stamped before <code>startTime<\/code>, and take the last active one as the close.<\/p>\n<pre class=\"wp-block-code\"><code>import os, time, requests\nfrom datetime import datetime\n\nAPI_KEY = os.environ[\"ODDSPAPI_API_KEY\"]\nBASE_URL = \"https:\/\/api.oddspapi.io\/v4\"\nFIXTURE = \"id1100064862675787\"   # Auburn v Alabama, tipped 7 Feb 2026 21:00 UTC\nTIP = \"2026-02-07T21:00:00.000Z\"\n\ndef ts(s):\n    return datetime.fromisoformat(s.replace(\"Z\", \"+00:00\"))\n\ndef get(path, **params):\n    while True:\n        r = requests.get(f\"{BASE_URL}\/{path}\", params={\"apiKey\": API_KEY, **params})\n        if r.status_code == 429:                      # honour retryMs, then try again\n            time.sleep(r.json()[\"error\"].get(\"retryMs\", 5000) \/ 1000 + 0.5)\n            continue\n        r.raise_for_status()\n        return r.json()\n\nhistory = get(\"historical-odds\", fixtureId=FIXTURE,\n              bookmakers=\"pinnacle,draftkings,fanduel\")   # three slugs is the cap\n\nfor slug, book in history[\"bookmakers\"].items():\n    winner = book[\"markets\"][\"111\"][\"outcomes\"]          # 111 = Winner (incl. overtime)\n    legs = {}\n    for outcome_id, outcome in winner.items():\n        snaps = [s for s in outcome[\"players\"][\"0\"] if s[\"createdAt\"] &lt; TIP]\n        live = [s for s in snaps if s[\"active\"]]\n        legs[outcome_id] = (snaps[0][\"createdAt\"], live[-1][\"price\"], live[-1][\"limit\"])\n    first = min(v[0] for v in legs.values())\n    hours = (ts(TIP) - ts(first)).total_seconds() \/ 3600\n    home, away = legs[\"111\"][1], legs[\"112\"][1]\n    margin = (1 \/ home + 1 \/ away - 1) * 100\n    limit = legs[\"111\"][2]\n    print(f\"{slug:11} opened {hours:5.1f} h before tip   close {home} \/ {away}\"\n          f\"   margin {margin:.2f}%   limit {limit}\")<\/code><\/pre>\n<pre class=\"wp-block-code\"><code>draftkings  opened  44.3 h before tip   close 1.7 \/ 2.2   margin 4.28%   limit None\nfanduel     opened  44.2 h before tip   close 1.649 \/ 2.28   margin 4.50%   limit None\npinnacle    opened   7.7 h before tip   close 1.689 \/ 2.24   margin 3.85%   limit 4354.0<\/code><\/pre>\n<p>DraftKings and FanDuel posted the moneyline 44 hours out. Pinnacle posted it at 13:15 UTC on the day. Only Pinnacle and the exchanges fill <code>limit<\/code>; sportsbooks return <code>None<\/code>, so null-check before you do arithmetic on it. To read the rest of the board, loop the call over the catalogue three slugs at a time. The <a href=\"https:\/\/oddspapi.io\/blog\/college-football-odds-api\/\">college football odds API post<\/a> covers the NCAAF side of the same season.<\/p>\n<h2>Step 3: Grade the First Half on the Right Score Key<\/h2>\n<p>This grader reads the format off <code>\/scores<\/code>, maps each market clock to the score keys it settles on, finds Pinnacle&#8217;s main first-half and full-game totals, and grades both.<\/p>\n<pre class=\"wp-block-code\"><code>import os, time, requests\n\nAPI_KEY = os.environ[\"ODDSPAPI_API_KEY\"]\nBASE_URL = \"https:\/\/api.oddspapi.io\/v4\"\nFIXTURE = \"id1100064862675793\"   # Mississippi State v Arkansas, 7 Feb 2026\n\ndef get(path, **params):\n    while True:\n        r = requests.get(f\"{BASE_URL}\/{path}\", params={\"apiKey\": API_KEY, **params})\n        if r.status_code == 429:\n            time.sleep(r.json()[\"error\"].get(\"retryMs\", 5000) \/ 1000 + 0.5)\n            continue\n        r.raise_for_status()\n        return r.json()\n\n# 1. Which score keys make up each market clock? Read the format off \/scores.\nperiods = get(\"scores\", fixtureId=FIXTURE)[\"scores\"][\"periods\"]\nsegments = sorted(k for k in periods if k.startswith(\"p\"))\nhalves = segments == [\"p1\", \"p2\"]          # men's college: two 20-minute halves\nSCORE_KEYS = {\n    \"p1+p2\": [\"p1\"] if halves else [\"p1\", \"p2\"],   # the first half\n    \"result\": [\"result\"],                           # final score, overtime included\n}\nprint(\"score keys:\", segments, \"-&gt; halves\" if halves else \"-&gt; quarters\")\n\ndef points(clock):\n    return sum(periods[k][\"participant1Score\"] + periods[k][\"participant2Score\"]\n               for k in SCORE_KEYS[clock])\n\n# 2. Pull Pinnacle's closing first-half and full-game totals.\nmarkets = {str(m[\"marketId\"]): m for m in get(\"markets\")}\nfixture = get(\"historical-odds\", fixtureId=FIXTURE, bookmakers=\"pinnacle\")\ntip = get(\"fixtures\", sportId=11, tournamentId=648,\n          **{\"from\": \"2026-02-07\", \"to\": \"2026-02-08\"})\ntip = next(f[\"startTime\"] for f in tip if f[\"fixtureId\"] == FIXTURE)\n\ndef close(snaps):\n    live = [s for s in snaps if s[\"active\"] and s[\"createdAt\"] &lt; tip]\n    return live[-1][\"price\"] if live else None\n\nbest = {}\nfor mid, m in fixture[\"bookmakers\"][\"pinnacle\"][\"markets\"].items():\n    meta = markets[mid]\n    if not meta[\"marketName\"].startswith(\"Over Under\") or \"Team\" in meta[\"marketName\"]:\n        continue\n    if meta[\"period\"] not in SCORE_KEYS:\n        continue\n    prices = {}\n    for o in meta[\"outcomes\"]:\n        snaps = m[\"outcomes\"].get(str(o[\"outcomeId\"]), {}).get(\"players\", {}).get(\"0\", [])\n        prices[o[\"outcomeName\"]] = close(snaps)\n    if None in prices.values():\n        continue\n    gap = abs(prices[\"Over\"] - prices[\"Under\"])\n    if meta[\"period\"] not in best or gap &lt; best[meta[\"period\"]][0]:\n        best[meta[\"period\"]] = (gap, meta[\"handicap\"], prices)\n\n# 3. Grade each main line on the score keys its clock maps to.\nfor clock, (_, line, prices) in best.items():\n    total = points(clock)\n    side = \"Over\" if total &gt; line else \"Under\"\n    print(f\"{clock:7} line {line:6}  close O {prices['Over']} \/ U {prices['Under']}\"\n          f\"  scored {total:3}  -&gt; {side} wins\")\n\n# The trap: read \"p1+p2\" as two score keys on a halves fixture.\nnaive = sum(periods[k][\"participant1Score\"] + periods[k][\"participant2Score\"] for k in (\"p1\", \"p2\"))\nprint(f\"naive first half = {naive} points, which is the whole game\")<\/code><\/pre>\n<pre class=\"wp-block-code\"><code>score keys: ['p1', 'p2'] -&gt; halves\np1+p2   line   77.5  close O 1.961 \/ U 1.862  scored  73  -&gt; Under wins\nresult  line  163.0  close O 1.925 \/ U 1.892  scored 156  -&gt; Under wins\nnaive first half = 156 points, which is the whole game<\/code><\/pre>\n<p>The main line is the rung where Over and Under sit closest together, because <code>mainLine<\/code> is not reliable across books. Match outcomes on <code>outcomeName<\/code>, never on array position; the catalogue flips Over and Under from rung to rung. If a men&#8217;s fixture goes to overtime, <code>\/scores<\/code> adds an <code>overtime<\/code> key that holds the running total, so <code>result<\/code> stays the key for full-game totals.<\/p>\n<h2>Step 4: Tier the Slate by Pinnacle&#8217;s Limit<\/h2>\n<p>This loop takes a day&#8217;s fixtures, reads Pinnacle&#8217;s first moneyline snapshot and its closing limit, and labels each board. We ran it on six fixtures from the 7 February slate, three from each wave.<\/p>\n<pre class=\"wp-block-code\"><code>import os, time, requests\n\nAPI_KEY = os.environ[\"ODDSPAPI_API_KEY\"]\nBASE_URL = \"https:\/\/api.oddspapi.io\/v4\"\n\ndef get(path, **params):\n    while True:\n        r = requests.get(f\"{BASE_URL}\/{path}\", params={\"apiKey\": API_KEY, **params})\n        if r.status_code == 429:\n            time.sleep(r.json()[\"error\"].get(\"retryMs\", 5000) \/ 1000 + 0.5)\n            continue\n        return r\n\n# Saturday 7 Feb 2026: the men's slate, tip-off times from \/fixtures\nslate = get(\"fixtures\", sportId=11, tournamentId=648,\n            **{\"from\": \"2026-02-07\", \"to\": \"2026-02-08\"}).json()\ntips = {f[\"fixtureId\"]: f for f in slate}\n\nSAMPLE = [\"id1100064863666695\",   # Wake Forest v Louisville\n          \"id1100064863690411\",   # Marquette v Butler\n          \"id1100064863151769\",   # Quinnipiac v Niagara\n          \"id1100064864185633\",   # Morgan State v Maryland Eastern Shore\n          \"id1100064864187413\",   # Grambling State v Alabama State\n          \"id1100064863063783\"]   # Southeastern Louisiana v Houston Christian\n\nfor fid in SAMPLE:\n    f = tips[fid]\n    r = get(\"historical-odds\", fixtureId=fid, bookmakers=\"pinnacle\")\n    time.sleep(4.6)\n    if r.status_code != 200:\n        print(f\"{fid}  HTTP {r.status_code}, Pinnacle history absent\")\n        continue\n    legs = r.json()[\"bookmakers\"][\"pinnacle\"][\"markets\"][\"111\"][\"outcomes\"].values()\n    posted, limits = [], []\n    for leg in legs:\n        snaps = [s for s in leg[\"players\"][\"0\"] if s[\"createdAt\"] &lt; f[\"startTime\"]]\n        posted.append(snaps[0][\"createdAt\"][11:16])\n        limits.append([s for s in snaps if s[\"active\"]][-1][\"limit\"])\n    base = min(limits)                       # Pinnacle's base sits on the shorter-limit leg\n    tier = \"full board\" if base &gt;= 1500 else \"small-conference board\"\n    name = f\"{f['participant1Name']} v {f['participant2Name']}\"\n    print(f\"{name:57} posted {min(posted)} UTC  base limit {base:6.0f}  {tier}\")<\/code><\/pre>\n<pre class=\"wp-block-code\"><code>Wake Forest Demon Deacons v Louisville Cardinals          posted 13:04 UTC  base limit   3000  full board\nMarquette Golden Eagles v Butler Bulldogs                 posted 13:10 UTC  base limit   3000  full board\nQuinnipiac Bobcats v Niagara Purple Eagles                posted 13:14 UTC  base limit   3000  full board\nMorgan State Bears v Maryland Eastern Shore Hawks         posted 15:25 UTC  base limit    272  small-conference board\nGrambling State Tigers v Alabama State Hornets            posted 15:56 UTC  base limit    250  small-conference board\nSoutheastern Louisiana Lions v Houston Christian Huskies  posted 15:51 UTC  base limit    250  small-conference board<\/code><\/pre>\n<p><code>\/historical-odds<\/code> needs a 4.6-second pause between successful calls on this payload size, so a Pinnacle pass over a full Saturday slate takes about 20 minutes. Run it overnight and cache the result per fixture.<\/p>\n<h2>What Changes When the Season Opens<\/h2>\n<p>Swap <code>\/historical-odds<\/code> for <code>\/v4\/odds<\/code> on the same fixture IDs once books post. The live endpoint returns every bookmaker the key can read in one call, under the top-level key <code>bookmakerOdds<\/code> rather than <code>bookmakers<\/code>. On the full board, filter on the price-level <code>active<\/code> flag before you rank margins; a wide board carries many posted but suspended prices. For in-play first-half totals, the <a href=\"https:\/\/oddspapi.io\/blog\/websocket-odds-api-real-time-betting-data\/\">WebSocket feed<\/a> pushes each price change instead of making you poll for it.<\/p>\n<p>The basketball market catalogue is the same one the NBA uses, so the full-game ladders and the regulation and overtime twins behave as the <a href=\"https:\/\/oddspapi.io\/blog\/nba-alternate-lines-api\/\">NBA alternate lines post<\/a> describes. The halves format is the one college-specific rule.<\/p>\n<h2>Get the Board Before Opening Night<\/h2>\n<p>OddsPapi carries 350+ bookmakers, Pinnacle and the US exchanges included, and the free tier includes the historical archive you need to replay last season. <a href=\"https:\/\/oddspapi.io\/en\/sign-up\">Get a free API key<\/a>, pull February&#8217;s closing lines this week, and have your college basketball model priced before the first tip in November.<\/p>\n<h2>FAQ<\/h2>\n<h3>What is the tournament ID for men&#8217;s college basketball?<\/h3>\n<p>Men&#8217;s Division I regular season is <code>tournamentId<\/code> 648, NCAA Regular Season, under <code>sportId<\/code> 11. The women&#8217;s regular season is 21384. Pass the ID to <code>\/v4\/fixtures<\/code> to pull a month of fixtures in one call; on 9 October 2026 it listed 466 men&#8217;s fixtures for 2 to 8 November.<\/p>\n<h3>How many bookmakers price a college basketball fixture?<\/h3>\n<p>On 7 February 2026, 156 books priced Auburn v Alabama, 157 priced Northern Iowa v Bradley, 142 priced NC A&amp;T v Campbell and 124 priced Morgan State v Maryland Eastern Shore. Dedupe on the price pair before you average: 146 moneyline quotes on Auburn v Alabama held 44 distinct pairs.<\/p>\n<h3>When does Pinnacle post college basketball lines?<\/h3>\n<p>On the day of the fixture. On the 7 February 2026 slate Pinnacle posted 28 boards between 13:02 and 13:37 UTC with a base moneyline limit of 1,500 to 3,211, and a second wave of 9 small-conference boards between 15:25 and 15:57 UTC with a base limit of 250 to 272.<\/p>\n<h3>Why does my first-half grader pay the wrong side?<\/h3>\n<p>Men&#8217;s college basketball plays two halves. The first-half markets carry period p1+p2, the NBA quarter label, while \/v4\/scores returns p1 and p2 as the two halves. Grade a men&#8217;s first-half market on scores p1 alone. Women&#8217;s college fixtures play quarters and return p1 to p4.<\/p>\n<h3>Can I get last season&#8217;s college basketball closing lines for free?<\/h3>\n<p>Yes. \/historical-odds returns every snapshot for a played fixture on the free tier, three bookmaker slugs per call. Take the last active snapshot before startTime as the close, and pause 4.6 seconds between successful calls.<\/p>\n<p><script type=\"application\/ld+json\">\n{\n  \"@context\": \"https:\/\/schema.org\",\n  \"@type\": \"FAQPage\",\n  \"mainEntity\": [\n    {\"@type\":\"Question\",\"name\":\"What is the tournament ID for men's college basketball?\",\"acceptedAnswer\":{\"@type\":\"Answer\",\"text\":\"Men's Division I regular season is tournamentId 648, NCAA Regular Season, under sportId 11. The women's regular season is 21384. Pass the ID to \/v4\/fixtures to pull a month of fixtures in one call; on 9 October 2026 it listed 466 men's fixtures for 2 to 8 November.\"}},\n    {\"@type\":\"Question\",\"name\":\"How many bookmakers price a college basketball fixture?\",\"acceptedAnswer\":{\"@type\":\"Answer\",\"text\":\"On 7 February 2026, 156 books priced Auburn v Alabama, 157 priced Northern Iowa v Bradley, 142 priced NC A&T v Campbell and 124 priced Morgan State v Maryland Eastern Shore. Dedupe on the price pair before you average: 146 moneyline quotes on Auburn v Alabama held 44 distinct pairs.\"}},\n    {\"@type\":\"Question\",\"name\":\"When does Pinnacle post college basketball lines?\",\"acceptedAnswer\":{\"@type\":\"Answer\",\"text\":\"On the day of the fixture. On the 7 February 2026 slate Pinnacle posted 28 boards between 13:02 and 13:37 UTC with a base moneyline limit of 1,500 to 3,211, and a second wave of 9 small-conference boards between 15:25 and 15:57 UTC with a base limit of 250 to 272.\"}},\n    {\"@type\":\"Question\",\"name\":\"Why does my first-half grader pay the wrong side?\",\"acceptedAnswer\":{\"@type\":\"Answer\",\"text\":\"Men's college basketball plays two halves. The first-half markets carry period p1+p2, the NBA quarter label, while \/v4\/scores returns p1 and p2 as the two halves. Grade a men's first-half market on scores p1 alone. Women's college fixtures play quarters and return p1 to p4.\"}},\n    {\"@type\":\"Question\",\"name\":\"Can I get last season's college basketball closing lines for free?\",\"acceptedAnswer\":{\"@type\":\"Answer\",\"text\":\"Yes. \/historical-odds returns every snapshot for a played fixture on the free tier, three bookmaker slugs per call. Take the last active snapshot before startTime as the close, and pause 4.6 seconds between successful calls.\"}}\n  ]\n}\n<\/script><\/p>\n<p><!--\nSEO\nFocus keyphrase: college basketball odds api\nTitle: College Basketball Odds API: Mid-Majors Draw 157 Books\nMeta description: College basketball odds API replay of 7 Feb 2026: Pinnacle posted small-conference boards after 15:25 UTC at a 250 limit, against 3,000 on the rest.\nSlug: college-basketball-odds-api\n--><\/p>\n","protected":false},"excerpt":{"rendered":"<p>College basketball odds API replay of 7 Feb 2026: Pinnacle posted small-conference boards after 15:25 UTC at a 250 limit, against 3,000 on the rest.<\/p>\n","protected":false},"author":2,"featured_media":4903,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7],"tags":[75,4,9,11,10],"class_list":["post-4902","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-how-to-guides","tag-basketball","tag-historical-odds","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>College Basketball Odds API: Mid-Majors Draw 157 Books | 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\/college-basketball-odds-api\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"College Basketball Odds API: Mid-Majors Draw 157 Books | OddsPapi Blog\" \/>\n<meta property=\"og:description\" content=\"College basketball odds API replay of 7 Feb 2026: Pinnacle posted small-conference boards after 15:25 UTC at a 250 limit, against 3,000 on the rest.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/oddspapi.io\/blog\/college-basketball-odds-api\/\" \/>\n<meta property=\"og:site_name\" content=\"OddsPapi Blog\" \/>\n<meta property=\"article:published_time\" content=\"2026-10-19T10:00:00+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/10\/college-basketball-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=\"14 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/oddspapi.io\/blog\/college-basketball-odds-api\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/oddspapi.io\/blog\/college-basketball-odds-api\/\"},\"author\":{\"name\":\"Odds API Writer\",\"@id\":\"https:\/\/oddspapi.io\/blog\/#\/schema\/person\/b6f21e649c4f556f0a95c23a0f1efa13\"},\"headline\":\"College Basketball Odds API: Mid-Majors Draw 157 Books\",\"datePublished\":\"2026-10-19T10:00:00+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/oddspapi.io\/blog\/college-basketball-odds-api\/\"},\"wordCount\":1776,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/oddspapi.io\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/oddspapi.io\/blog\/college-basketball-odds-api\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/10\/college-basketball-odds-api.webp\",\"keywords\":[\"Basketball\",\"historical odds\",\"Odds API\",\"Python\",\"Sports Betting API\"],\"articleSection\":[\"How To Guides\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/oddspapi.io\/blog\/college-basketball-odds-api\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/oddspapi.io\/blog\/college-basketball-odds-api\/\",\"url\":\"https:\/\/oddspapi.io\/blog\/college-basketball-odds-api\/\",\"name\":\"College Basketball Odds API: Mid-Majors Draw 157 Books | OddsPapi Blog\",\"isPartOf\":{\"@id\":\"https:\/\/oddspapi.io\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/oddspapi.io\/blog\/college-basketball-odds-api\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/oddspapi.io\/blog\/college-basketball-odds-api\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/10\/college-basketball-odds-api.webp\",\"datePublished\":\"2026-10-19T10:00:00+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/oddspapi.io\/blog\/college-basketball-odds-api\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/oddspapi.io\/blog\/college-basketball-odds-api\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/oddspapi.io\/blog\/college-basketball-odds-api\/#primaryimage\",\"url\":\"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/10\/college-basketball-odds-api.webp\",\"contentUrl\":\"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/10\/college-basketball-odds-api.webp\",\"width\":1200,\"height\":675,\"caption\":\"College Basketball Odds API\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/oddspapi.io\/blog\/college-basketball-odds-api\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/oddspapi.io\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"College Basketball Odds API: Mid-Majors Draw 157 Books\"}]},{\"@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":"College Basketball Odds API: Mid-Majors Draw 157 Books | 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\/college-basketball-odds-api\/","og_locale":"en_US","og_type":"article","og_title":"College Basketball Odds API: Mid-Majors Draw 157 Books | OddsPapi Blog","og_description":"College basketball odds API replay of 7 Feb 2026: Pinnacle posted small-conference boards after 15:25 UTC at a 250 limit, against 3,000 on the rest.","og_url":"https:\/\/oddspapi.io\/blog\/college-basketball-odds-api\/","og_site_name":"OddsPapi Blog","article_published_time":"2026-10-19T10:00:00+00:00","og_image":[{"width":1200,"height":675,"url":"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/10\/college-basketball-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":"14 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/oddspapi.io\/blog\/college-basketball-odds-api\/#article","isPartOf":{"@id":"https:\/\/oddspapi.io\/blog\/college-basketball-odds-api\/"},"author":{"name":"Odds API Writer","@id":"https:\/\/oddspapi.io\/blog\/#\/schema\/person\/b6f21e649c4f556f0a95c23a0f1efa13"},"headline":"College Basketball Odds API: Mid-Majors Draw 157 Books","datePublished":"2026-10-19T10:00:00+00:00","mainEntityOfPage":{"@id":"https:\/\/oddspapi.io\/blog\/college-basketball-odds-api\/"},"wordCount":1776,"commentCount":0,"publisher":{"@id":"https:\/\/oddspapi.io\/blog\/#organization"},"image":{"@id":"https:\/\/oddspapi.io\/blog\/college-basketball-odds-api\/#primaryimage"},"thumbnailUrl":"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/10\/college-basketball-odds-api.webp","keywords":["Basketball","historical odds","Odds API","Python","Sports Betting API"],"articleSection":["How To Guides"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/oddspapi.io\/blog\/college-basketball-odds-api\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/oddspapi.io\/blog\/college-basketball-odds-api\/","url":"https:\/\/oddspapi.io\/blog\/college-basketball-odds-api\/","name":"College Basketball Odds API: Mid-Majors Draw 157 Books | OddsPapi Blog","isPartOf":{"@id":"https:\/\/oddspapi.io\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/oddspapi.io\/blog\/college-basketball-odds-api\/#primaryimage"},"image":{"@id":"https:\/\/oddspapi.io\/blog\/college-basketball-odds-api\/#primaryimage"},"thumbnailUrl":"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/10\/college-basketball-odds-api.webp","datePublished":"2026-10-19T10:00:00+00:00","breadcrumb":{"@id":"https:\/\/oddspapi.io\/blog\/college-basketball-odds-api\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/oddspapi.io\/blog\/college-basketball-odds-api\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/oddspapi.io\/blog\/college-basketball-odds-api\/#primaryimage","url":"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/10\/college-basketball-odds-api.webp","contentUrl":"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/10\/college-basketball-odds-api.webp","width":1200,"height":675,"caption":"College Basketball Odds API"},{"@type":"BreadcrumbList","@id":"https:\/\/oddspapi.io\/blog\/college-basketball-odds-api\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/oddspapi.io\/blog\/"},{"@type":"ListItem","position":2,"name":"College Basketball Odds API: Mid-Majors Draw 157 Books"}]},{"@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\/4902","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=4902"}],"version-history":[{"count":2,"href":"https:\/\/oddspapi.io\/blog\/wp-json\/wp\/v2\/posts\/4902\/revisions"}],"predecessor-version":[{"id":4905,"href":"https:\/\/oddspapi.io\/blog\/wp-json\/wp\/v2\/posts\/4902\/revisions\/4905"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/oddspapi.io\/blog\/wp-json\/wp\/v2\/media\/4903"}],"wp:attachment":[{"href":"https:\/\/oddspapi.io\/blog\/wp-json\/wp\/v2\/media?parent=4902"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/oddspapi.io\/blog\/wp-json\/wp\/v2\/categories?post=4902"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/oddspapi.io\/blog\/wp-json\/wp\/v2\/tags?post=4902"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}