{"id":3728,"date":"2026-09-05T10:00:00","date_gmt":"2026-09-05T10:00:00","guid":{"rendered":"https:\/\/oddspapi.io\/blog\/?p=3728"},"modified":"2026-08-29T14:58:01","modified_gmt":"2026-08-29T14:58:01","slug":"lol-odds-api","status":"publish","type":"post","link":"https:\/\/oddspapi.io\/blog\/lol-odds-api\/","title":{"rendered":"LoL Odds API: 119 Books on the LEC, LCK and LPL Board"},"content":{"rendered":"<p>Riot does not publish a betting odds API. The esports data vendors that do will quote you an annual contract before they show you a payload. So developers building a League of Legends model end up scraping two or three sportsbooks and calling it a market.<\/p>\n<p>That was a defensible shortcut a year ago. It is not one now. We pulled every LoL fixture on the OddsPapi feed on 27 August 2026 and counted <strong>119 distinct bookmakers<\/strong> across 36 pre-match series, with a median of <strong>63.5 books per fixture<\/strong> and 101 on the deepest LEC game.<\/p>\n<p>The board is bigger than the football board most people assume is the ceiling. It is also shaped nothing like it, and the book you would reach for first is the wrong one.<\/p>\n<h2>The finding: Pinnacle is not the LoL benchmark<\/h2>\n<p>On soccer, on baseball, on the NFL, you anchor on Pinnacle and measure everything else against it. That habit fails on League of Legends in two ways at once.<\/p>\n<p>First, coverage. Pinnacle priced <strong>17 of the 36 pre-match series<\/strong>. Polymarket priced 35. Kalshi 30. 1xBet and 22Bet were on all 36. If your scanner filters to Pinnacle you throw away half the slate before you start.<\/p>\n<p>Second, price. Across every book quoting at least 8 of the 36 series, here is the median two-way margin on the series Winner market.<\/p>\n<figure class=\"wp-block-table\">\n<table>\n<thead>\n<tr>\n<th>Rank<\/th>\n<th>Bookmaker<\/th>\n<th>Median Winner margin<\/th>\n<th>Series priced (of 36)<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>1<\/td>\n<td><code>polymarket.us<\/code><\/td>\n<td>1.51%<\/td>\n<td>22<\/td>\n<\/tr>\n<tr>\n<td>2<\/td>\n<td><code>kalshi<\/code><\/td>\n<td>1.99%<\/td>\n<td>30<\/td>\n<\/tr>\n<tr>\n<td>3<\/td>\n<td><code>polymarket<\/code><\/td>\n<td>2.00%<\/td>\n<td>35<\/td>\n<\/tr>\n<tr>\n<td>4<\/td>\n<td><code>duel<\/code><\/td>\n<td>3.83%<\/td>\n<td>30<\/td>\n<\/tr>\n<tr>\n<td>5<\/td>\n<td><code>roobet<\/code><\/td>\n<td>5.38%<\/td>\n<td>26<\/td>\n<\/tr>\n<tr>\n<td>6<\/td>\n<td><code>betfair-ex<\/code><\/td>\n<td>6.35%<\/td>\n<td>13<\/td>\n<\/tr>\n<tr>\n<td>7<\/td>\n<td><code>1xbet<\/code><\/td>\n<td>6.35%<\/td>\n<td>36<\/td>\n<\/tr>\n<tr>\n<td>8<\/td>\n<td><code>22bet<\/code><\/td>\n<td>6.35%<\/td>\n<td>36<\/td>\n<\/tr>\n<tr>\n<td><strong>14<\/strong><\/td>\n<td><strong><code>pinnacle<\/code><\/strong><\/td>\n<td><strong>6.46%<\/strong><\/td>\n<td><strong>17<\/strong><\/td>\n<\/tr>\n<tr>\n<td>20<\/td>\n<td><code>betano<\/code><\/td>\n<td>7.05%<\/td>\n<td>31<\/td>\n<\/tr>\n<tr>\n<td>21<\/td>\n<td><code>bet365<\/code><\/td>\n<td>7.08%<\/td>\n<td>30<\/td>\n<\/tr>\n<tr>\n<td>68<\/td>\n<td><code>stake<\/code><\/td>\n<td>8.07%<\/td>\n<td>32<\/td>\n<\/tr>\n<tr>\n<td>76<\/td>\n<td><code>betway<\/code><\/td>\n<td>8.33%<\/td>\n<td>31<\/td>\n<\/tr>\n<tr>\n<td>100<\/td>\n<td><code>netbet.co.uk<\/code><\/td>\n<td>17.50%<\/td>\n<td>32<\/td>\n<\/tr>\n<\/tbody>\n<\/table><figcaption>100 bookmakers ranked, measured 27 Aug 2026 across 36 pre-match LoL series. Complete two-sided quotes only, suspended prices excluded.<\/figcaption><\/figure>\n<p>Pinnacle charges 6.46% on a LoL series and 3 to 4% on a football match. Kalshi charges 1.99% on the same LoL series. Thirteen books beat Pinnacle, and eight of the top eight are exchanges, prediction markets or crypto books. Read our <a href=\"https:\/\/oddspapi.io\/blog\/vig-calculator-python-sportsbook-margin\/\">vig calculator guide<\/a> if you want the margin arithmetic in full.<\/p>\n<p>Kalshi being tighter does not make Kalshi sharper. The two venues price a LoL series for different reasons. What it does mean is that if you benchmark against Pinnacle alone on esports, you are benchmarking against a book that shows up half the time and charges twice its usual rate.<\/p>\n<h2>Old way vs OddsPapi<\/h2>\n<figure class=\"wp-block-table\">\n<table>\n<thead>\n<tr>\n<th><\/th>\n<th>Scraping 3 books<\/th>\n<th>Esports data vendor<\/th>\n<th>OddsPapi<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Books per series<\/td>\n<td>3<\/td>\n<td>20-40<\/td>\n<td><strong>Median 63.5, max 101<\/strong><\/td>\n<\/tr>\n<tr>\n<td>Prediction markets<\/td>\n<td>No<\/td>\n<td>Rare<\/td>\n<td>Kalshi, Polymarket, Betfair, SX Bet<\/td>\n<\/tr>\n<tr>\n<td>Map-level markets<\/td>\n<td>Build your own parser<\/td>\n<td>Yes<\/td>\n<td>Native, 8 families<\/td>\n<\/tr>\n<tr>\n<td>Historical prices<\/td>\n<td>Whatever you stored<\/td>\n<td>Paid add-on<\/td>\n<td><strong>Free tier<\/strong><\/td>\n<\/tr>\n<tr>\n<td>Access<\/td>\n<td>Cloudflare roulette<\/td>\n<td>Sales call<\/td>\n<td>Free API key<\/td>\n<\/tr>\n<tr>\n<td>Format<\/td>\n<td>HTML<\/td>\n<td>JSON + contract<\/td>\n<td>JSON<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/figure>\n<h2>Step 1: authenticate and find the sport<\/h2>\n<p>The key is a query parameter, never a header.<\/p>\n<pre class=\"wp-block-code\"><code>import requests, time, collections\n\nAPI_KEY  = \"YOUR_API_KEY\"\nBASE_URL = \"https:\/\/api.oddspapi.io\/v4\"\nLOL      = 18                      # sportId for ESport League of Legends\n\ndef call(path, **params):\n    \"\"\"One request, honouring the documented 429 retry.\"\"\"\n    for _ in range(6):\n        r = requests.get(f\"{BASE_URL}{path}\",\n                         params={\"apiKey\": API_KEY, **params}, timeout=120)\n        if r.status_code == 429:\n            time.sleep(r.json()[\"error\"][\"retryMs\"] \/ 1000 + 0.3)\n            continue\n        return r\n    return r\n\nsports = call(\"\/sports\").json()\nprint([s for s in sports if s[\"sportId\"] == LOL])\n# [{'sportId': 18, 'slug': 'esport-league-of-legends', 'sportName': 'ESport League of Legends'}]\n<\/code><\/pre>\n<p>The free tier rate-limits per endpoint and returns a real 429 with a <code>retryMs<\/code> figure in the body. Sleep about a second between calls on the same endpoint and never run <code>\/odds<\/code> concurrently. Four parallel workers get eleven of twelve requests rejected.<\/p>\n<h2>Step 2: discover circuits from \/fixtures, not \/tournaments<\/h2>\n<p>This is the trap that costs you 40% of the slate. The LoL catalogue holds 90 tournament rows, and each carries a <code>futureFixtures<\/code> count. On most sports that count is the right filter. On LoL it lies.<\/p>\n<pre class=\"wp-block-code\"><code>fixtures = call(\"\/fixtures\", sportId=LOL,\n                **{\"from\": \"2026-08-27\", \"to\": \"2026-09-06\"}).json()\npriced = [f for f in fixtures if f.get(\"hasOdds\")]\n\ncircuits = collections.Counter(\n    (f[\"tournamentId\"], f[\"tournamentName\"]) for f in priced)\nfor (tid, name), n in circuits.most_common():\n    print(f\"{n:3d}  {tid:6d}  {name}\")\n\n# The \/tournaments row disagrees:\nrows = {t[\"tournamentId\"]: t.get(\"futureFixtures\", 0)\n        for t in call(\"\/tournaments\", sportId=LOL).json()}\nblind = sum(n for (tid, _), n in circuits.items() if not rows.get(tid))\nprint(f\"\\n{blind} of {len(priced)} priced fixtures sit under a \"\n      f\"tournament row reporting futureFixtures = 0\")\n<\/code><\/pre>\n<pre class=\"wp-block-code\"><code>  7    2452  LEC\n  4   39985  LPL\n  4   26698  CBLOL\n  4    2450  LCS\n  3   39009  NACL\n  2   26706  TCL\n  2   45855  Rift Legends\n  2   45985  Road of Legends\n  2   46121  Circuito Desafiante\n  1    2454  LCK\n  1   33814  Prime League\n  1   33678  LFL\n  1   45589  LCP\n  1   36997  LCK CL\n  1   46117  LRN\n  1   50586  LES\n\n15 of 37 priced fixtures sit under a tournament row reporting futureFixtures = 0\n<\/code><\/pre>\n<p>LPL, LCK, LCS and CBLOL all report zero future fixtures. All four had priced games inside 48 hours. Go through <code>\/fixtures<\/code> and group by <code>tournamentName<\/code>.<\/p>\n<p>Two more things in that output. <code>LPL<\/code> exists twice in the catalogue (rows 15490 and 39985) and only 39985 carries fixtures, so match on the ID you saw in a real fixture rather than the name. And the tail of that list is the interesting part: Rift Legends, Road of Legends, LES and LRN are tier-2 and tier-3 circuits that a scraper aimed at LEC and LCK never sees.<\/p>\n<h2>Step 3: pull one board and read the market families<\/h2>\n<p>Market IDs and outcome IDs are integers. Names come from <code>\/markets<\/code>. Do not hardcode the catalogue: it holds 32,815 rows and it is global rather than per-sport, so use it as a lookup.<\/p>\n<pre class=\"wp-block-code\"><code>catalogue    = call(\"\/markets\", sportId=LOL).json()\nMARKET_NAME  = {m[\"marketId\"]: m[\"marketName\"]   for m in catalogue}\nHANDICAP     = {m[\"marketId\"]: m.get(\"handicap\") for m in catalogue}\n\nfx    = next(f for f in priced if f[\"fixtureId\"] == \"id1803998573998788\")\nboard = call(\"\/odds\", fixtureId=fx[\"fixtureId\"]).json()[\"bookmakerOdds\"]\nprint(f'{fx[\"participant1Name\"]} v {fx[\"participant2Name\"]} '\n      f'({fx[\"tournamentName\"]}) - {len(board)} bookmakers')\n\nfamilies = collections.defaultdict(set)\nfor slug, book in board.items():\n    for market_id in book[\"markets\"]:\n        families[MARKET_NAME.get(int(market_id), \"?\")].add(slug)\nfor name, slugs in sorted(families.items(), key=lambda x: -len(x[1])):\n    print(f\"  {name:45s} {len(slugs):3d} books\")\n<\/code><\/pre>\n<pre class=\"wp-block-code\"><code>Edward Gaming v Ninjas In Pyjamas (LPL) - 98 bookmakers\n  Winner                                         97 books\n  Maps Handicap                                  86 books\n  First Map Winner (incl. overtime)              83 books\n  Second Map Winner (incl. overtime)             82 books\n  Total Maps Over Under                          81 books\n  Third Map Winner (incl. overtime)              78 books\n  Fourth Map Winner (incl. overtime)             33 books\n  Fifth Map Winner (incl. overtime)              29 books\n<\/code><\/pre>\n<p>Eight families and that is the whole menu. Across all 36 series we counted zero player props: every price on the LoL board is keyed <code>players[\"0\"]<\/code>, so the kill\/assist markets you see on a book&#8217;s own site do not reach the aggregated feed.<\/p>\n<p>What you get instead is the native series structure. A LoL match is a best-of-three or best-of-five, and the feed models it that way: a series Winner, a Maps Handicap ladder (-1.5 through +1.5, one market ID per rung), a Total Maps line at 2.5, 3.5 or 4.5, and a separate Winner market for each individual map with <code>period<\/code> set to <code>p1<\/code> through <code>p5<\/code>. The Fifth Map Winner only carries 29 books because most books post it once a best-of-five is 2-2.<\/p>\n<p><strong>Winner is a single market ID on LoL.<\/strong> Market 181, outcome 181 for participant 1 and 182 for participant 2. Boxing splits the same bet across three IDs and rugby across two, so this is worth stating: on LoL you can key on 181 and lose nothing. The outcome names in the catalogue are literally <code>\"1\"<\/code> and <code>\"2\"<\/code>, so join <code>fixtureId<\/code> back to <code>\/fixtures<\/code> for team names.<\/p>\n<h2>Step 4: filter to usable quotes, then dedupe<\/h2>\n<p>98 books is the headline number and it is not the number you can bet into. Two filters cut it down.<\/p>\n<pre class=\"wp-block-code\"><code>WINNER = 181                    # outcome 181 = participant 1, 182 = participant 2\n\ndef winner_quote(book):\n    \"\"\"Return (p1, p2) only when both legs are present AND active.\"\"\"\n    market = book[\"markets\"].get(str(WINNER))\n    if not market:\n        return None\n    legs = []\n    for outcome_id in (\"181\", \"182\"):\n        outcome = market[\"outcomes\"].get(outcome_id)\n        if not outcome:\n            return None\n        price = outcome[\"players\"][\"0\"]      # game lines are always keyed \"0\"\n        if not price.get(\"active\") or not price.get(\"price\"):\n            return None\n        legs.append(float(price[\"price\"]))\n    return tuple(legs)\n\nquotes = {}\nfor slug, book in board.items():\n    if slug.startswith(\"pinnacle+\") or slug == \"demo\":   # internal test feeds\n        continue\n    q = winner_quote(book)\n    if q:\n        quotes[slug] = q\n\ngroups = collections.defaultdict(list)\nfor slug, q in quotes.items():\n    groups[q].append(slug)\n\nprint(f\"{len(board)} books on the board\")\nprint(f\"{len(quotes)} with a complete, active Winner quote\")\nprint(f\"{len(groups)} independent prices \"\n      f\"({100 * (1 - len(groups) \/ len(quotes)):.1f}% collapse)\")\n\nbiggest = max(groups.items(), key=lambda g: len(g[1]))\nprint(f\"largest duplicate group: {len(biggest[1])} slugs at {biggest[0]}\")\n<\/code><\/pre>\n<pre class=\"wp-block-code\"><code>98 books on the board\n93 with a complete, active Winner quote\n31 independent prices (66.7% collapse)\nlargest duplicate group: 24 slugs at (2.95, 1.36)\n<\/code><\/pre>\n<p>Two of every three bookmaker rows on a LoL series repeat a price you already have. Across all 36 pre-match series the collapse runs <strong>60.7%<\/strong>: 2,285 complete quotes become 899 independent ones. The 24-slug group above includes <code>atg.se<\/code>, <code>betmgm.co.uk<\/code>, <code>betplay<\/code>, <code>betrivers<\/code>, <code>betuk<\/code>, <code>bingoal.be<\/code>, <code>casumo<\/code>, <code>expekt.se<\/code>, <code>fourwinds<\/code> and <code>grosvenor<\/code>, and every one of them reports <code>cloneOf: null<\/code>. The clone flag does not track feed reality, so dedupe on the price tuple, per fixture.<\/p>\n<p>The <code>pinnacle+<\/code> skip in that code matters too. <code>pinnacle<\/code>, <code>pinnacle+30<\/code> and <code>pinnacle+5<\/code> are internal test feeds that ship in live payloads, and on 13 of the 18 series where Pinnacle appeared at least one of them quoted the identical price. Count them and you count Pinnacle three times.<\/p>\n<h2>Step 5: rank the board and take the best price<\/h2>\n<pre class=\"wp-block-code\"><code>ladder = sorted(((1 \/ a + 1 \/ b - 1) * 100, slug, (a, b))\n                for slug, (a, b) in quotes.items())\nfor rank, (margin, slug, price) in enumerate(ladder, 1):\n    if rank &lt;= 8 or slug in (\"pinnacle\", \"bet365\", \"stake\"):\n        print(f\"{rank:4d}. {slug:16s} {margin:6.2f}%  {price}\")\n\nbest  = (max(p[0] for p in quotes.values()), max(p[1] for p in quotes.values()))\nsharp = quotes[\"pinnacle\"]\nprint(f\"\\npinnacle {sharp}  best on board {best}\")\nprint(\"gain: \" + \"  \".join(f\"{100 * (best[i] \/ sharp[i] - 1):+.2f}%\" for i in (0, 1)))\n<\/code><\/pre>\n<pre class=\"wp-block-code\"><code>   1. kalshi             1.00%  (3.448, 1.389)\n   2. polymarket         1.00%  (3.448, 1.389)\n   3. polymarket.us      1.00%  (3.448, 1.389)\n   4. duel               3.38%  (3.35, 1.36)\n   5. 3et                5.40%  (3.25, 1.34)\n   6. roobet             5.40%  (3.25, 1.34)\n   7. pinnacle           5.88%  (3.46, 1.299)\n   8. betfury            6.44%  (3.2, 1.33)\n  49. bet365             7.79%  (2.75, 1.4)\n  74. stake              8.17%  (3.2, 1.3)\n\npinnacle (3.46, 1.299)  best on board (3.61, 1.455)\ngain: +4.34%  +12.01%\n<\/code><\/pre>\n<p>Taking the best of 93 books instead of Pinnacle is worth 4.34% on the underdog and 12.01% on the favourite, on one LPL series. Our <a href=\"https:\/\/oddspapi.io\/blog\/line-shopping-python-best-odds\/\">line shopping walkthrough<\/a> generalises the same loop across sports.<\/p>\n<h3>Check the ladder before you trust a prediction-market price<\/h3>\n<p>Kalshi and Polymarket lead that table. Depth decides whether either price is worth anything. Exchange-type books ship an <code>exchangeMeta<\/code> object with a three-level <code>back<\/code> ladder; sportsbooks ship <code>null<\/code>. Summing the stake capacity across those three levels on every LoL price we pulled:<\/p>\n<figure class=\"wp-block-table\">\n<table>\n<thead>\n<tr>\n<th>Venue<\/th>\n<th>Median back-ladder stake<\/th>\n<th>Max<\/th>\n<th>Priced outcomes<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>polymarket<\/code><\/td>\n<td>$978.42<\/td>\n<td>$46,510.28<\/td>\n<td>474<\/td>\n<\/tr>\n<tr>\n<td><code>kalshi<\/code><\/td>\n<td>$798.49<\/td>\n<td>$45,464.91<\/td>\n<td>281<\/td>\n<\/tr>\n<tr>\n<td><code>polymarket.us<\/code><\/td>\n<td><strong>$0.00<\/strong><\/td>\n<td><strong>$0.00<\/strong><\/td>\n<td>176<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/figure>\n<p><code>polymarket.us<\/code> posts the tightest median margin on the whole sport at 1.51% and carries nothing behind it on any of the 176 outcomes we sampled. Polymarket and Kalshi are the opposite: roughly a thousand dollars of depth on a median LoL outcome, which is real money for an esports market. Screen on margin and ladder depth together, never on margin alone. The <a href=\"https:\/\/oddspapi.io\/blog\/polymarket-api-kalshi-api-vs-sportsbooks-the-developers-guide\/\">prediction market guide<\/a> covers the ladder shape in more detail.<\/p>\n<h2>The Maps Handicap ladder, and the one sport where mainLine works<\/h2>\n<p>Every handicap rung is its own market ID. -1.5 is 1825, +1.5 is 1837, and the worked fixture carried 15 rung IDs from 86 books. So you need to resolve which rung is the real line.<\/p>\n<p>Each price object carries a <code>mainLine<\/code> boolean that claims to answer this. On tennis it matches the consensus line 8.6% of the time. On the NFL 46%. On rugby FanDuel flags every single rung true. We ran the same test on LoL, resolving the consensus rung as each book&#8217;s own most balanced quote and then taking the mode across books:<\/p>\n<pre class=\"wp-block-code\"><code>mainLine flags on Maps Handicap: 2217\nmatching the resolved consensus rung: 1856 (83.7%)\n\nworst books        best books\n  polymarket   5.6%   bwin            100.0%\n  gamdom      32.4%   roobet          100.0%\n  1xbet       47.5%   sportingbet     100.0%\n  22bet       47.5%   bcgame          100.0%\n<\/code><\/pre>\n<p><strong>83.7% is the highest figure we have measured on any sport.<\/strong> LoL handicaps sit on a short ladder with an obvious centre, so the flag mostly agrees with the market. It still misses one rung in six, and Polymarket gets it wrong 19 times in 20, so keep the balanced-rung resolver as your source of truth and treat <code>mainLine<\/code> as a hint.<\/p>\n<h2>When the LoL board opens<\/h2>\n<p><code>\/historical-odds<\/code> is on the free tier, so the opening time of every book is free to measure. Take the first snapshot per bookmaker on one series.<\/p>\n<pre class=\"wp-block-code\"><code>import datetime\n\nFIXTURE = \"id1803998573998788\"\nKICKOFF = datetime.datetime.fromisoformat(\"2026-08-28T06:00:00+00:00\")\n\ndef opened(slug):\n    \"\"\"First recorded snapshot for one book, in days before kick-off.\"\"\"\n    r = call(\"\/historical-odds\", fixtureId=FIXTURE, bookmakers=slug)\n    if r.status_code != 200:\n        return None\n    book = r.json()[\"bookmakers\"].get(slug)\n    if not book:\n        return None\n    stamps, changes = [], 0\n    for market in book[\"markets\"].values():\n        for outcome in market[\"outcomes\"].values():\n            history = outcome[\"players\"][\"0\"]      # a LIST here, not a dict\n            previous = None\n            for snap in history:\n                stamps.append(snap[\"createdAt\"])\n                if previous is not None and snap[\"price\"] != previous:\n                    changes += 1\n                previous = snap[\"price\"]\n    first = datetime.datetime.fromisoformat(min(stamps).replace(\"Z\", \"+00:00\"))\n    return (KICKOFF - first).total_seconds() \/ 86400, len(stamps), changes\n\nfor slug in [\"stake\", \"1xbet\", \"bet365\", \"kalshi\", \"betano\", \"pinnacle\"]:\n    result = opened(slug)\n    if result:\n        days, snaps, changes = result\n        print(f\"{slug:10s} opened T-{days:4.2f}d   {snaps:6d} snapshots   {changes:4d} price changes\")\n    time.sleep(4.6)\n<\/code><\/pre>\n<pre class=\"wp-block-code\"><code>stake      opened T-4.21d      312 snapshots    212 price changes\n1xbet      opened T-4.17d     1428 snapshots     72 price changes\nbet365     opened T-4.17d     1050 snapshots     42 price changes\nkalshi     opened T-3.21d    14556 snapshots   2884 price changes\nbetano     opened T-2.72d     2010 snapshots    179 price changes\npinnacle   opened T-1.25d      450 snapshots    298 price changes\n<\/code><\/pre>\n<p>The whole LoL board opens inside about four days. A football league opener posts two months out; a Grand Slam first round posts six hours out; LoL sits between them and compresses everything into a long weekend. <strong>Pinnacle is the last book in<\/strong>, at T-1.25 days here and T-1.68 on an LEC game we ran the same test on.<\/p>\n<p>Late does not mean idle. Pinnacle logged 298 price changes across 450 snapshots while Bet365 logged 42 across 1,050. Count changes rather than snapshots: the feed records on a cadence and most snapshots repeat the previous price.<\/p>\n<p>Two mechanical notes on that endpoint. It caps at <strong>three bookmakers per call<\/strong> and a batch containing one slug your key cannot read returns nothing at all, so retry failed batches one slug at a time. And <code>betfair-ex<\/code> and <code>polymarket<\/code> both reject a multi-book call outright: pass one bookmaker and one <code>outcomeId<\/code>, or leave them out of the batch.<\/p>\n<h2>Caveats worth coding around<\/h2>\n<figure class=\"wp-block-table\">\n<table>\n<thead>\n<tr>\n<th>Behaviour<\/th>\n<th>What it does to your parser<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>76.9% of prices are <code>active<\/code><\/td>\n<td>Roughly a quarter of the board is posted and suspended. Filter on the price-level <code>active<\/code> flag, not <code>marketActive<\/code>.<\/td>\n<\/tr>\n<tr>\n<td>In-play boards look deep and are not<\/td>\n<td>A live LCK game returned 103 books and 21.6% active prices. Only 25 carried a complete two-sided Winner quote.<\/td>\n<\/tr>\n<tr>\n<td>127 book records ship <code>suspended: true<\/code><\/td>\n<td>They still return prices. Check <code>book[\"suspended\"]<\/code> before adding a book to consensus.<\/td>\n<\/tr>\n<tr>\n<td>Tier-3 circuits bottom out at 13 books<\/td>\n<td>Depth ranges 13 to 101. Count the board per fixture rather than per sport.<\/td>\n<\/tr>\n<tr>\n<td>No FanDuel, no SBOBet, DraftKings on 3 of 36<\/td>\n<td>US retail barely prices LoL. Do not build a US-book-only esports scanner.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/figure>\n<h2>Where to go next<\/h2>\n<p>The same eight-family structure and the same dedupe problem show up across the rest of the esports board. Our <a href=\"https:\/\/oddspapi.io\/blog\/esports-odds-api-guide-how-to-get-pinnacle-cs2-lol-data-for-free\/\">esports odds API hub<\/a> covers CS2 and Dota alongside LoL, the <a href=\"https:\/\/oddspapi.io\/blog\/valorant-odds-api-vct-pinnacle-polymarket\/\">Valorant guide<\/a> runs the same measurement on VCT, and if you arrived here comparing vendors, we wrote up <a href=\"https:\/\/oddspapi.io\/blog\/pandascore-api-alternative-free-esports-odds\/\">PandaScore<\/a> and <a href=\"https:\/\/oddspapi.io\/blog\/abios-esports-api-alternative\/\">Abios<\/a> against the free tier.<\/p>\n<h2>Get the data<\/h2>\n<p>Every number on this page came from the free tier: 37 fixtures, 119 bookmakers, 37,653 prices and a full historical pull, with no card and no sales call. Grab a key, run the discovery block against today&#8217;s slate and see what your three scraped books have been missing.<\/p>\n<p><a href=\"https:\/\/oddspapi.io\/\">Get your free OddsPapi API key<\/a> and pull the LoL board in the next five minutes.<\/p>\n<h2>FAQ<\/h2>\n<h3>Is there an official League of Legends betting odds API?<\/h3>\n<p>No. Riot publishes match and esports data APIs but no odds feed. Betting prices come from the bookmakers themselves or from an aggregator. OddsPapi covers LoL under <code>sportId<\/code> 18 and returned 119 distinct bookmakers across 36 pre-match series on 27 August 2026.<\/p>\n<h3>Which bookmakers cover League of Legends?<\/h3>\n<p>1xBet and 22Bet priced all 36 series we sampled. Polymarket covered 35, Stake 33, Bet365 32, Betway 32, Betano 32, Kalshi 30, Pinnacle 17 and Betfair Exchange 13. DraftKings appeared on 3 and FanDuel on none.<\/p>\n<h3>Does Pinnacle cover LoL?<\/h3>\n<p>Partially. Pinnacle priced 17 of 36 series and posted a 6.46% median margin on the series Winner, which ranks it 14th of 100 bookmakers. It also opens last, about a day before the match. Use it as one input rather than as the benchmark.<\/p>\n<h3>What LoL markets does the API return?<\/h3>\n<p>Eight families: series Winner, Maps Handicap, Total Maps Over Under, and a separate Winner market for maps one through five. There are no player props on the LoL feed. Every price is keyed <code>players[\"0\"]<\/code>.<\/p>\n<h3>How do I find which LoL circuits have odds?<\/h3>\n<p>Pull <code>\/fixtures<\/code> with <code>sportId=18<\/code> and group the results by <code>tournamentName<\/code>. The <code>futureFixtures<\/code> count on <code>\/tournaments<\/code> reported zero for LPL, LCK, LCS and CBLOL while all four had priced games inside 48 hours.<\/p>\n<h3>Is historical LoL odds data free?<\/h3>\n<p>Yes. <code>\/historical-odds<\/code> is on the free tier and returns the full snapshot history for a fixture, capped at three bookmakers per call. That is how the opening-time table above was built.<\/p>\n<p><script type=\"application\/ld+json\">\n{\"@context\":\"https:\/\/schema.org\",\"@type\":\"FAQPage\",\"mainEntity\":[\n{\"@type\":\"Question\",\"name\":\"Is there an official League of Legends betting odds API?\",\"acceptedAnswer\":{\"@type\":\"Answer\",\"text\":\"No. Riot publishes match and esports data APIs but no odds feed. Betting prices come from the bookmakers themselves or from an aggregator. OddsPapi covers LoL under sportId 18 and returned 119 distinct bookmakers across 36 pre-match series on 27 August 2026.\"}},\n{\"@type\":\"Question\",\"name\":\"Which bookmakers cover League of Legends?\",\"acceptedAnswer\":{\"@type\":\"Answer\",\"text\":\"1xBet and 22Bet priced all 36 series we sampled. Polymarket covered 35, Stake 33, Bet365 32, Betway 32, Betano 32, Kalshi 30, Pinnacle 17 and Betfair Exchange 13. DraftKings appeared on 3 and FanDuel on none.\"}},\n{\"@type\":\"Question\",\"name\":\"Does Pinnacle cover LoL?\",\"acceptedAnswer\":{\"@type\":\"Answer\",\"text\":\"Partially. Pinnacle priced 17 of 36 series and posted a 6.46% median margin on the series Winner, which ranks it 14th of 100 bookmakers. It also opens last, about a day before the match. Use it as one input rather than as the benchmark.\"}},\n{\"@type\":\"Question\",\"name\":\"What LoL markets does the API return?\",\"acceptedAnswer\":{\"@type\":\"Answer\",\"text\":\"Eight families: series Winner, Maps Handicap, Total Maps Over Under, and a separate Winner market for maps one through five. There are no player props on the LoL feed. Every price is keyed players[\\\"0\\\"].\"}},\n{\"@type\":\"Question\",\"name\":\"How do I find which LoL circuits have odds?\",\"acceptedAnswer\":{\"@type\":\"Answer\",\"text\":\"Pull \/fixtures with sportId=18 and group the results by tournamentName. The futureFixtures count on \/tournaments reported zero for LPL, LCK, LCS and CBLOL while all four had priced games inside 48 hours.\"}},\n{\"@type\":\"Question\",\"name\":\"Is historical LoL odds data free?\",\"acceptedAnswer\":{\"@type\":\"Answer\",\"text\":\"Yes. \/historical-odds is on the free tier and returns the full snapshot history for a fixture, capped at three bookmakers per call. That is how the opening-time table above was built.\"}}]}\n<\/script><\/p>\n<p><!--\nFocus Keyphrase: lol odds api\nSEO Title: LoL Odds API: Live LEC, LCK & LPL Odds in Python (Free Tier)\nMeta Description: Pull League of Legends odds from 119 bookmakers in Python. Free LoL odds API with map handicaps, Kalshi and Polymarket, and free historical prices.\nSlug: lol-odds-api\n--><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Pull League of Legends odds from 119 bookmakers in Python. Free LoL odds API with map handicaps, Kalshi and Polymarket, plus free historical prices.<\/p>\n","protected":false},"author":2,"featured_media":3729,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7],"tags":[13,8,94,9,11],"class_list":["post-3728","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-how-to-guides","tag-esports","tag-free-api","tag-league-of-legends","tag-odds-api","tag-python"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v26.4 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>LoL Odds API: 119 Books on the LEC, LCK and LPL Board | 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\/lol-odds-api\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"LoL Odds API: 119 Books on the LEC, LCK and LPL Board | OddsPapi Blog\" \/>\n<meta property=\"og:description\" content=\"Pull League of Legends odds from 119 bookmakers in Python. Free LoL odds API with map handicaps, Kalshi and Polymarket, plus free historical prices.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/oddspapi.io\/blog\/lol-odds-api\/\" \/>\n<meta property=\"og:site_name\" content=\"OddsPapi Blog\" \/>\n<meta property=\"article:published_time\" content=\"2026-09-05T10:00:00+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/08\/lol-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=\"14 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/oddspapi.io\/blog\/lol-odds-api\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/oddspapi.io\/blog\/lol-odds-api\/\"},\"author\":{\"name\":\"Odds API Writer\",\"@id\":\"https:\/\/oddspapi.io\/blog\/#\/schema\/person\/b6f21e649c4f556f0a95c23a0f1efa13\"},\"headline\":\"LoL Odds API: 119 Books on the LEC, LCK and LPL Board\",\"datePublished\":\"2026-09-05T10:00:00+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/oddspapi.io\/blog\/lol-odds-api\/\"},\"wordCount\":1886,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/oddspapi.io\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/oddspapi.io\/blog\/lol-odds-api\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/08\/lol-odds-api-scaled.webp\",\"keywords\":[\"Esports\",\"Free API\",\"League of Legends\",\"Odds API\",\"Python\"],\"articleSection\":[\"How To Guides\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/oddspapi.io\/blog\/lol-odds-api\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/oddspapi.io\/blog\/lol-odds-api\/\",\"url\":\"https:\/\/oddspapi.io\/blog\/lol-odds-api\/\",\"name\":\"LoL Odds API: 119 Books on the LEC, LCK and LPL Board | OddsPapi Blog\",\"isPartOf\":{\"@id\":\"https:\/\/oddspapi.io\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/oddspapi.io\/blog\/lol-odds-api\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/oddspapi.io\/blog\/lol-odds-api\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/08\/lol-odds-api-scaled.webp\",\"datePublished\":\"2026-09-05T10:00:00+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/oddspapi.io\/blog\/lol-odds-api\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/oddspapi.io\/blog\/lol-odds-api\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/oddspapi.io\/blog\/lol-odds-api\/#primaryimage\",\"url\":\"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/08\/lol-odds-api-scaled.webp\",\"contentUrl\":\"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/08\/lol-odds-api-scaled.webp\",\"width\":2560,\"height\":1429,\"caption\":\"LoL Odds API - OddsPapi API Blog\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/oddspapi.io\/blog\/lol-odds-api\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/oddspapi.io\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"LoL Odds API: 119 Books on the LEC, LCK and LPL Board\"}]},{\"@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":"LoL Odds API: 119 Books on the LEC, LCK and LPL Board | 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\/lol-odds-api\/","og_locale":"en_US","og_type":"article","og_title":"LoL Odds API: 119 Books on the LEC, LCK and LPL Board | OddsPapi Blog","og_description":"Pull League of Legends odds from 119 bookmakers in Python. Free LoL odds API with map handicaps, Kalshi and Polymarket, plus free historical prices.","og_url":"https:\/\/oddspapi.io\/blog\/lol-odds-api\/","og_site_name":"OddsPapi Blog","article_published_time":"2026-09-05T10:00:00+00:00","og_image":[{"width":2560,"height":1429,"url":"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/08\/lol-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":"14 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/oddspapi.io\/blog\/lol-odds-api\/#article","isPartOf":{"@id":"https:\/\/oddspapi.io\/blog\/lol-odds-api\/"},"author":{"name":"Odds API Writer","@id":"https:\/\/oddspapi.io\/blog\/#\/schema\/person\/b6f21e649c4f556f0a95c23a0f1efa13"},"headline":"LoL Odds API: 119 Books on the LEC, LCK and LPL Board","datePublished":"2026-09-05T10:00:00+00:00","mainEntityOfPage":{"@id":"https:\/\/oddspapi.io\/blog\/lol-odds-api\/"},"wordCount":1886,"commentCount":0,"publisher":{"@id":"https:\/\/oddspapi.io\/blog\/#organization"},"image":{"@id":"https:\/\/oddspapi.io\/blog\/lol-odds-api\/#primaryimage"},"thumbnailUrl":"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/08\/lol-odds-api-scaled.webp","keywords":["Esports","Free API","League of Legends","Odds API","Python"],"articleSection":["How To Guides"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/oddspapi.io\/blog\/lol-odds-api\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/oddspapi.io\/blog\/lol-odds-api\/","url":"https:\/\/oddspapi.io\/blog\/lol-odds-api\/","name":"LoL Odds API: 119 Books on the LEC, LCK and LPL Board | OddsPapi Blog","isPartOf":{"@id":"https:\/\/oddspapi.io\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/oddspapi.io\/blog\/lol-odds-api\/#primaryimage"},"image":{"@id":"https:\/\/oddspapi.io\/blog\/lol-odds-api\/#primaryimage"},"thumbnailUrl":"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/08\/lol-odds-api-scaled.webp","datePublished":"2026-09-05T10:00:00+00:00","breadcrumb":{"@id":"https:\/\/oddspapi.io\/blog\/lol-odds-api\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/oddspapi.io\/blog\/lol-odds-api\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/oddspapi.io\/blog\/lol-odds-api\/#primaryimage","url":"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/08\/lol-odds-api-scaled.webp","contentUrl":"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/08\/lol-odds-api-scaled.webp","width":2560,"height":1429,"caption":"LoL Odds API - OddsPapi API Blog"},{"@type":"BreadcrumbList","@id":"https:\/\/oddspapi.io\/blog\/lol-odds-api\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/oddspapi.io\/blog\/"},{"@type":"ListItem","position":2,"name":"LoL Odds API: 119 Books on the LEC, LCK and LPL Board"}]},{"@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\/3728","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=3728"}],"version-history":[{"count":2,"href":"https:\/\/oddspapi.io\/blog\/wp-json\/wp\/v2\/posts\/3728\/revisions"}],"predecessor-version":[{"id":3815,"href":"https:\/\/oddspapi.io\/blog\/wp-json\/wp\/v2\/posts\/3728\/revisions\/3815"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/oddspapi.io\/blog\/wp-json\/wp\/v2\/media\/3729"}],"wp:attachment":[{"href":"https:\/\/oddspapi.io\/blog\/wp-json\/wp\/v2\/media?parent=3728"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/oddspapi.io\/blog\/wp-json\/wp\/v2\/categories?post=3728"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/oddspapi.io\/blog\/wp-json\/wp\/v2\/tags?post=3728"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}