Each market's closing line, and closing line value on every large trade and per wallet
GET /api/v1/market/{condition_id}/close is new. It returns a sports or esports market’s closing price on each side, read from Polymarket’s price history in the last minute before kickoff, with the interval and source it came from. A market without one says pending or unavailable with a reason, never 0.Every large trade now carries clv, its closing line value against that close, on GET /api/v1/large-trades, /large-trades/history, /large-trades/{id}, and the trades on /events/feed/since:status:measured,in_play(placed at or after kickoff),pending(the close is not stored yet), orunavailable, withunavailable_reason.clv_cents: positive when the trade beat the close. On a buy it is the closing price minus the price paid, on a sell the price received minus the closing price, in cents per share and before fees.close_price,close_anchor_at,pre_kickoff, andbasis_version(clv@v1).
GET /api/v1/trader/{address}/clv is new. It sums a wallet’s large trades in a window: average CLV, size-weighted average, the share that beat the close, and a per-market average with a 95% interval.The remote MCP server adds the tools get_market_close and get_trader_clv. The stdio MCP server, the CLI (market close, traders clv) and the TypeScript client (getMarketClose, getTraderClv) add them in their next release. Both endpoints need a Pro or Max key.Backward compatible. clv is a new field on the large trade object; no field changed.What to change: Nothing. If your client refuses unknown fields on a large trade, allow clv.SDK 0.40.0 and MCP 3.14.0 carry game market settlement, quotes and trading terms
@0xinsider/sdk 0.40.0 and @0xinsider/mcp 3.14.0 are on npm, and 3.14.0 is in the MCP Registry. They bring the November 4 game market changes listed below to the SDK types, the local MCP server and the CLI.Before these releases, the local list_game_markets tool in 3.13.0 accepted only "sharp_money" in expand and refused "quotes" and "trading_terms" with an input validation error. SDK 0.39.0 had no type for settlement, quote or trading_terms. The entries below said the MCP tool and the SDK types describe these fields, which was true of the remote MCP server and not yet of the packages you install.- SDK: every
listGameMarketsrow carriessettlement,expand: ["quotes"]adds each outcome’squote, andexpand: ["trading_terms"]adds each row’strading_terms, withmin_order_size_shares. - SDK:
getMarketSnapshotand thegetGamewinner markets carrysettlement, andlistGamestakesexpand: ["settlement"]. - Local MCP:
list_game_marketstakes"quotes"and"trading_terms"inexpand, andlist_gamestakesexpandas one value or an array of"sharp_money"and"settlement". Thelist_game_markets,list_games,get_gameandget_market_snapshotdescriptions match the remote server’s. - Both: the
leaguedescription says to spell a league as the list’s owncoverage.leaguesdoes, sinceGET /api/v1/coveragelists no leagues.
@0xinsider/mcp@3.14.0.Backward compatible. Every change adds a type, a field or an expand value, and one list_games expand value still works.What to change: Run npm install @0xinsider/sdk@0.40.0. For the CLI and the local MCP server, run npm install --global @0xinsider/mcp@3.14.0, or change a client’s @0xinsider/mcp@3.13.0 argument to @0xinsider/mcp@3.14.0. 0xinsider --version prints 3.14.0 once the update is in place.A team keeps one name before, during and after its game, the name its moneyline outcome uses
GET /api/v1/games and GET /api/v1/games/{event_slug}, and the MCP list_games and get_game tools, now give a team the same competitors[].name in every state: upcoming, live and finished. It is the moneyline outcome that names the team, in the outcome’s own text, so a side reads as the label Polymarket prices it under.Before this change, the name depended on the game’s state. Over every upcoming and live game and every game finished since October 28, read on November 4, 573 teams in 43 leagues carried more than one name; with this change, none do. An upcoming NFL game read Jacksonville Jaguars while its moneyline, and the same team’s finished games, read Jaguars. A finished Premier League game read Villa while upcoming ones read Aston Villa FC.- NFL upcoming games: the nickname the outcomes use (
Jaguars,Ravens). NHL:Utah, notMammoth. - Tennis, every state: the full name the outcome uses (
Jacopo Vasami, notJ. Vasami). - MLB and other finished games: the outcome’s name (
Milwaukee Brewers, notBrewers). - Soccer, whose win markets read
YesandNo: the club’s full name in every state (Aston Villa FC). - Where Polymarket’s outcome drops an accent, so does the name (
Fenerbahce). Where an outcome names a team some other way (CanadaforTeam Canada), the team’s full name stays. - Upcoming games’
markets[].outcome_yesandoutcome_nocarry the same text. provider_id,logo,sideand price values are unchanged. No team lost aprovider_idor a paired price.
competitors[].name values changed, and upcoming games’ outcome labels with them.What to change: A client that matched a team by its old name should match by provider_id, which is the same in every state, or by the name now served.Game markets carry each market's minimum order size in shares on expand=trading_terms
GET /api/v1/games/{event_slug}/markets with expand=trading_terms now carries trading_terms.min_order_size_shares: the smallest order Polymarket’s order book accepts for the market, in shares. It is Polymarket’s orderMinSize, read from the same market record as the other terms.Before this change, trading_terms left the minimum order size out. Polymarket’s market reference calls the figure USDC and its order guide calls it shares. Polymarket’s order book accepts a limit order of exactly that many shares at the smallest price step, worth as little as $0.05, so the unit is shares.min_order_size_shares: a number, ornullwhen the record carries none orstatusis notobserved. It was5on every open sports market we read on November 4.- Compare it with an order’s share count, not its dollar cost. A buy of 5 shares at $0.40 costs $2.00 and meets a minimum of 5.
- The
list_game_marketsMCP tool, the SDK types and the OpenAPI document describe the same.
min_order_size_shares instead of a separate order book request.Finished soccer games name the home and away side of each team-win market
A finished soccer game in
GET /api/v1/games/{event_slug} and GET /api/v1/games now sends side home or away on its two team-win markets after it leaves the live board, as it did before kickoff. The draw market keeps side draw.Before this change, those two markets left out side, so only the market slug told a client which team each one priced. On November 4, 2026 that was 2,130 markets of the 1,065 finished soccer games since October 28.- The team is the one Polymarket’s own title for the market names, such as
FC Bayern München, matched to one of the game’s twocompetitors. The first competitor ishome, the secondaway. sideis still left out when the game’s markets store no team pair, when the title names neither competitor or both, when both markets name the same team, or when the market’s slug names the other team. It is never taken from the slug or from the order of the markets.- Other sports, and soccer games still on the live board, are unchanged.
side was already documented on these markets and is now sent where it was missing.What to change: Nothing. If you read a finished soccer market’s team from its slug, read side instead.Quotes and snapshots no longer serve a 0 bid or a 1 ask for a side with no orders
GET /api/v1/games/{event_slug}/markets with expand=quotes and GET /api/v1/market/{condition_id}/snapshot now serve a book with one side, or with no orders, as that book for as long as we stream it, also after its side moves, flips or empties.Polymarket’s best bid and ask stream sends a side with no orders as a bid of 0 or an ask of 1. Before this change, we stored that as a price. Such a book read as two-sided, then as missing:- Its quote carried
best_bid: 0orbest_ask: 1, and its snapshot readtop_of_book.status: available. On November 4 at 11:27 UTC, the junjilopzfx0764 vs. Stronghold Overwatch moneyline (ow-jun-strong-2026-11-04) served junjilopzfx0764 at bid 0 / ask 0.97 and Stronghold at bid 0.03 / ask 1, while Polymarket’s book held only asks for the first and only bids for the second. - Once that book went 30 seconds without an update, the outcome read
unavailable(cache_misson the snapshot). The same market readcache_missfrom 11:37 to 11:42 UTC while its Polymarket book stayed the same.
- A served
best_bidis never0and a servedbest_askis never1. A side with no orders isnullbeside a setbook_observed_at, and the outcome staysobservedwhile its book has one side or none. - The snapshot reads
one_sided_bookorempty_bookfor such a book, neveravailable. - Books with orders on both sides are unchanged.
0 bid or a 1 ask as a price can drop that handling.Finished games that store no team pair show each side's crest, and its provider_id where it has one
A finished game in
GET /api/v1/games/{event_slug} and GET /api/v1/games whose markets store no pair of team ids now matches each side to one of the two teams its slug names. Each matched side carries that team’s logo, and its provider_id where the team has one. Most of these are FCS college football games: Polymarket has no team id for many of those schools.Before this change, such a game served each side’s name with no provider_id and no logo:- Bryant vs. Brown on October 10 (
cfb-bryant-brwn-2026-10-10) served neither side’s id or logo, though Bryant’s id is231. - 63 finished college football games played since October 5 were affected. Of their 126 sides, 30 carried an id and 86 a logo.
- How a side is matched: by its outcome name, such as
Brown, against the two teams the slug’s codes name (bryant,brwn), exactly or by its words, never by position. When a stored final score names neither side’s team, the settled moneyline decides: the side with the higher score is the team the winning outcome names. logois the team’s crest.provider_idis the team’s id, or absent when the team has none. In the 63 games, 44 sides now carry an id and 125 a logo.coverage.competitorsisprovider_idsonly when both sides carry an id, elselabels. One Counter-Strike game, maybe vs. Honvéd on November 2, now readsprovider_ids.- Games whose markets store a team pair are unchanged.
Quotes and snapshots say when reading again will not bring a market's live book
GET /api/v1/games/{event_slug}/markets with expand=quotes adds book_unavailable_reason to each outcome’s quote, and GET /api/v1/market/{condition_id}/snapshot adds the reason stream_capacity.We always stream Polymarket’s order book for the sports boards and for liquid games around kickoff. Any other open market gets a live book when you read it, up to a shared number of markets that API reads can hold at once. Before this change, a read past that number answered like a first read (unavailable on a quote, cache_miss on a snapshot), so reading again looked as if it would help, and it did not. On November 4, one read of every active market of the 23 live games asked for 359 markets against room for 100, and 31 markets with a two-sided Polymarket book stayed unavailable.quote.book_unavailable_reasonisnullwhenbook_observed_atis set. Otherwise it iscache_miss(no book held yet; read again after a few seconds),stream_capacity(API reads already hold every live book they can open; reading again does not help until fewer markets are read),no_orderbookormissing_provider_token_id.- The snapshot’s
outcomes[].top_of_book.reasonandfreshness.top_of_book.reasonreadstream_capacityinstead ofcache_missin the same case. - A market we always stream no longer takes one of those places when you read it, so more of the markets you read get a live book.
- The
list_game_marketsMCP tool, the SDK types and the OpenAPI document describe the same.
book_unavailable_reason is a new key, and stream_capacity is a new value of an existing string field. A client that treats an unknown snapshot reason as “no book” keeps working.What to change: If you poll many markets, read book_unavailable_reason: on stream_capacity, read fewer markets, or that one less often, instead of retrying it.Quotes and snapshots serve a book with one side or no orders, not unavailable
GET /api/v1/games/{event_slug}/markets with expand=quotes now serves an outcome whose Polymarket order book holds orders on one side only, or none, as observed: the side with orders carries its best price, an empty side is null, and book_observed_at is set. GET /api/v1/market/{condition_id}/snapshot names the same books in top_of_book.reason.Before this change, such an outcome read unavailable with every figure null, and the snapshot read cache_miss, for as long as the book stayed that way; a later read did not fill it. On November 4 that was about 260 empty and 60 one-sided books across the live games.quote.statusisobservedwithbook_observed_atset and anullbest_bid(no bids) orbest_ask(no asks), or bothnullfor an empty book.priceis unchanged.- The snapshot’s
top_of_book.statusstaysavailableonly for a book with both sides. A book with one side isunavailablewithreasonone_sided_bookand carries that side’sbest_bidorbest_ask, with no spread or depth; an empty book isunavailablewithreasonempty_book. freshness.top_of_book.reasontakes the same values:one_sided_bookwhen either outcome’s book has one side, thenempty_book, thencache_miss.- The
list_game_marketsMCP tool and the OpenAPI document describe the same.
status and reason first. A client that took a present snapshot best_bid or best_ask to mean a two-sided book now also sees one beside unavailable.What to change: Nothing, unless you read snapshot prices without checking top_of_book.status; then check it. To tell an empty side from a missing figure on a quote, read book_observed_at.Finished tennis doubles games from October 17 to 31 name both pairs as the two sides
A finished ATP or WTA doubles game in
GET /api/v1/games/{event_slug} and GET /api/v1/games now names each side by its pair, such as Bolelli/Vavassori, with the pair’s provider_id and logo. This applies to doubles games whose stored live score was written before October 31, 2026.Before this change, such a game named one player on each side, often the two partners of one pair, and the other pair was missing:- Bolelli/Vavassori vs. Andreozzi/Guinard on October 30 served
Simone Bolelli(noprovider_id) againstA. Vavassori, with his singles id625505, the Italian flag and arecord. - 272 doubles games played October 17 to 31 were affected, 201 ATP and 71 WTA. In 234 of them
coverage.competitorswaslabels. The other 38 carried singles players’ ids.
- How a side is matched: by the pair code in the game’s slug (
bolevav,andrgui), in the slug’s order, as for doubles games stored since October 31. This applies only while both sides’ scores are0, the placeholder Polymarket sends for doubles games. A side with a real score keeps its stored name. name,provider_id,logo: the pair’s, as on other doubles games.recordisnull: the stored record was the player’s.coverage.competitors:provider_idswhen both pairs are found.- Doubles games whose stored score already names the pairs are unchanged.
Finished games whose stored score names a side by an unknown code, or as the wrong team, name each side's team
A finished game in
GET /api/v1/games/{event_slug} and GET /api/v1/games now names each side by the team the game’s moneyline names, with its provider_id and logo. This applies when the stored live score names the side by a code no team carries, or carries another team’s identity.Before this change, such a side kept what the stored score said:- Air Force vs. Wyoming on October 23 served the codes
AFAandWYO, withprovider_idandlogoset tonullandcoverage.competitorsset tolabels. So did 132 other college football games, two NHL games and one CS2 game. - Two South Dakota State games served that side as San Diego State: its name, id
212, logo and record. - A CS2 side was named
GODS PLAN(id139465) beside Joga de terno’s logo.
- How a side is matched: by its code or name against the two teams of the game’s stored team pair, or as the one team left once the other side is named. When neither side names a team, the settled moneyline decides: in a final score by points, the side with the higher score is the team that won. A side is never given a team by its position.
- When it applies: only when the moneyline’s two outcomes name the pair’s two teams, one each. A game whose stored pair disagrees with its outcomes is unchanged.
name,provider_id,logo: the matched team’s, as on other finished games. In college footballnameis the school (Air Force), not the mascot.record:nullwhere the stored score carried another team’s record. Elsewhere it stays the record stored at the game.coverage.competitors:provider_idswhen both sides carry a team.- Tennis doubles games that showed one pair’s two partners as the two sides have their own entry.
Game markets carry each market's fees, liquidity rewards, order delay and tick with expand=trading_terms
GET /api/v1/games/{event_slug}/markets takes expand=trading_terms, which adds trading_terms to every row: the market’s fee schedule, liquidity reward settings and allocations, order delay and tick, as Polymarket’s market record states them, with the time it was read.Before this change, a client that quotes a game’s lines had to read each market from Polymarket’s Gamma or CLOB API to learn what it pays and how long a marketable order waits.status:observed,not_listed(Polymarket’s market list returned no record for the market) orunavailable(no read yet; every figure isnull, and a read a few seconds later usually answers).fees_enabledandfee_schedule:rate,exponent,taker_onlyandrebate_rate, the fraction of taker fees rebated to the resting maker.rewards_min_size(shares),rewards_max_spread(cents from the midpoint) andreward_allocations, each withrewards_amount,rewards_daily_rate,start_dateandend_date.seconds_delay: how many seconds a newly placed marketable order waits before it can match. Polymarket sets it on sports markets around live play.tick_sizeandobserved_at. Each market’s read is refreshed about once a minute.- It works on every plan and adds 1 to the request cost: 3 with
trading_terms, 4 withquotestoo. - The
list_game_marketsMCP tool takes"trading_terms"in itsexpandarray. The OpenAPI document and the SDK types describe the block.
trading_terms appears only when you send expand=trading_terms, and every key in it is always present; null means unknown. Without the expand, the response is unchanged.What to change: Nothing. To read a game’s fees, rewards and order delay in one request, send expand=trading_terms.Finished games filtered by a small league reach the end in a few pages
GET /api/v1/games with status=ended, cancelled or postponed and a league filter now reads only the games that league can hold, so a small league inside a large sport no longer spends each page on the sport’s other games.Before this change, the league filter ran after a page’s read budget, which counted every game of the league’s sport. league=ukr1 read through all of Soccer, and most of its pages came back empty with has_more: true. Paging kickoffs from October 21 to November 4 with limit=100, on a copy of production data, before and after:league=ukr1: 21 pages (15 empty) before, 8 pages (4 empty) after, the same 13 games.league=enl: 16 pages (7 empty) before, 5 pages (none empty) after, the same 34 games.league=taipei: 24 pages (19 empty) before, 5 pages (2 empty) after, the same 39 games.league=cfb,league=eplandsport=Footballreturn the same games in the same pages or fewer.
has_more is true.What to change: Nothing. Keep following next_cursor until has_more is false.Game markets carry each outcome's price, best bid and best ask with expand=quotes
GET /api/v1/games/{event_slug}/markets takes expand=quotes, which adds a quote to every outcome on the page: the price Polymarket shows, and the best bid and best ask, each with the time it was observed.Before this change, a game’s spreads, totals and props carried no price, so a client had to call Polymarket’s CLOB, or read Market snapshot once per market.status:observed(we hold the price, the book or both; anullfigure beside it is one we do not hold),no_orderbook(Polymarket confirmed the outcome has no order book and we hold no price) orunavailable(we hold nothing for it yet; every figure isnull, and a read a few seconds later usually answers, because the request starts covering the page’s open markets).price, from 0 to 1, withprice_basis:midpointwhen the best bid and ask are at most $0.10 apart, otherwiselast_trade.price_observed_atis when the quote and trades behind it were observed. These are the figures Market snapshot serves ascurrent_price, at full precision.best_bidandbest_ask, from 0 to 1, withbook_observed_at, when Polymarket’s book update behind them was observed.- It works on every plan and adds 1 to the request cost: 3 with
quotes, 6 withsharp_moneytoo. - The
list_game_marketsMCP tool takes"quotes"in itsexpandarray. The OpenAPI document and the SDK types describe the block.
quote appears only when you send expand=quotes, and every key in it is always present; null means unknown. Without the expand, the response is unchanged.What to change: Nothing. To price a game’s lines in one request, send expand=quotes, and read again a few seconds later for an outcome that reads unavailable.Finished tennis games keep their tournament as league in /api/v1/games
GET /api/v1/games and GET /api/v1/games/{event_slug} now give a finished game the league the live board gave it: the provider event’s own league, which in tennis is the tournament (taipei, pan pacific open). Esports and cricket games outside a league scope (cs2, lol and the other scope leagues keep theirs) read their event’s league the same way.Before this change, a finished game read from its stored rows took the tour instead (atp, wta, itf or challenger), so a game changed league when it left the board, and league=taipei&status=ended found none of a tournament’s finished games. A few ended tennis games still on the board also read challenger.Breaking for clients that read or filter finished tennis games by a tour code: league=wta&status=ended no longer matches a game whose event names its tournament.What to change: Filter finished games by the tournament, as you do for upcoming and live ones, and use sport=Tennis to read every tour.Games, the game detail and the market snapshot carry each market's settlement
GET /api/v1/games/{event_slug} and GET /api/v1/market/{condition_id}/snapshot now carry settlement, the block List game markets returns, and GET /api/v1/games carries it with expand=settlement.Before this change, only the game markets route said how Polymarket’s oracle settled a market, so a client reading games or a snapshot had to make a second call to learn which side paid or whether a market settled 50-50.GET /api/v1/games/{event_slug}: every winner market carriessettlement, also for a finished game read after it leaves the live board. The request cost stays 2.GET /api/v1/games:expand=settlementadds it to every winner market on the page, on every plan, and adds 2 to the request cost. It combines withexpand=sharp_money. Without it, markets carry nosettlementkey.GET /api/v1/market/{condition_id}/snapshotand its Markdown twin: a top-levelsettlement, read from the market’s event, or from its game for a market Polymarket files under a child event.market.market_resultstaysnull.- None of these reads waits for Polymarket. A game no read has asked about lately reads
statusunavailable, and its read starts at once, so a read a second or two later carries the block. - The
list_games,get_gameandget_market_snapshotMCP tools, the OpenAPI document, the SDK types and the sandbox describe the field. Thelist_gamestool’sexpandnow also takes an array,["sharp_money", "settlement"], for both blocks in one call; one value works as before.
settlement is a new field, expand=settlement is a new value, and a single expand value is still accepted.What to change: Nothing. To settle a position from a game or a snapshot read, read settlement.result and settlement.payouts, and treat unavailable as “ask again shortly”, never as unsettled.Upcoming college football games name each side by its school, not its mascot
An upcoming college football game in
GET /api/v1/games and GET /api/v1/games/{event_slug}, and in the MCP list_games and get_game tools, now names each side by its school.Before this change, such a game named its sides by mascot until kickoff, and by school once it was live or finished. Ball State vs. UMass on November 4 read Cardinals and Minutemen in competitors[].name and outcome_yes, while the same response’s title (Ball State vs. UMass), its prices.provider labels and Polymarket’s moneyline outcomes read Ball State and UMass. Several schools share a mascot, so a mascot alone can name the wrong team: Eagles is Eastern Michigan, Boston College and Georgia Southern.competitors[].name,markets[].outcome_yesandmarkets[].outcome_no: the school (Ball State), as the moneyline outcomes name it. A team keeps one name before kickoff, in play and after the game ends.markets[].prices.provider.binding_provenance:exact_labelsfor a game Polymarket lists without team ids, where it readeliminationornull. Prices are unchanged, except that a pair refused asinvalidwithfinal_identity_mismatchbecause its names disagreed is nowpairedat Polymarket’s prices (Morehead State vs. Marist on November 7).provider_id,logo,recordandsideare unchanged.- Every other league is unchanged, college basketball included: its names already carry the school (
Southern Indiana Screaming Eagles).
provider_id, or by the school name now served.Finished games with no stored score carry each side's team id and logo
A finished game in
GET /api/v1/games/{event_slug} and GET /api/v1/games that has no stored live score now carries provider_id and logo for each side its moneyline names, when the game’s stored team pair includes that team.Before this change, such a game named its competitors from the moneyline’s two outcomes only, with provider_id and logo set to null and coverage.competitors set to labels. Western Kentucky vs. Sam Houston on October 14 is one example. The change reaches every sport: in a read of ten leagues on November 4, 468 of 1,586 finished games moved from labels to provider_ids, most of them table tennis (306) and tennis singles (102).name: unchanged. It stays the outcome’s name, which in college football is the school (Western Kentucky), not the mascot.provider_idandlogo: set when the outcome names one team of the game’s team pair, by its exact name, alias or code, or by its words. A side is never given a team by its position. For a tennis or table tennis player,logois the player’s country flag, as on games with a stored score.coverage.competitors:provider_idswhen both sides carry a team, elselabels.- A game whose legs store no team pair, such as Columbia vs. Penn on October 16, is unchanged.
null are now set.What to change: Nothing. A client that matches finished games to teams by name can use provider_id for these games too.Finished games filtered by sport or league reach the end in far fewer pages
GET /api/v1/games with status=ended, cancelled or postponed and a sport or league filter now spends each page’s read on the filtered sport’s games, so a page reaches several days of kickoffs instead of under one.Before this change, a page’s read budget counted every sport’s games, and the filter dropped the others afterwards. A filtered walk of two weeks came back as dozens of pages, most of them empty with has_more: true. Paging kickoffs from October 21 to November 4 with limit=100, before and after:league=cfb: 51 pages (37 empty) before, 4 pages (none empty) after, the same 225 games.league=nba: 51 pages (29 empty) before, 5 pages (none empty) after, the same 104 games.sport=Football: 12 pages before, 5 after, the same 259 games.league=ukr1: 51 pages (42 empty) before, 18 pages (12 empty) after, the same 13 games. A small league inside a large sport still takes several short pages.
has_more is true.What to change: Nothing. Keep following next_cursor until has_more is false. A league with no game on the live board reads every sport, as before: pass sport beside it (sport=Esports&league=iem) to narrow the read.Finished games in /api/v1/games name each side and serve its current crest
A finished game in
GET /api/v1/games/{event_slug} and GET /api/v1/games now names its competitors through the same team binding a live game uses, so name, provider_id and logo match the live board.Before this change, a game the board had dropped served its sides exactly as the last live score stored them. Penn carried Polymarket’s generic ESPN college football image, and Duke, Virginia and Yale an older crest file.logo: generic provider artwork is dropped, and a team with a current college or supplemental crest serves it.provider_idandname: a side whose score-feed code names its team, or the one side left once the other is named, carries that team’s id and name.coverage.competitorscan change fromlabelstoprovider_ids.scoreandrecordare unchanged: they stay the final score and the record stored at the game.- A game whose two sides both carry codes that name no team, such as
AFAandWYO, still serves those codes with no logo.
logo or provider_id can read the game again for the corrected values.Game markets carry each market's settlement: oracle status, payouts and 50-50
Every row of
GET /api/v1/games/{event_slug}/markets now carries settlement: how Polymarket’s oracle settled, or is settling, the market, from Polymarket’s /v2/resolutions.Before this change, a row said only active or closed, so a client had to call Polymarket to learn which side paid, whether a market settled 50-50, or whether a proposal was disputed.status:observed(Polymarket’s resolution row is below),not_posed(no oracle request yet;settledisfalse) orunavailable(no read in hand; every other field isnull, and a read a moment later may answer).oracle_status: Polymarket’s lifecycle state as Polymarket writes it, such asproposed,disputedorresolved.settledistruewhen it isresolved.payouts: what one share of each outcome pays, in micro-USDC (1000000is $1), in outcome index order. It is set only on a resolved row that carries payouts.result:outcome(one side paid in full;winning_outcome_indexnames it) orsplit(Polymarket’s 50-50), read offpayoutsonly.was_disputed,resolved_at, and for a pending marketexpected_settlement_timewithsettlement_time_basis: Polymarket’s estimate of the earliest settlement, not a deadline.proposed_answer:outcome_0,outcome_1,splitortoo_early, the newest proposal of a pending round. A proposal is not a result.observed_at: when Polymarket answered. A settled read is refreshed every 10 minutes, any other every minute.- The
list_game_marketsMCP tool, the OpenAPI document, the SDK types and the sandbox describe the block. The request cost stays 2.
settlement is a new field, and every key in it is always present; null means unknown.What to change: Nothing. To settle a position without calling Polymarket, read settlement.result and settlement.payouts, and treat unavailable as “ask again shortly”, never as unsettled.SDK 0.39.0 sends the stream's min_grade_at_trade filter
@0xinsider/sdk 0.39.0 adds min_grade_at_trade to StreamFilters, so streamFeed, streamFeedResilient and consumeStreamCheckpointed can send the GET /api/v1/stream filter of the same name.Before this release, the SDK’s only grade filter on the stream was min_grade, which reads the wallet’s grade when the trade was published, hours after the fill for a backfilled trade. A client that caught up on GET /api/v1/large-trades/history with min_grade_at_trade could not stream on the same basis through the SDK.min_grade_at_tradekeeps aLargeTradeInsertedV2frame only when itsgrade_at_tradeis at or above the value and itsgrade_at_trade_statusisgraded. With it set, every other frame type is excluded.- Sending it beside
min_gradeis refused with400bad_requestandparammin_grade_at_trade. The resilient consumers do not retry it. - The same release types
min_grade_at_tradeonlistLargeTrades,listLargeTradeHistory,getEventReplaySinceand webhooktrade_filters, andgrade_at_tradeandgrade_at_trade_statusonLargeTradeInsertedV2Data. - It also types
scores_freshnessandscores_age_secondson games.
min_grade_at_trade instead of min_grade on both.Games scores_freshness reads stale for esports, college basketball and NHL games
GET /api/v1/games and GET /api/v1/games/{event_slug} now judge freshness.scores_freshness for esports, college basketball and NHL games, and read not_applicable in a break between periods. The list_games and get_game MCP tools carry the same values.Before this change, only a running soccer half could read fresh or stale. Every other live game read unknown, including an NHL game in an intermission.Each bound is about twice the longest gap between frames that we measured on November 4, 2026:- Esports (
leaguecs2orlol):staleafter 120 seconds with no frame while the series is in progress. The provider resends each running series about every 20 seconds, also while the map score does not move. - Men’s and women’s college basketball (
cbb,cwbb) and NHL hockey (nhl):staleafter 600 seconds with no frame while a period’s clock is running. These feeds send no frame while the clock is stopped for a timeout or review. - Breaks: a period of
HTorEnd ...(for exampleEnd P2orEnd Q2) readsnot_applicable. In women’s college basketball,End OTis the end of the third quarter and the provider sends no frame for the fourth, so it readsunknown. - Still
unknown: tennis, college football, the NBA, the NFL, other esports titles, and every other league with no measured bound.
scores_age_seconds is the time since the game’s last frame. For esports that is the last resend, not the last change in the score.Backward compatible. No field is added or removed. Some live games that read unknown now read fresh, stale or not_applicable.What to change: Nothing, if you already show a live score as delayed when scores_freshness is stale.@0xinsider/mcp 3.13.0 is published; local large-trade tools filter on the grade at the fill
@0xinsider/mcp 3.13.0 is on npm and in the MCP Registry. It brings the November 4 changes listed below to the local MCP server and the CLI.get_large_trades,get_large_trades_history,get_event_replay_sinceand the deprecated aliasesget_whale_tradesandget_whale_trades_historytakemin_grade_at_trade, the grade the trader held when the trade filled. Sending it withmin_gradereturnsbad_request.0xinsider api listnamesmin_grade_at_tradeforlistLargeTrades,listLargeTradeHistoryandgetEventReplaySince. The entry “Large trades, the stream and webhooks can filter on the grade a trade filled under” said it would name it forgetStreamtoo, butapi listandapi callleave out the stream, which you read fromGET /api/v1/streamdirectly.- The
get_pick_of_the_daydescription says apick_idcall returns the pick once, inpicks[0], as the API already did. - The bundled SDK types describe every sport leaderboard field.
@0xinsider/mcp@3.13.0.Backward compatible. Every change adds a parameter, a section or a description; no tool, default or field changed.What to change: Run npm install --global @0xinsider/mcp@3.13.0, or change a client’s @0xinsider/mcp@3.12.0 argument to @0xinsider/mcp@3.13.0. 0xinsider --version prints 3.13.0 once the update is in place.Games add scores_freshness and scores_age_seconds, so a frozen live score no longer reads fresh
GET /api/v1/games and GET /api/v1/games/{event_slug} now send freshness.scores_freshness on every game, plus freshness.scores_age_seconds when a Sports WebSocket frame dates the score. scores_age_seconds is the time since that game’s last frame, which is how long its score, period and clock have gone unchanged. The list_games and get_game MCP tools and the TypeScript types carry both.Before this change, source_freshness was the only freshness value. It dates the board as a whole, so it read fresh while one live game’s clock and score were 14 minutes old.scores_freshness is judged on the game clock:stale: a soccer half’s clock is running and no new frame has arrived for more than 180 seconds. The provider sends a frame each match minute.fresh: a running soccer half’s clock had a frame within that bound.not_applicable: the game is not in play (scheduled, final, postponed or cancelled), or it is at halftime.unknown: no frame dates the score, the game is in stoppage time, or the game’s sport has no measured bound. Basketball and hockey clocks stop for timeouts and reviews, so those sports readunknown.
scores_freshness is stale. Treat unknown as unverified, never as current.Scheduled games and live soccer games now carry sports_market_type and side on their markets
GET /api/v1/games and GET /api/v1/games/{event_slug} now send sports_market_type (the provider’s own value, for example moneyline) and side on the markets of a game that has not started, and on soccer markets while the game is live.Before this change, those markets left out both fields. A client that picked a game’s moneyline by sports_market_type found no market on any scheduled game. Measured on November 4, 2026: 0 of 100 scheduled esports markets carried the field.side is still left out when the provider does not identify the competitors (no provider ids, as on many ITF tennis matches). The live markets work the same way.Backward compatible. Both fields were already documented and are now sent where they were missing.What to change: Nothing. If you fall back to the only listed market when sports_market_type is missing, you can now select by sports_market_type === "moneyline" instead.Large-trade history and the event replay can filter on the grade a trade filled under
GET /api/v1/large-trades/history and GET /api/v1/events/feed/since accept min_grade_at_trade. It keeps a trade only when the grade its trader held when the trade filled is at or above the value, the rule GET /api/v1/large-trades, GET /api/v1/stream and webhook trade_filters already apply.Before this change, both routes offered only min_grade, which reads the wallet’s grade when the page is read. A client that caught up through one of them and then streamed with min_grade_at_trade could get a different set of trades.- Only a trade whose grade at the fill is
gradedmatches. A trade before September 19, 2026, 23:00 UTC isunknownand never matches. - On the history route it works with both sorts and beside
condition_id,event_slug,trader,fromandto. - On the event replay it is bound to the cursor like the other filters: a cursor minted under
min_gradeand presented withmin_grade_at_trade, or the reverse, returns400witherror.reasoncursor_expired.meta.replay.filtersechoes it. - Sending
min_gradeandmin_grade_at_tradetogether returns400withparammin_grade_at_trade. - The remote MCP tools
get_large_trades_history, its deprecated aliasget_whale_trades_history, andget_event_replay_sincetakemin_grade_at_tradenow. The next@0xinsider/mcprelease adds it to the local MCP tools, and0xinsider api listwill name it forlistLargeTradeHistoryandgetEventReplaySince. - The next SDK release adds
min_grade_at_tradetoStreamFilters, sent as themin_grade_at_tradequery parameter ofGET /api/v1/stream. min_gradekeeps its meaning on every surface.
min_grade_at_trade instead of min_grade on the history or replay read and on the stream.@0xinsider/mcp 3.12.0 is published; Pick of the Day tools default to the summary view
@0xinsider/mcp 3.12.0 is on npm and in the MCP Registry. It brings the November 3 changes listed below to the local MCP server and the CLI. Before this release, the local server ran 3.11.0, whose Pick of the Day tools sent no view and returned the whole record: 198,807 bytes for one day’s 14 picks.get_pick_of_the_day,get_pick_of_the_day_archiveandget_pick_of_the_day_statssendview=summaryunless you name a view. They takepick_id, the archive’slimitandcursor, and the statssections.get_leaderboarddescribes the boardsummary(ranked_total,by_grade,active_30d,as_of), sent on a page with no category or strategy.get_edge_hunterreadscategory: "sports", in any casing, askind: "sports"in every view.explore_marketsandget_leaderboardtakesportsfor every sport but Esports, and the market and trade tools that reject the word say to omitcategoryinstead.get_tradertakesexpand: ["breakdowns"]and describesprice_edge, the edge over the price paid that the profile badge shows.- Each
get_game_holdersitem’s data carriesstale. - The package’s MCP Registry description reads “Polymarket sports and esports data: wallet grades on settled P&L, large trades, markets.”
@0xinsider/mcp@3.12.0. The November 4 pick_id change to Pick of the Day needs no package update: the local get_pick_of_the_day passes the API body through, so a pick_id call returns the pick once, in picks[0].Breaking for local MCP clients that read Pick of the Day fields the summary leaves out, such as display_holders or entry_authorization. The other changes add parameters, fields and descriptions.What to change: Run npm install --global @0xinsider/mcp@3.12.0, or change a client’s @0xinsider/mcp@3.11.0 argument to @0xinsider/mcp@3.12.0. For the full Pick of the Day body, send view: "full", or call get_pick_of_the_day with pick_id for one pick in full. 0xinsider --version prints 3.12.0 once the update is in place.Sandbox leaderboard lists S, A and B only, with a ranked edge for each grade
In the sandbox,
GET /api/v1/leaderboard now returns 5 rows graded S, A and B, the grades the live leaderboard lists. Each of the 3 grades has a price_edge with status: "ranked" and no hold, the edges sort=edge ranks.Before this change, the sandbox leaderboard returned 7 rows graded S to D. Every price_edge had status: "ranked", hold: "record_incomplete" and edge: 1, so a client that keeps only ranked edges with no hold found none.- One
Aedge keepshold: "record_incomplete", and oneBedge hasstatus: "sample_mismatch". price_edge.edgeishit_rateminusavg_price, as the field is defined.holdis omitted when nothing holds the edge, as in the live API.- In
POST /api/v1/traders/batch, a sandbox wallet’sprice_edgehas the same figures, withshrunk_edgeandfield_averageonly when the edge ranks. - The sandbox leaderboard’s
totalis 5, so alimit=3walk ends on its second page.
C or D row, now gets 5 rows graded S, A and B.OpenAPI describes every sport leaderboard field: grade is all-time, P&L is in-sport
The OpenAPI schemas for the sport leaderboard and leaderboard leagues now describe every field, including each row field and each
price_edge field.Before this change, both schemas listed field types only. A reader could not tell from the schema that a row’s grade is the wallet’s all-time grade while its other figures are in the sport or league. On the esports board sorted by P&L on November 4, the top wallet had $3,692,604 in esports P&L and an F grade.grade: the all-time grade, led by realized profit across all of the wallet’s sports and esports markets, not this sport’s.pnl,cost,roi,wins,losses,win_rate,price_edge,edge_skill: the wallet’s record in this sport or league.roiandwin_rateare fractions:0.12is 12%.volume: the wallet’s volume across all sports and esports on a sport board, asvolume_scopesays, andnullon every league board row.total_traders: wallets with at leastmin_resolvedsettled markets here and a trade in the last 180 days.
Large trades, the stream and webhooks can filter on the grade a trade filled under
GET /api/v1/large-trades, GET /api/v1/stream and webhook trade_filters on POST /api/v1/webhooks accept min_grade_at_trade. It keeps a trade only when the grade its trader held when the trade filled is at or above the value, by the same rule on all three.Before this change, each min_grade read a different grade: the list read the wallet’s grade now, and the stream and webhooks read its grade when the trade was published. A client that caught up on the list and then streamed got two answers: over 16 hours on November 3 the list added 2 trades and dropped 3 against the stream. Publication can also come hours after the fill: in the 7 days to November 3, 14 of 3,892 trades were published under a different grade than they filled under.- The
LargeTradeInsertedV2stream frame and thelarge_trade_inserted_v2webhookdataaddgrade_at_tradeandgrade_at_trade_status, the same facts astrader.grade_at_tradeandtrader.grade_at_trade_statuson the list.gradeis unchanged. - Only a trade whose
grade_at_trade_statusisgradedmatches. A trade before September 19, 2026, 23:00 UTC isunknownand never matches, and neither does an event published before this change. Such an event, redelivered, carries neither field, so read both as optional. - On the list,
min_grade_at_tradeworks withsince,sort=market_volume_share,condition_idandevent_slug. - On the stream,
min_grade_at_tradepasses onlyLargeTradeInsertedV2frames.min_gradealso passeswallet_grade_changedframes. - Sending
min_gradeandmin_grade_at_tradetogether returns400withparammin_grade_at_trade(trade_filters.min_grade_at_tradeon webhooks). - The remote MCP tool
get_large_tradesand its deprecated aliasget_whale_tradestakemin_grade_at_tradenow. The next@0xinsider/mcprelease adds it to the local MCP tools, and0xinsider api listwill name it forlistLargeTradesandgetStream. min_gradekeeps its meaning on every surface.
min_grade_at_trade instead of min_grade on each. A stream client that also reads wallet_grade_changed frames gets them only on a connection without min_grade_at_trade.Games reports a cancelled or postponed upcoming game as cancelled or postponed
GET /api/v1/games and GET /api/v1/games/{event_slug} now report status.state cancelled or postponed when Polymarket marks an upcoming game that way. window=now leaves those games out, as it already did for every cancelled and postponed game.Before this change, a game that Polymarket marked only on its event, with no live-score update, read scheduled. On November 3, 2026, Paine at Jacksonville (cbb-pain-jax-2026-11-02) was cancelled and still read scheduled 23 hours after its listed tip-off.An upcoming game whose provider period this API does not recognize now reads unknown, not scheduled. No game read that way on November 3, 2026.Backward compatible. Both values were already in the status.state enum, and no field is added or removed.What to change: Nothing. If you list upcoming games and treat every game that is not live as still to be played, check for cancelled and postponed too.Pick of the Day with pick_id returns the pick once, in picks[0]
GET /api/v1/pick-of-the-day with pick_id now returns that pick once, as picks[0], beside state, pick_date and pick_count. The remote MCP tool get_pick_of_the_day with pick_id returns the same body.Before this change, the pick_id body also copied the pick’s fields to the top level, the way a whole-day read repeats its first pick. That doubled the body. On November 2, 2026, the largest pick was 42,388 characters, and 7 of the 14 picks were over 25,000. Without the copy the largest is about 21,150.Breaking only for clients that read pick fields, such as entry_authorization or display_holders, from the top level of a pick_id body. pick_id was added on November 3, 2026. A request without pick_id returns the same body and ETag as before.What to change: Read the pick from picks[0].