{"id":3675,"date":"2026-08-27T10:00:00","date_gmt":"2026-08-27T10:00:00","guid":{"rendered":"https:\/\/oddspapi.io\/blog\/?p=3675"},"modified":"2026-08-29T14:57:55","modified_gmt":"2026-08-29T14:57:55","slug":"corners-cards-odds-api","status":"publish","type":"post","link":"https:\/\/oddspapi.io\/blog\/corners-cards-odds-api\/","title":{"rendered":"Corners &#038; Cards Odds API: The Three-Day Clock on Side Markets"},"content":{"rendered":"<p>Query a football fixture a week before kickoff, look for corner totals, and you get nothing. Look for booking markets and you get nothing again. Most developers conclude the feed does not carry them and move on.<\/p>\n<p>It does carry them. On Valencia against Real Betis, Pinnacle opened the three-way on 6 July, 50 days before kickoff. It opened the corner market on 23 August at 06:01 UTC, two and a half days out. It opened bookings on 24 August at 16:16 UTC, just over a day out. Same fixture, same book, three different clocks.<\/p>\n<p>Side markets in this feed run on a schedule you can set a timer by. This guide measures that schedule, shows which books price corners and cards on which competitions, and gives you the two parsing guards that stop a corner ladder from reading as free money. Everything below comes from live calls made on 24 August 2026 against the <a href=\"https:\/\/oddspapi.io\/blog\/free-odds-api-350-bookmakers\/\">OddsPapi free tier<\/a> and its 350+ bookmakers, across 30 fixtures in ten competitions: the Premier League, LaLiga, Serie A, Ligue 1, the Bundesliga, the Champions League, the Europa League, the Championship, the Eredivisie and the Brasileiro Serie A, three fixtures each.<\/p>\n<h2>What the board actually looks like<\/h2>\n<p>One number frames everything else in this guide. On 24 August 2026 those 30 fixtures returned 1,762,429 prices between them.<\/p>\n<figure class=\"wp-block-table\">\n<table>\n<thead>\n<tr>\n<th>Measure<\/th>\n<th>30 fixtures, 24 August 2026<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Books on a fixture<\/td>\n<td>178 median, 161 min, 195 max<\/td>\n<\/tr>\n<tr>\n<td>Books quoting corners<\/td>\n<td>92 median, 50 min, 156 max<\/td>\n<\/tr>\n<tr>\n<td>Books quoting cards or bookings<\/td>\n<td>0 min, 138 max<\/td>\n<\/tr>\n<tr>\n<td>Distinct market IDs per fixture<\/td>\n<td>560 median, 859 max<\/td>\n<\/tr>\n<tr>\n<td>Corner markets per fixture<\/td>\n<td>3,044 median, 6,769 max<\/td>\n<\/tr>\n<tr>\n<td>Side-market families<\/td>\n<td>22 corners, 21 bookings, 2 player-card<\/td>\n<\/tr>\n<tr>\n<td>Prices active<\/td>\n<td>86.0% median<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/figure>\n<p>The spread on those minimums and maximums is not a league quality ranking. It is the clock. A fixture two days from kickoff carries corner and card markets; a fixture six days out does not, and it is the same competition either way.<\/p>\n<h2>The market-open clock<\/h2>\n<p><code>\/historical-odds<\/code> records the first time each market was seen, so the open time of every market family is recoverable at no cost. Across the 30 fixtures:<\/p>\n<figure class=\"wp-block-table\">\n<table>\n<thead>\n<tr>\n<th>Pinnacle market family<\/th>\n<th>Median open<\/th>\n<th>Range<\/th>\n<th>Fixtures with it<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Match markets (1X2, totals, handicap)<\/td>\n<td>T-6.07 days<\/td>\n<td>fixture-dependent, see below<\/td>\n<td>30 of 30<\/td>\n<\/tr>\n<tr>\n<td>Corners<\/td>\n<td><strong>T-2.77 days<\/strong><\/td>\n<td>1.00 to 4.00 days<\/td>\n<td>10 of 30<\/td>\n<\/tr>\n<tr>\n<td>Bookings<\/td>\n<td><strong>T-1.11 days<\/strong><\/td>\n<td>1.06 to 2.08 days<\/td>\n<td>3 of 30<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/figure>\n<p>Corners never opened earlier than 4.00 days out on any fixture in the sample, and the 20 fixtures with no corner market were all more than four days from kickoff. That is the whole story: the market was not missing, it had not opened yet.<\/p>\n<p><strong>The match-market number needs a label, because it is the one figure here that moves.<\/strong> The median match open on this regular round was 6.07 days, but the spread is enormous. Valencia against Real Betis opened 50.50 days out and Bayern against Stuttgart 53.45 days out, while Crystal Palace against Manchester City opened 5.98 days out and AC Milan against Venezia 5.16 days out. Match markets open anywhere from six days to eight weeks ahead depending on the fixture. Corners hold at about three days and bookings at about one day regardless. Never quote a single median for match markets without saying which kind of fixture it came from.<\/p>\n<p>The full wave structure on one fixture makes the pattern obvious. Malaga CF against Deportivo, kickoff 24 August 19:30 UTC, with the corner open landing on 3.00 days to the minute:<\/p>\n<figure class=\"wp-block-table\">\n<table>\n<thead>\n<tr>\n<th>Wave<\/th>\n<th>Opened<\/th>\n<th>Lead time<\/th>\n<th>What arrives<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>1<\/td>\n<td>14 Aug 04:42<\/td>\n<td>T-10.62 days<\/td>\n<td>Asian Handicap, Full Time Result, Over Under, first-half versions, team totals<\/td>\n<\/tr>\n<tr>\n<td>2<\/td>\n<td>17 Aug 14:28<\/td>\n<td>T-7.21 days<\/td>\n<td>Correct score, HT\/FT, double chance, BTTS, win to nil, draw no bet, odd\/even, exact score, winning margin<\/td>\n<\/tr>\n<tr>\n<td>3<\/td>\n<td>21 Aug 19:31<\/td>\n<td><strong>T-3.00 days<\/strong><\/td>\n<td>Corners, 6 families<\/td>\n<\/tr>\n<tr>\n<td>4<\/td>\n<td>23 Aug 18:01<\/td>\n<td><strong>T-1.06 days<\/strong><\/td>\n<td>Bookings, 5 families<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/figure>\n<p>Two practical consequences. Polling for corners more than five days out wastes calls on every football fixture you track. And a coverage audit run a week ahead will tell you corners do not exist, which is how the &#8220;the feed has no corner data&#8221; belief survives.<\/p>\n<h2>Old way vs OddsPapi<\/h2>\n<figure class=\"wp-block-table\">\n<table>\n<thead>\n<tr>\n<th>Job<\/th>\n<th>Scraping or a mainline-only API<\/th>\n<th>OddsPapi<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Corner totals<\/td>\n<td>Not exposed, or one book<\/td>\n<td>A median of 92 books, 22 corner market families<\/td>\n<\/tr>\n<tr>\n<td>Booking markets<\/td>\n<td>Almost never carried<\/td>\n<td>Bookings 1X2, handicap, totals and player-carded<\/td>\n<\/tr>\n<tr>\n<td>Sharp corner price<\/td>\n<td>Pinnacle has no public API<\/td>\n<td><code>pinnacle<\/code> slug with published limits<\/td>\n<\/tr>\n<tr>\n<td>When a market opened<\/td>\n<td>You would have to log it yourself<\/td>\n<td><code>\/historical-odds<\/code> on the free tier<\/td>\n<\/tr>\n<tr>\n<td>Line ladders<\/td>\n<td>Flattened to one number<\/td>\n<td>One market ID per rung, native<\/td>\n<\/tr>\n<tr>\n<td>Live updates<\/td>\n<td>Poll and hope<\/td>\n<td>WebSocket feed<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/figure>\n<h2>Step 1: Auth and the catalogue lookup<\/h2>\n<p>The key is a query parameter, never a header. Market IDs are integers and the names live in <code>\/v4\/markets<\/code>, so build a lookup once and keep it. Do not hardcode corner market IDs. There is one ID per line, and the lines move.<\/p>\n<pre class=\"wp-block-code\"><code>import requests, time\nfrom collections import Counter, defaultdict\nfrom datetime import datetime\n\nAPI_KEY = \"YOUR_API_KEY\"\nBASE_URL = \"https:\/\/api.oddspapi.io\/v4\"\nSESSION = requests.Session()\n\ndef api(path, **params):\n    \"\"\"GET a v4 endpoint. Honours 429 retryMs. Treats 404 as an empty result.\"\"\"\n    params[\"apiKey\"] = API_KEY\n    for _ in range(6):\n        r = SESSION.get(f\"{BASE_URL}{path}\", params=params, timeout=600)\n        if r.status_code == 429:\n            time.sleep(r.json().get(\"error\", {}).get(\"retryMs\", 1500) \/ 1000 + 0.3)\n            continue\n        if r.status_code == 404:\n            return None\n        r.raise_for_status()\n        return r.json()\n    raise RuntimeError(f\"gave up on {path}\")\n\ndef catalogue(sport_id=10):\n    return {str(m[\"marketId\"]): (m[\"marketName\"], m.get(\"handicap\"), m.get(\"period\"))\n            for m in api(\"\/markets\", sportId=sport_id)}\n\ndef family(name):\n    if \"Bookings\" in name or \"Card\" in name:\n        return \"bookings\"\n    if \"Corners\" in name:\n        return \"corners\"\n    return \"match\"\n<\/code><\/pre>\n<p>The soccer catalogue holds 32,815 rows. The <code>sportId<\/code> parameter is a no-op, so treat the response as a global name lookup rather than a way to discover which markets a sport supports.<\/p>\n<h2>Step 2: The two guards that stop a fake arbitrage<\/h2>\n<p>Corner ladders break naive de-vig code in two separate ways, and both produce a two-leg sum under 100% that reads as free money. Across the 24 August 2026 sample, 102 of 17,314 two-sided corner quotes summed to 100% or less. Of those, 74 were whole-number lines and 28 were <code>Corners - 1X2<\/code>. Two causes, two guards.<\/p>\n<p><strong>The first is a three-way market wearing a two-way name.<\/strong> <code>Corners - 1X2<\/code> has three outcomes: more home corners, level, more away corners. Its first-half and second-half variants ship only two of the three. Grab &#8220;the priced legs&#8221; and sum them and you get a 6% arbitrage that does not exist.<\/p>\n<p><strong>The second is a whole-number line.<\/strong> A corner total of exactly 10.0 pushes if the game ends on 10 corners, so the two prices legitimately sum below 100%. On Real Madrid against Real Sociedad, FanDuel quoted twelve whole-number corner totals and eight of them summed to 100% or less: 5.0 at +0.24%, 6.0 at -1.50%, 7.0 at -3.05%, 8.0 at -1.80%, 9.0 at -1.61% and 10.0 at -1.13%. Nothing is wrong with those prices. The push is missing from your arithmetic.<\/p>\n<pre class=\"wp-block-code\"><code>def two_sided(market):\n    legs = []\n    for outcome in (market.get(\"outcomes\") or {}).values():\n        price = (outcome.get(\"players\") or {}).get(\"0\")\n        if isinstance(price, dict) and price.get(\"price\") and price.get(\"active\") is not False:\n            legs.append(price[\"price\"])\n    return legs if len(legs) == 2 else None\n\ndef margin(legs):\n    return sum(1 \/ p for p in legs) - 1\n\ndef usable_total(market, handicap):\n    \"\"\"Reject three-way markets and whole-number push lines before de-vigging.\"\"\"\n    legs = two_sided(market)\n    if not legs:\n        return None       # Corners - 1X2 has three outcomes\n    if float(handicap) == int(float(handicap)):\n        return None       # a whole line can push, so it sums below 100%\n    if margin(legs) &lt;= 0:\n        return None       # one book never offers a free arb\n    return legs\n<\/code><\/pre>\n<p>Pinnacle handles whole lines differently again. Its 9.0, 10.0 and 11.0 corner totals on the same fixture came back at +6.49%, +4.34% and +6.35%, so it prices the push into its own margin. Comparing a Pinnacle whole line against a FanDuel whole line without accounting for that is comparing two different bets.<\/p>\n<h2>Step 3: Build the corner board<\/h2>\n<pre class=\"wp-block-code\"><code>def corner_totals(payload, cat, period=\"fulltime\"):\n    \"\"\"{bookmaker: {line: (margin, [over, under])}} for full-time corner totals.\"\"\"\n    out = defaultdict(dict)\n    for slug, book in (payload.get(\"bookmakerOdds\") or {}).items():\n        if book.get(\"suspended\"):\n            continue\n        for market_id, market in (book.get(\"markets\") or {}).items():\n            name, hcap, per = cat.get(market_id, (\"\", None, None))\n            if name != \"Corners - Over Under Full Time\" or per != period or hcap is None:\n                continue\n            legs = usable_total(market, hcap)\n            if legs:\n                out[slug][hcap] = (margin(legs), legs)\n    return out\n\ndef consensus_line(board):\n    votes = Counter()\n    for lines in board.values():\n        for line in lines:\n            votes[line] += 1\n    return votes.most_common(1)[0][0] if votes else None\n<\/code><\/pre>\n<p>The worked fixture for the rest of this guide is <strong>Real Madrid against Real Sociedad<\/strong>, <code>id1000000872478460<\/code>, LaLiga, kickoff 26 August 2026 19:00 UTC. Sampled on 24 August it returned a 30.9 MB payload from 187 books, carrying 18 distinct half-point full-time corner lines from 2.5 up to 19.5.<\/p>\n<p>The consensus is the line the most books quote, and here that is <strong>10.5, quoted by 121 of the 187 books<\/strong>. Next come 9.5 on 118 books, 11.5 on 112, 8.5 on 102, 12.5 on 96 and 7.5 on 73. Pinnacle quoted only 9.5 and 10.5 after the whole-line filter, which is normal: sharps quote two or three rungs near the true number while the alt-ladder books post fifteen. Its two rungs came in at 5.68% and 5.51%.<\/p>\n<h2>Step 4: Corners cost more than the match market<\/h2>\n<p>Compare each book&#8217;s margin on the consensus corner line against its own three-way on the same fixture. Across 2,276 book-and-fixture pairs in the 24 August 2026 sample, the median corner margin was <strong>1.27 times<\/strong> the same book&#8217;s three-way margin, and 80% of pairs charged more for corners. In absolute terms that is a median corner margin of 8.70% against a median three-way of 6.94%.<\/p>\n<pre class=\"wp-block-code\"><code>def match_margin(book):\n    market = (book.get(\"markets\") or {}).get(\"101\")\n    if not market:\n        return None\n    legs = []\n    for outcome_id in (\"101\", \"102\", \"103\"):\n        price = ((market[\"outcomes\"].get(outcome_id) or {}).get(\"players\") or {}).get(\"0\")\n        if not isinstance(price, dict) or not price.get(\"price\") or price.get(\"active\") is False:\n            return None\n        legs.append(price[\"price\"])\n    return sum(1 \/ p for p in legs) - 1\n<\/code><\/pre>\n<p>On Real Madrid against Real Sociedad, 119 books quoted both the consensus corner line and a complete three-way, which is the pair count for the ratio test on this fixture. The median ratio was 1.59 and 92% of pairs charged more for corners, on a median corner margin of 8.64% against a median three-way of 5.08%. Ranked out of those 119 books, at corner line 10.5:<\/p>\n<figure class=\"wp-block-table\">\n<table>\n<thead>\n<tr>\n<th>Rank<\/th>\n<th>Book<\/th>\n<th>Over \/ Under<\/th>\n<th>Corner margin<\/th>\n<th>Same book 1X2<\/th>\n<th>Ratio<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>1<\/td>\n<td>polymarket<\/td>\n<td>2.174 \/ 1.695<\/td>\n<td>5.00%<\/td>\n<td>2.02%<\/td>\n<td>2.47<\/td>\n<\/tr>\n<tr>\n<td>2<\/td>\n<td>duel<\/td>\n<td>2.100 \/ 1.740<\/td>\n<td>5.09%<\/td>\n<td>1.90%<\/td>\n<td>2.68<\/td>\n<\/tr>\n<tr>\n<td>3<\/td>\n<td><strong>pinnacle<\/strong><\/td>\n<td>2.120 \/ 1.714<\/td>\n<td><strong>5.51%<\/strong><\/td>\n<td>3.91%<\/td>\n<td>1.41<\/td>\n<\/tr>\n<tr>\n<td>8<\/td>\n<td>betfair-ex<\/td>\n<td>2.100 \/ 1.710<\/td>\n<td>6.10%<\/td>\n<td>0.53%<\/td>\n<td>11.53<\/td>\n<\/tr>\n<tr>\n<td>18<\/td>\n<td>fanduel<\/td>\n<td>1.600 \/ 2.240<\/td>\n<td>7.14%<\/td>\n<td>5.87%<\/td>\n<td>1.22<\/td>\n<\/tr>\n<tr>\n<td>28<\/td>\n<td>bet365<\/td>\n<td>2.000 \/ 1.727<\/td>\n<td>7.90%<\/td>\n<td>7.66%<\/td>\n<td>1.03<\/td>\n<\/tr>\n<tr>\n<td>40<\/td>\n<td>draftkings<\/td>\n<td>2.150 \/ 1.625<\/td>\n<td>8.05%<\/td>\n<td>5.21%<\/td>\n<td>1.55<\/td>\n<\/tr>\n<tr>\n<td>57<\/td>\n<td>betmgm<\/td>\n<td>1.980 \/ 1.720<\/td>\n<td>8.64%<\/td>\n<td>4.84%<\/td>\n<td>1.78<\/td>\n<\/tr>\n<tr>\n<td>64<\/td>\n<td>hardrockbet<\/td>\n<td>1.606 \/ 2.150<\/td>\n<td>8.78%<\/td>\n<td>4.86%<\/td>\n<td>1.81<\/td>\n<\/tr>\n<tr>\n<td>103<\/td>\n<td>codere.es<\/td>\n<td>1.700 \/ 1.950<\/td>\n<td>10.11%<\/td>\n<td>5.43%<\/td>\n<td>1.86<\/td>\n<\/tr>\n<tr>\n<td>117<\/td>\n<td>winamax.es<\/td>\n<td>1.920 \/ 1.660<\/td>\n<td>12.32%<\/td>\n<td>7.04%<\/td>\n<td>1.75<\/td>\n<\/tr>\n<tr>\n<td>119<\/td>\n<td><strong>kalshi<\/strong><\/td>\n<td>1.695 \/ 1.149<\/td>\n<td><strong>46.03%<\/strong><\/td>\n<td>3.02%<\/td>\n<td>15.24<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/figure>\n<p><strong>Look at the two prediction markets.<\/strong> Polymarket is the tightest corner quote on the whole board at 5.00%. Kalshi is the worst of all 119 books at 46.03%, while pricing the three-way on the same fixture at 3.02%. That 46% is a placeholder rather than a price, and nothing in the payload says so. A prediction market&#8217;s tight three-way tells you nothing about its side markets, so screen every market separately before you treat any exchange quote as consensus. If you want the fair number on a corner line, take the sharp quote and <a href=\"https:\/\/oddspapi.io\/blog\/no-vig-odds-api\/\">strip the margin<\/a> rather than trusting a mid-market average of the retail board.<\/p>\n<h2>Step 5: Read Pinnacle&#8217;s limits as a confidence ranking<\/h2>\n<p>Pinnacle publishes a capped maximum win, so dividing it back out recovers a per-market base. That base ranks how much the book wants to be on each market.<\/p>\n<pre class=\"wp-block-code\"><code>def limit_base(price_obj):\n    limit, price = price_obj.get(\"limit\"), price_obj.get(\"price\")\n    if not limit or not price:\n        return None            # sbobet and US retail ship limit: null\n    return round(limit if price >= 2 else limit * (price - 1))\n\ndef base_by_family(book, cat):\n    out = defaultdict(list)\n    for market_id, market in (book.get(\"markets\") or {}).items():\n        name = cat.get(market_id, (\"\",))[0]\n        for outcome in (market.get(\"outcomes\") or {}).values():\n            price = (outcome.get(\"players\") or {}).get(\"0\")\n            if isinstance(price, dict):\n                base = limit_base(price)\n                if base:\n                    out[family(name)].append(base)\n    # the headline market of a family carries the family's top base\n    return {fam: max(v) for fam, v in out.items()}\n<\/code><\/pre>\n<p>Match markets always take the most. On the three fixtures in the 24 August sample where all three families were open at once:<\/p>\n<figure class=\"wp-block-table\">\n<table>\n<thead>\n<tr>\n<th>Competition<\/th>\n<th>Fixture<\/th>\n<th>Match base<\/th>\n<th>Corner base<\/th>\n<th>Bookings base<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>LaLiga<\/td>\n<td>Malaga v Deportivo<\/td>\n<td>$15,000<\/td>\n<td>$2,500<\/td>\n<td>$750<\/td>\n<\/tr>\n<tr>\n<td>LaLiga<\/td>\n<td>Valencia v Real Betis<\/td>\n<td>$3,750<\/td>\n<td>$625<\/td>\n<td>$187<\/td>\n<\/tr>\n<tr>\n<td>Brasileiro Serie A<\/td>\n<td>Botafogo v Athletico PR<\/td>\n<td>$1,200<\/td>\n<td>$100<\/td>\n<td><strong>$250<\/strong><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/figure>\n<p>And on the fixtures where corners had opened but bookings had not:<\/p>\n<figure class=\"wp-block-table\">\n<table>\n<thead>\n<tr>\n<th>Competition<\/th>\n<th>Fixture<\/th>\n<th>Match base<\/th>\n<th>Corner base<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>LaLiga<\/td>\n<td>Real Madrid v Real Sociedad<\/td>\n<td>$2,250<\/td>\n<td>$250<\/td>\n<\/tr>\n<tr>\n<td>Premier League<\/td>\n<td>Crystal Palace v Man City<\/td>\n<td>$1,500<\/td>\n<td>$250<\/td>\n<\/tr>\n<tr>\n<td>Ligue 1<\/td>\n<td>Lille v PSG<\/td>\n<td>$1,000<\/td>\n<td>$100<\/td>\n<\/tr>\n<tr>\n<td>Bundesliga<\/td>\n<td>Bayern v Stuttgart<\/td>\n<td>$1,000<\/td>\n<td>$100<\/td>\n<\/tr>\n<tr>\n<td>Champions League<\/td>\n<td>Three playoff ties<\/td>\n<td>$300<\/td>\n<td>$50<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/figure>\n<p>The match-to-corner ratio ran from 6x to 12x, with a median of 6x. <strong>The corner-to-bookings ordering is not a rule.<\/strong> It held at 3.3x on both LaLiga fixtures, and it inverted on the Brasileirao fixture, where bookings carried a $250 base against corners at $100. Take match above corners as reliable and probe the rest per fixture. On fixtures where the side markets had not opened at all, the match-only bases were $1,500 on Serie A, $500 on the Championship, $300 on the Eredivisie and $150 on the Europa League.<\/p>\n<p>A book that takes $15,000 on the result, $2,500 on the corner count and $750 on the bookings count is telling you which of the three numbers it trusts. For more on reading limits as a signal, see the <a href=\"https:\/\/oddspapi.io\/blog\/betting-limits-api-stake-sizing\/\">betting limits guide<\/a>.<\/p>\n<h2>Step 6: Which competitions carry corners<\/h2>\n<p>Three priced fixtures in each of ten competitions, all sampled on 24 August 2026:<\/p>\n<figure class=\"wp-block-table\">\n<table>\n<thead>\n<tr>\n<th>Competition<\/th>\n<th>Books on fixture<\/th>\n<th>Books quoting corners<\/th>\n<th>Books quoting cards<\/th>\n<th>Distinct market IDs<\/th>\n<th>Corner markets<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>LaLiga<\/td>\n<td>187 to 195<\/td>\n<td><strong>132 to 156<\/strong><\/td>\n<td>55 to 138<\/td>\n<td>741 to 859<\/td>\n<td>6,007 to 6,769<\/td>\n<\/tr>\n<tr>\n<td>Brasileiro Serie A<\/td>\n<td>161 to 188<\/td>\n<td>83 to 131<\/td>\n<td>10 to 115<\/td>\n<td>494 to 833<\/td>\n<td>2,710 to 5,928<\/td>\n<\/tr>\n<tr>\n<td>Champions League<\/td>\n<td>176 to 188<\/td>\n<td>116 to 121<\/td>\n<td>67 to 99<\/td>\n<td>767 to 782<\/td>\n<td>4,574 to 5,143<\/td>\n<\/tr>\n<tr>\n<td>Ligue 1<\/td>\n<td>179 to 180<\/td>\n<td>97 to 115<\/td>\n<td>10<\/td>\n<td>516 to 653<\/td>\n<td>3,037 to 4,719<\/td>\n<\/tr>\n<tr>\n<td>Serie A<\/td>\n<td>172 to 174<\/td>\n<td>102 to 103<\/td>\n<td>10 to 11<\/td>\n<td>488 to 528<\/td>\n<td>2,969 to 3,052<\/td>\n<\/tr>\n<tr>\n<td>Bundesliga<\/td>\n<td>190 to 191<\/td>\n<td>50 to 102<\/td>\n<td>6 to 16<\/td>\n<td>615 to 697<\/td>\n<td>2,584 to 4,338<\/td>\n<\/tr>\n<tr>\n<td>Eredivisie<\/td>\n<td>165 to 168<\/td>\n<td>73 to 94<\/td>\n<td>0 to 3<\/td>\n<td>490 to 573<\/td>\n<td>2,560 to 3,723<\/td>\n<\/tr>\n<tr>\n<td>Europa League<\/td>\n<td>175 to 177<\/td>\n<td>78 to 90<\/td>\n<td>0 to 26<\/td>\n<td>534 to 637<\/td>\n<td>1,413 to 2,790<\/td>\n<\/tr>\n<tr>\n<td>Premier League<\/td>\n<td>181 to 183<\/td>\n<td>58 to 87<\/td>\n<td>11 to 16<\/td>\n<td>454 to 665<\/td>\n<td>1,562 to 3,771<\/td>\n<\/tr>\n<tr>\n<td>Championship<\/td>\n<td>172 to 173<\/td>\n<td>75<\/td>\n<td>10 to 14<\/td>\n<td>449 to 455<\/td>\n<td>1,650 to 1,801<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/figure>\n<p><strong>Do not read that as a league quality ranking.<\/strong> The LaLiga fixtures were the closest to kickoff in the sample, which is why they top the corner and card columns, and the Premier League fixtures were further out, which is why they sit near the bottom. Sort that table by days to kickoff and it stops looking like a ranking at all.<\/p>\n<h3>Test coverage on a played fixture, not an upcoming one<\/h3>\n<p>This is the single most useful trick in this guide, and it is the reason an earlier version of this post got the next section wrong.<\/p>\n<p>A live <code>\/odds<\/code> call on an upcoming fixture tells you what is open right now. It cannot tell you whether a book covers a market at all. <code>\/historical-odds<\/code> can, because the price history is retained after the fixture is played and the live prices are dropped. Run it on a fixture from last weekend and you see the book&#8217;s full menu instead of whatever the clock happens to have opened.<\/p>\n<p>Done that way, on played fixtures from 19 to 24 August 2026:<\/p>\n<figure class=\"wp-block-table\">\n<table>\n<thead>\n<tr>\n<th>Competition<\/th>\n<th>Fixture date<\/th>\n<th>Pinnacle corner families<\/th>\n<th>Pinnacle booking families<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Championship<\/td>\n<td>23 Aug<\/td>\n<td><strong>8<\/strong><\/td>\n<td>5<\/td>\n<\/tr>\n<tr>\n<td>Championship<\/td>\n<td>22 Aug<\/td>\n<td><strong>8<\/strong><\/td>\n<td>5<\/td>\n<\/tr>\n<tr>\n<td>Eredivisie<\/td>\n<td>23 Aug<\/td>\n<td><strong>8<\/strong><\/td>\n<td>0<\/td>\n<\/tr>\n<tr>\n<td>Eredivisie<\/td>\n<td>23 Aug<\/td>\n<td><strong>8<\/strong><\/td>\n<td>0<\/td>\n<\/tr>\n<tr>\n<td>Brasileiro Serie A<\/td>\n<td>23 Aug<\/td>\n<td><strong>8<\/strong><\/td>\n<td>5<\/td>\n<\/tr>\n<tr>\n<td>Brasileiro Serie A<\/td>\n<td>23 Aug<\/td>\n<td><strong>8<\/strong><\/td>\n<td>5<\/td>\n<\/tr>\n<tr>\n<td>LaLiga<\/td>\n<td>23 Aug<\/td>\n<td>8<\/td>\n<td>5<\/td>\n<\/tr>\n<tr>\n<td>Serie A<\/td>\n<td>24 Aug<\/td>\n<td>8<\/td>\n<td>5<\/td>\n<\/tr>\n<tr>\n<td>Premier League<\/td>\n<td>24 Aug<\/td>\n<td>8<\/td>\n<td>5<\/td>\n<\/tr>\n<tr>\n<td>Champions League<\/td>\n<td>19 Aug<\/td>\n<td>4<\/td>\n<td>0<\/td>\n<\/tr>\n<tr>\n<td>Europa League<\/td>\n<td>20 Aug<\/td>\n<td>4<\/td>\n<td>0<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/figure>\n<p><strong>Pinnacle prices corners on all ten competitions.<\/strong> The split is not by country and it is not by league tier. Domestic league fixtures get eight Pinnacle corner families; European club competition gets four. The Championship and the Eredivisie carry exactly the same eight families as LaLiga.<\/p>\n<p>Bookings are the narrower product. Pinnacle priced bookings on the Championship, the Brasileirao, LaLiga, Serie A and the Premier League, and did not price them on the Eredivisie, the Champions League or the Europa League.<\/p>\n<p>So the rule about losing the sharp benchmark is real, but it has nothing to do with which league you picked. <strong>You lose the sharp benchmark by querying too early.<\/strong> Audit a Championship fixture five days out and Pinnacle looks absent from the corner market; audit the same fixture after it is played and eight families are sitting there.<\/p>\n<p>Sixteen of the 22 corner families in the sample, ranked by how many books quote them:<\/p>\n<figure class=\"wp-block-table\">\n<table>\n<thead>\n<tr>\n<th>Market family<\/th>\n<th>Books<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Corners &#8211; Over Under Full Time<\/td>\n<td><strong>152<\/strong><\/td>\n<\/tr>\n<tr>\n<td>Corners &#8211; Over Under First Half<\/td>\n<td>143<\/td>\n<\/tr>\n<tr>\n<td>Corners &#8211; 1X2<\/td>\n<td>140<\/td>\n<\/tr>\n<tr>\n<td>Corners &#8211; Over Under Team 2<\/td>\n<td>132<\/td>\n<\/tr>\n<tr>\n<td>Corners &#8211; Over Under Team 1<\/td>\n<td>131<\/td>\n<\/tr>\n<tr>\n<td>Corners &#8211; 1X2 First Half<\/td>\n<td>110<\/td>\n<\/tr>\n<tr>\n<td>Corners &#8211; Over Under Team 1 First Half<\/td>\n<td>102<\/td>\n<\/tr>\n<tr>\n<td>Corners &#8211; Over Under Team 2 First Half<\/td>\n<td>102<\/td>\n<\/tr>\n<tr>\n<td>Corners &#8211; Over Under Second Half<\/td>\n<td>90<\/td>\n<\/tr>\n<tr>\n<td>Corners &#8211; Odd Even<\/td>\n<td>69<\/td>\n<\/tr>\n<tr>\n<td>Corners &#8211; Over Under Team 1 Second Half<\/td>\n<td>69<\/td>\n<\/tr>\n<tr>\n<td>Corners &#8211; Over Under Team 2 Second Half<\/td>\n<td>69<\/td>\n<\/tr>\n<tr>\n<td>Corners &#8211; Handicap<\/td>\n<td>68<\/td>\n<\/tr>\n<tr>\n<td>Corners &#8211; 1X2 Second Half<\/td>\n<td>60<\/td>\n<\/tr>\n<tr>\n<td>Corners &#8211; Odd Even First Half<\/td>\n<td>55<\/td>\n<\/tr>\n<tr>\n<td>Corners &#8211; Handicap First Half<\/td>\n<td>44<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/figure>\n<p>The remaining six sit in a long tail of second-half and per-team odd\/even variants, on 1 to 15 books each.<\/p>\n<h2>Step 7: Card and booking markets<\/h2>\n<p>Cards split into two products. Match-level booking counts behave like a total. Player-level &#8220;to be carded&#8221; behaves like a prop, keyed by player ID.<\/p>\n<pre class=\"wp-block-code\"><code>def card_markets(payload, cat):\n    out = defaultdict(set)\n    for slug, book in (payload.get(\"bookmakerOdds\") or {}).items():\n        for market_id, market in (book.get(\"markets\") or {}).items():\n            name = cat.get(market_id, (\"\",))[0]\n            if family(name) == \"bookings\":\n                out[name].add(slug)\n    return out\n\ndef carded_players(payload, cat):\n    rows = []\n    for slug, book in (payload.get(\"bookmakerOdds\") or {}).items():\n        for market_id, market in (book.get(\"markets\") or {}).items():\n            if not cat.get(market_id, (\"\",))[0].startswith(\"Player To Be Carded\"):\n                continue\n            for outcome in (market.get(\"outcomes\") or {}).values():\n                for player_id, price in (outcome.get(\"players\") or {}).items():\n                    if player_id == \"0\" or not isinstance(price, dict):\n                        continue\n                    if not price.get(\"price\") or price.get(\"active\") is False:\n                        continue\n                    rows.append((slug, price.get(\"playerName\"), price[\"price\"]))\n    return rows\n\n# each row is (bookmaker slug, playerName, decimal price)\n# playerName arrives in \"Last, First\" format\n<\/code><\/pre>\n<p>On game lines <code>players<\/code> holds a single <code>\"0\"<\/code> key. On player-carded markets it is keyed by player ID with a <code>playerName<\/code> in &#8220;Last, First&#8221; format. Hardcoding <code>players[\"0\"]<\/code> returns an empty result and looks like missing coverage.<\/p>\n<p>Run it on a fixture close to kickoff and the volume is the point. Real Madrid against Real Sociedad returned 1,608 player-carded prices across 54 books. Malaga against Deportivo, sampled on its kickoff day, returned 621 across 60 books and carried 23 card and booking families in total from 196 books:<\/p>\n<figure class=\"wp-block-table\">\n<table>\n<thead>\n<tr>\n<th>Market family<\/th>\n<th>Books<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Bookings &#8211; Over Under Full Time<\/td>\n<td><strong>128<\/strong><\/td>\n<\/tr>\n<tr>\n<td>Bookings &#8211; Over Under Team 1<\/td>\n<td>106<\/td>\n<\/tr>\n<tr>\n<td>Bookings &#8211; Over Under Team 2<\/td>\n<td>95<\/td>\n<\/tr>\n<tr>\n<td>Bookings &#8211; 1X2<\/td>\n<td>94<\/td>\n<\/tr>\n<tr>\n<td>Bookings &#8211; Over Under First Half<\/td>\n<td>80<\/td>\n<\/tr>\n<tr>\n<td>Player To Be Carded<\/td>\n<td>79<\/td>\n<\/tr>\n<tr>\n<td>Bookings &#8211; Over Under Team 1 First Half<\/td>\n<td>50<\/td>\n<\/tr>\n<tr>\n<td>Bookings &#8211; 1X2 First Half<\/td>\n<td>48<\/td>\n<\/tr>\n<tr>\n<td>Bookings &#8211; Over Under Team 2 First Half<\/td>\n<td>41<\/td>\n<\/tr>\n<tr>\n<td>Bookings &#8211; 1X2 Second Half<\/td>\n<td>31<\/td>\n<\/tr>\n<tr>\n<td>Bookings &#8211; Handicap<\/td>\n<td>20<\/td>\n<\/tr>\n<tr>\n<td>Bookings &#8211; Odd Even<\/td>\n<td>10<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/figure>\n<p>Across the whole 30-fixture sample, <code>Bookings - Over Under Full Time<\/code> appeared on 129 books and <code>Bookings - 1X2<\/code> on 99.<\/p>\n<p><strong>Pinnacle prices bookings.<\/strong> On the played fixtures tested above it quoted five booking families on the Championship, the Brasileirao, LaLiga, Serie A and the Premier League, so the sharp benchmark exists on the card market too, on a majority of the competitions sampled.<\/p>\n<p>One note before you de-vig a booking total. Depth on this family is a function of the clock more than anything else. On a fixture sampled on its kickoff day there were 128 books on the full-time booking count, which is more consensus than you need. On a fixture six days out the same family had not opened, and in between you get a handful of books rather than a hundred. Count the independent quotes on the fixture in front of you, and read the <a href=\"https:\/\/oddspapi.io\/blog\/consensus-odds-fair-odds-calculator-python\/\">consensus odds guide<\/a> for how many a fair number needs.<\/p>\n<h2>Step 8: Time your poller to the clock<\/h2>\n<pre class=\"wp-block-code\"><code>def open_clock(fixture_id, kickoff, cat, slug=\"pinnacle\"):\n    data = api(\"\/historical-odds\", fixtureId=fixture_id, bookmakers=slug) or {}\n    book = (data.get(\"bookmakers\") or {}).get(slug) or {}\n    ko = datetime.fromisoformat(kickoff.replace(\"Z\", \"+00:00\"))\n    first = {}\n    for market_id, market in (book.get(\"markets\") or {}).items():\n        name = cat.get(market_id, (\"\",))[0]\n        fam = family(name)\n        for outcome in (market.get(\"outcomes\") or {}).values():\n            snaps = (outcome.get(\"players\") or {}).get(\"0\") or []\n            if not snaps:\n                continue\n            t = datetime.fromisoformat(snaps[0][\"createdAt\"].replace(\"Z\", \"+00:00\"))\n            if fam not in first or t &lt; first[fam]:\n                first[fam] = t\n    return {fam: (ko - t).total_seconds() \/ 86400 for fam, t in first.items()}\n\n# Malaga v Deportivo\n# {'match': 10.62, 'corners': 3.0, 'bookings': 1.06}\n<\/code><\/pre>\n<p>Run that on a handful of fixtures in the competition you care about and you get its own schedule rather than mine. Run it on fixtures that have already been played and you also get the book&#8217;s full menu, which a live call cannot give you. Then start polling side markets at five days out and not before. <code>\/historical-odds<\/code> allows three bookmakers per call and needs roughly 4.5 seconds between successful calls, so a season of open times costs you patience and nothing else.<\/p>\n<h2>Corners and cards quick reference<\/h2>\n<figure class=\"wp-block-table\">\n<table>\n<thead>\n<tr>\n<th>Item<\/th>\n<th>Value, 30 fixtures sampled 24 August 2026<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Books on a fixture<\/td>\n<td>178 median, 161 min, 195 max<\/td>\n<\/tr>\n<tr>\n<td>Books quoting corners<\/td>\n<td>92 median, 50 min, 156 max<\/td>\n<\/tr>\n<tr>\n<td>Corner market open<\/td>\n<td>Median T-2.77 days, never earlier than 4.00<\/td>\n<\/tr>\n<tr>\n<td>Bookings market open<\/td>\n<td>Median T-1.11 days<\/td>\n<\/tr>\n<tr>\n<td>Main corner family<\/td>\n<td><code>Corners - Over Under Full Time<\/code>, 152 books<\/td>\n<\/tr>\n<tr>\n<td>Consensus corner line<\/td>\n<td>10.5 on the worked LaLiga fixture, 121 of 187 books; resolve by book count<\/td>\n<\/tr>\n<tr>\n<td>Corner margin<\/td>\n<td>Median 1.27x the same book&#8217;s three-way, 80% of pairs higher<\/td>\n<\/tr>\n<tr>\n<td>Pinnacle limit base<\/td>\n<td>Match 6x to 12x the corner base; corner to bookings order varies<\/td>\n<\/tr>\n<tr>\n<td>Pinnacle corners<\/td>\n<td>All ten competitions tested: 8 families domestic, 4 in European club competition<\/td>\n<\/tr>\n<tr>\n<td>Player carded<\/td>\n<td>Keyed by player ID, never <code>players[\"0\"]<\/code><\/td>\n<\/tr>\n<tr>\n<td>Parsing guards<\/td>\n<td>Reject three-outcome markets and whole-number lines<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/figure>\n<h2>Get your key<\/h2>\n<p>Corners and cards are the markets most odds APIs skip and most bettors price by feel. One call gives you the full ladder from a median of 92 books quoting corners, the sharp benchmark with its limits attached, and the free history that tells you when each market opened.<\/p>\n<p><a href=\"https:\/\/oddspapi.io\/\">Get your free OddsPapi API key<\/a> and run the open-clock script on your own league.<\/p>\n<h2>Where to go next<\/h2>\n<ul>\n<li><a href=\"https:\/\/oddspapi.io\/blog\/premier-league-odds-api\/\">Premier League Odds API<\/a> and <a href=\"https:\/\/oddspapi.io\/blog\/la-liga-odds-api\/\">La Liga Odds API<\/a> for the per-league board in detail<\/li>\n<li><a href=\"https:\/\/oddspapi.io\/blog\/ligue-1-odds-api\/\">Ligue 1 Odds API<\/a> for why coverage resolves per fixture rather than per league<\/li>\n<li><a href=\"https:\/\/oddspapi.io\/blog\/champions-league-odds-api\/\">Champions League Odds API<\/a> for European club competition<\/li>\n<li><a href=\"https:\/\/oddspapi.io\/blog\/player-props-api-nfl-nba-mlb-odds-python\/\">Player Props API<\/a> for the player-keyed payload shape used by the carded market<\/li>\n<li><a href=\"https:\/\/oddspapi.io\/blog\/vig-calculator-python-sportsbook-margin\/\">Vig calculator<\/a> and <a href=\"https:\/\/oddspapi.io\/blog\/line-shopping-python-best-odds\/\">line shopping in Python<\/a> for the margin maths applied across the board<\/li>\n<li><a href=\"https:\/\/oddspapi.io\/blog\/historical-odds-csv-excel-backtesting\/\">Historical odds to CSV<\/a> to bulk-export what the open-clock script samples<\/li>\n<li><a href=\"https:\/\/oddspapi.io\/blog\/websocket-odds-api-real-time-betting-data\/\">WebSocket odds feed<\/a> once you stop polling<\/li>\n<\/ul>\n<h2>FAQ<\/h2>\n<h3>Does the OddsPapi API have corner odds?<\/h3>\n<p>Yes. Across 30 fixtures in ten competitions sampled on 24 August 2026, full-time corner totals appeared on a median of 92 bookmakers per fixture, with 50 on the thinnest board and 156 on the deepest. The feed carries 22 corner market families covering half splits, per-team counts, handicaps and a three-way. A LaLiga fixture close to kickoff carried 6,769 corner markets. The market opens about three days before kickoff, so a query made a week ahead returns nothing.<\/p>\n<h3>When do corner and booking markets open?<\/h3>\n<p>Measured across 30 fixtures in ten competitions on 24 August 2026, Pinnacle opened corners a median 2.77 days before kickoff and never earlier than 4.00 days. Bookings opened a median 1.11 days out. Match markets have no single answer: the median on that regular round was 6.07 days, but Valencia v Real Betis opened 50.50 days out and Bayern v Stuttgart 53.45 days out. Poll side markets from five days out, not before.<\/p>\n<h3>Are corner odds more expensive than the match market?<\/h3>\n<p>Usually. Across 2,276 book-and-fixture pairs sampled on 24 August 2026 the median corner margin was 1.27 times the same book&#8217;s three-way margin, and 80% of pairs charged more for corners. The gap is not uniform across books. On Real Madrid v Real Sociedad, Kalshi was the widest corner quote of all 119 ranked books at 46.03% while its three-way sat at 3.02%, and Polymarket was the tightest at 5.00%.<\/p>\n<h3>Why does a corner total sum to less than 100%?<\/h3>\n<p>Two reasons. A whole-number line such as 10.0 pushes when the game lands on exactly ten corners, so the two prices legitimately sum below 100%. And Corners &#8211; 1X2 is a three-way market whose half variants ship only two outcomes, so pairing them is a parser bug. Across the 24 August 2026 sample, 102 of 17,314 two-sided corner quotes summed to 100% or less: 74 whole-number lines and 28 Corners &#8211; 1X2. Reject both before de-vigging.<\/p>\n<h3>Which bookmakers price card and booking markets?<\/h3>\n<p>Widely, once the market opens. On Malaga v Deportivo, sampled on its kickoff day, Bookings &#8211; Over Under Full Time appeared on 128 books, Bookings &#8211; 1X2 on 94 and Player To Be Carded on 79. Across the whole 24 August 2026 sample the full-time booking total appeared on 129 books and Bookings &#8211; 1X2 on 99. Pinnacle prices bookings on the Championship, the Brasileirao, LaLiga, Serie A and the Premier League, and did not price them on the Eredivisie, the Champions League or the Europa League.<\/p>\n<h3>Can I see when a market opened without paying?<\/h3>\n<p>Yes. The historical-odds endpoint is on the free tier and its first snapshot timestamp is the market&#8217;s open time. The limit is three bookmakers per call and roughly one call every 4.5 seconds. To test whether a book covers a market at all, run it on a fixture that has already been played: the live prices are dropped after the game but the history is retained, so you see the full menu rather than only what the clock has opened.<\/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\": \"Does the OddsPapi API have corner odds?\",\n      \"acceptedAnswer\": {\n        \"@type\": \"Answer\",\n        \"text\": \"Yes. Across 30 fixtures in ten competitions sampled on 24 August 2026, full-time corner totals appeared on a median of 92 bookmakers per fixture, with 50 on the thinnest board and 156 on the deepest. The feed carries 22 corner market families covering half splits, per-team counts, handicaps and a three-way. A LaLiga fixture close to kickoff carried 6,769 corner markets. The market opens about three days before kickoff, so a query made a week ahead returns nothing.\"\n      }\n    },\n    {\n      \"@type\": \"Question\",\n      \"name\": \"When do corner and booking markets open?\",\n      \"acceptedAnswer\": {\n        \"@type\": \"Answer\",\n        \"text\": \"Measured across 30 fixtures in ten competitions on 24 August 2026, Pinnacle opened corners a median 2.77 days before kickoff and never earlier than 4.00 days. Bookings opened a median 1.11 days out. Match markets have no single answer: the median on that regular round was 6.07 days, but Valencia v Real Betis opened 50.50 days out and Bayern v Stuttgart 53.45 days out. Poll side markets from five days out, not before.\"\n      }\n    },\n    {\n      \"@type\": \"Question\",\n      \"name\": \"Are corner odds more expensive than the match market?\",\n      \"acceptedAnswer\": {\n        \"@type\": \"Answer\",\n        \"text\": \"Usually. Across 2,276 book-and-fixture pairs sampled on 24 August 2026 the median corner margin was 1.27 times the same book's three-way margin, and 80% of pairs charged more for corners. The gap is not uniform across books. On Real Madrid v Real Sociedad, Kalshi was the widest corner quote of all 119 ranked books at 46.03% while its three-way sat at 3.02%, and Polymarket was the tightest at 5.00%.\"\n      }\n    },\n    {\n      \"@type\": \"Question\",\n      \"name\": \"Why does a corner total sum to less than 100%?\",\n      \"acceptedAnswer\": {\n        \"@type\": \"Answer\",\n        \"text\": \"Two reasons. A whole-number line such as 10.0 pushes when the game lands on exactly ten corners, so the two prices legitimately sum below 100%. And Corners - 1X2 is a three-way market whose half variants ship only two outcomes, so pairing them is a parser bug. Across the 24 August 2026 sample, 102 of 17,314 two-sided corner quotes summed to 100% or less: 74 whole-number lines and 28 Corners - 1X2. Reject both before de-vigging.\"\n      }\n    },\n    {\n      \"@type\": \"Question\",\n      \"name\": \"Which bookmakers price card and booking markets?\",\n      \"acceptedAnswer\": {\n        \"@type\": \"Answer\",\n        \"text\": \"Widely, once the market opens. On Malaga v Deportivo, sampled on its kickoff day, Bookings - Over Under Full Time appeared on 128 books, Bookings - 1X2 on 94 and Player To Be Carded on 79. Across the whole 24 August 2026 sample the full-time booking total appeared on 129 books and Bookings - 1X2 on 99. Pinnacle prices bookings on the Championship, the Brasileirao, LaLiga, Serie A and the Premier League, and did not price them on the Eredivisie, the Champions League or the Europa League.\"\n      }\n    },\n    {\n      \"@type\": \"Question\",\n      \"name\": \"Can I see when a market opened without paying?\",\n      \"acceptedAnswer\": {\n        \"@type\": \"Answer\",\n        \"text\": \"Yes. The historical-odds endpoint is on the free tier and its first snapshot timestamp is the market's open time. The limit is three bookmakers per call and roughly one call every 4.5 seconds. To test whether a book covers a market at all, run it on a fixture that has already been played: the live prices are dropped after the game but the history is retained, so you see the full menu rather than only what the clock has opened.\"\n      }\n    }\n  ]\n}\n<\/script><\/p>\n<p><!--\nFocus Keyphrase: corners odds api\nSEO Title: Corners & Cards Odds API: Pull Football Side Markets in Python (Free Tier)\nMeta Description: Corner and card odds from a median of 92 bookmakers in Python. Free OddsPapi tier, tested code, and the 3-day clock that decides when side markets open.\nSlug: corners-cards-odds-api\n--><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Corner and card odds from a median of 92 bookmakers in Python. Free OddsPapi tier, tested code, and the 3-day clock that decides when side markets open.<\/p>\n","protected":false},"author":2,"featured_media":3676,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7],"tags":[12,8,9,11,15],"class_list":["post-3675","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-how-to-guides","tag-betting-data","tag-free-api","tag-odds-api","tag-python","tag-soccer"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v26.4 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Corners &amp; Cards Odds API: The Three-Day Clock on Side Markets | 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\/corners-cards-odds-api\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Corners &amp; Cards Odds API: The Three-Day Clock on Side Markets | OddsPapi Blog\" \/>\n<meta property=\"og:description\" content=\"Corner and card odds from a median of 92 bookmakers in Python. Free OddsPapi tier, tested code, and the 3-day clock that decides when side markets open.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/oddspapi.io\/blog\/corners-cards-odds-api\/\" \/>\n<meta property=\"og:site_name\" content=\"OddsPapi Blog\" \/>\n<meta property=\"article:published_time\" content=\"2026-08-27T10:00:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-08-29T14:57:55+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/08\/corners-cards-odds-api-scaled.webp\" \/>\n\t<meta property=\"og:image:width\" content=\"2560\" \/>\n\t<meta property=\"og:image:height\" content=\"1429\" \/>\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=\"20 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/oddspapi.io\/blog\/corners-cards-odds-api\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/oddspapi.io\/blog\/corners-cards-odds-api\/\"},\"author\":{\"name\":\"Odds API Writer\",\"@id\":\"https:\/\/oddspapi.io\/blog\/#\/schema\/person\/b6f21e649c4f556f0a95c23a0f1efa13\"},\"headline\":\"Corners &#038; Cards Odds API: The Three-Day Clock on Side Markets\",\"datePublished\":\"2026-08-27T10:00:00+00:00\",\"dateModified\":\"2026-08-29T14:57:55+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/oddspapi.io\/blog\/corners-cards-odds-api\/\"},\"wordCount\":3334,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/oddspapi.io\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/oddspapi.io\/blog\/corners-cards-odds-api\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/08\/corners-cards-odds-api-scaled.webp\",\"keywords\":[\"Betting Data\",\"Free API\",\"Odds API\",\"Python\",\"Soccer\"],\"articleSection\":[\"How To Guides\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/oddspapi.io\/blog\/corners-cards-odds-api\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/oddspapi.io\/blog\/corners-cards-odds-api\/\",\"url\":\"https:\/\/oddspapi.io\/blog\/corners-cards-odds-api\/\",\"name\":\"Corners & Cards Odds API: The Three-Day Clock on Side Markets | OddsPapi Blog\",\"isPartOf\":{\"@id\":\"https:\/\/oddspapi.io\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/oddspapi.io\/blog\/corners-cards-odds-api\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/oddspapi.io\/blog\/corners-cards-odds-api\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/08\/corners-cards-odds-api-scaled.webp\",\"datePublished\":\"2026-08-27T10:00:00+00:00\",\"dateModified\":\"2026-08-29T14:57:55+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/oddspapi.io\/blog\/corners-cards-odds-api\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/oddspapi.io\/blog\/corners-cards-odds-api\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/oddspapi.io\/blog\/corners-cards-odds-api\/#primaryimage\",\"url\":\"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/08\/corners-cards-odds-api-scaled.webp\",\"contentUrl\":\"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/08\/corners-cards-odds-api-scaled.webp\",\"width\":2560,\"height\":1429,\"caption\":\"Corners & Cards Odds API - OddsPapi API Blog\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/oddspapi.io\/blog\/corners-cards-odds-api\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/oddspapi.io\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Corners &#038; Cards Odds API: The Three-Day Clock on Side Markets\"}]},{\"@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":"Corners & Cards Odds API: The Three-Day Clock on Side Markets | 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\/corners-cards-odds-api\/","og_locale":"en_US","og_type":"article","og_title":"Corners & Cards Odds API: The Three-Day Clock on Side Markets | OddsPapi Blog","og_description":"Corner and card odds from a median of 92 bookmakers in Python. Free OddsPapi tier, tested code, and the 3-day clock that decides when side markets open.","og_url":"https:\/\/oddspapi.io\/blog\/corners-cards-odds-api\/","og_site_name":"OddsPapi Blog","article_published_time":"2026-08-27T10:00:00+00:00","article_modified_time":"2026-08-29T14:57:55+00:00","og_image":[{"width":2560,"height":1429,"url":"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/08\/corners-cards-odds-api-scaled.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":"20 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/oddspapi.io\/blog\/corners-cards-odds-api\/#article","isPartOf":{"@id":"https:\/\/oddspapi.io\/blog\/corners-cards-odds-api\/"},"author":{"name":"Odds API Writer","@id":"https:\/\/oddspapi.io\/blog\/#\/schema\/person\/b6f21e649c4f556f0a95c23a0f1efa13"},"headline":"Corners &#038; Cards Odds API: The Three-Day Clock on Side Markets","datePublished":"2026-08-27T10:00:00+00:00","dateModified":"2026-08-29T14:57:55+00:00","mainEntityOfPage":{"@id":"https:\/\/oddspapi.io\/blog\/corners-cards-odds-api\/"},"wordCount":3334,"commentCount":0,"publisher":{"@id":"https:\/\/oddspapi.io\/blog\/#organization"},"image":{"@id":"https:\/\/oddspapi.io\/blog\/corners-cards-odds-api\/#primaryimage"},"thumbnailUrl":"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/08\/corners-cards-odds-api-scaled.webp","keywords":["Betting Data","Free API","Odds API","Python","Soccer"],"articleSection":["How To Guides"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/oddspapi.io\/blog\/corners-cards-odds-api\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/oddspapi.io\/blog\/corners-cards-odds-api\/","url":"https:\/\/oddspapi.io\/blog\/corners-cards-odds-api\/","name":"Corners & Cards Odds API: The Three-Day Clock on Side Markets | OddsPapi Blog","isPartOf":{"@id":"https:\/\/oddspapi.io\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/oddspapi.io\/blog\/corners-cards-odds-api\/#primaryimage"},"image":{"@id":"https:\/\/oddspapi.io\/blog\/corners-cards-odds-api\/#primaryimage"},"thumbnailUrl":"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/08\/corners-cards-odds-api-scaled.webp","datePublished":"2026-08-27T10:00:00+00:00","dateModified":"2026-08-29T14:57:55+00:00","breadcrumb":{"@id":"https:\/\/oddspapi.io\/blog\/corners-cards-odds-api\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/oddspapi.io\/blog\/corners-cards-odds-api\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/oddspapi.io\/blog\/corners-cards-odds-api\/#primaryimage","url":"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/08\/corners-cards-odds-api-scaled.webp","contentUrl":"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/08\/corners-cards-odds-api-scaled.webp","width":2560,"height":1429,"caption":"Corners & Cards Odds API - OddsPapi API Blog"},{"@type":"BreadcrumbList","@id":"https:\/\/oddspapi.io\/blog\/corners-cards-odds-api\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/oddspapi.io\/blog\/"},{"@type":"ListItem","position":2,"name":"Corners &#038; Cards Odds API: The Three-Day Clock on Side Markets"}]},{"@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\/3675","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=3675"}],"version-history":[{"count":3,"href":"https:\/\/oddspapi.io\/blog\/wp-json\/wp\/v2\/posts\/3675\/revisions"}],"predecessor-version":[{"id":3809,"href":"https:\/\/oddspapi.io\/blog\/wp-json\/wp\/v2\/posts\/3675\/revisions\/3809"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/oddspapi.io\/blog\/wp-json\/wp\/v2\/media\/3676"}],"wp:attachment":[{"href":"https:\/\/oddspapi.io\/blog\/wp-json\/wp\/v2\/media?parent=3675"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/oddspapi.io\/blog\/wp-json\/wp\/v2\/categories?post=3675"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/oddspapi.io\/blog\/wp-json\/wp\/v2\/tags?post=3675"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}