> ## Documentation Index
> Fetch the complete documentation index at: https://docs.0xinsider.com/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> The Markdown of an API reference page leaves out the OpenAPI schema.
> Every object an endpoint returns or a webhook carries, with each field's type, presence and meaning, is on https://docs.0xinsider.com/api-reference/objects.md.
> The full OpenAPI 3.1 spec names each operation's and each webhook's exact parameters, request body and response schema: https://docs.0xinsider.com/api-reference/openapi.json.

# API changelog: November 2, 2026

> 39 API, SDK, CLI, MCP, OAuth, and feed changes from November 2, 2026, newest first, each with its effect on clients. Newer changes are on the API changelog.

These are the API changelog entries from November 2, 2026, newest first. The newest changes are on the [API changelog](https://docs.0xinsider.com/changelog.md).

**November 2, 2026**

data\_quality reads stale when a clock is older than its writer's refresh budget

Every `data_quality` block now judges each dated group against its writer's refresh budget: `fresh` inside it, the new `stale` past it, with the budget in seconds as the new `max_age_s`. This covers [`GET /api/v1/positions`](https://docs.0xinsider.com/api-reference/endpoint/get-positions), [`GET /api/v1/trader/{address}`](https://docs.0xinsider.com/api-reference/endpoint/get-trader), [`POST /api/v1/traders/batch`](https://docs.0xinsider.com/api-reference/endpoint/batch-get-traders), [`GET /api/v1/trader/{address}/context`](https://docs.0xinsider.com/api-reference/endpoint/get-trader-context), [`GET /api/v1/large-trades`](https://docs.0xinsider.com/api-reference/endpoint/get-large-trades) and [`GET /api/v1/large-trades/history`](https://docs.0xinsider.com/api-reference/endpoint/get-large-trades-history).

Before this change, a group read `fresh` whenever it had a timestamp, however old. One wallet's positions page, reconciled 5 days earlier, said `fresh` while each of its rows said `stale`.

* `max_age_s` is 1800 for the `positions` group on positions, the age at which each row's own `freshness` reads `stale`; 604800 (7 days) for `sync`, `ranking`, `volume` and `positions` on a trader and for `trader` and `ranking` on positions and large trades; and 22620 for `leaderboard_rank`.
* A group whose timestamp is written once, moves only when its value changes, or is written when a reader asks carries no `max_age_s` and is never `stale`: `sports_record`, `market`, `trade` and the large-trade `volume`.
* The top-level `status` is `stale` when every group is `fresh` or `stale` and at least one is `stale`. `unavailable` and `partial` keep their rules.
* A cached trader response is judged again when it is served. A positions snapshot page (`consistency=snapshot`) serves the block stored with its rows.
* The `max_age_s` ceiling on `GET /api/v1/trader/{address}` and the `get_trader` MCP tool accepts `fresh` or `stale`, so every request answers as it did before. `error.freshness.data_quality_status` can now be `stale`.
* In the next `@0xinsider/sdk` release, the types gain `"stale"` and `max_age_s`, and `assessDataQuality` passes a `stale` group inside your `maxAgeMs`, as it passed that group before. Python `0xinsider` 0.8.1 (`assess_data_quality`) and Go `github.com/0xinsider/0xinsider-go` v0.5.1 (`AssessDataQuality`) pass a `stale` group inside your `max_age` / `MaxAge` the same way; earlier releases fail `stale` as an unrecognized status, which errs toward refusing a body.

**Backward compatible** under the published rule to treat a status you do not recognize as `unknown`. A client that accepts a body only when `status` is `fresh` now refuses one whose writer has missed a refresh.

**What to change:** Treat `stale` as dated but overdue, and compare `as_of` with your own limit, as you did for `fresh`. Read `max_age_s` for each writer's budget. If you only send `max_age_s` to the trader route, nothing.

**November 2, 2026**

A trader's pnl.unrealized counts open positions only, without the profit of partial sells

[`GET /api/v1/trader/{address}`](https://docs.0xinsider.com/api-reference/endpoint/get-trader) `pnl.unrealized` is now the unrealized P\&L of the wallet's open sports and esports positions and nothing else: Polymarket's `cashPnl`, current value minus cost, summed over the positions still held. It is the same figure as `position_summary.unrealized_mtm` on [`GET /api/v1/trader/{address}/context`](https://docs.0xinsider.com/api-reference/endpoint/get-trader-context), and `trader.pnl.unrealized` in that body now equals it.

Before this change, `pnl.unrealized` also added the realized P\&L of partial sells on markets the wallet still held. `pnl.in_scope.realized_pnl` already counts those sells, so adding the two fields counted them twice, and one context body carried two different unrealized figures. On one wallet whose open positions were down about $2,500 on Polymarket, `pnl.unrealized` read $3,278.76 while `unrealized_mtm` read -\$2,700.34.

* The value changes only for a wallet that sold part of a position it still holds. Other wallets read the same figure as before.
* The `get_trader` and `get_trader_context` MCP tools, the CLI's `traders get` and `traders context`, and the SDK's `getTrader` return the corrected figure with no update.
* The OpenAPI descriptions of `pnl.unrealized` and `position_summary.unrealized_mtm` state the definition.

**Backward compatible.** The field, its type and the response envelope are unchanged. Its value is corrected.

**What to change:** If you subtracted partial-sell profit from `pnl.unrealized`, or reconciled it against `unrealized_mtm`, remove that step. `pnl.in_scope.realized_pnl` plus `pnl.unrealized` now counts each sale once.

**November 2, 2026**

Top holders send the last sample, marked source\_stale, while a new one builds

[`GET /api/v1/market/{condition_id}/top-holders`](https://docs.0xinsider.com/api-reference/endpoint/get-market-top-holders) now answers a request that arrives after the sample's 30 seconds are up with the market's last sample and a new field, `source_stale: true`, while 0xinsider builds a new one. It does so only while that sample's holder board is at most 300 seconds old.

Before this change, such a request waited for the whole build, which took 0.4 to 2.5 seconds, mostly the read of Polymarket's holder board. `source_stale` is `false` on every other response, including every response for a resolved market.

* `positions_as_of` on a stale sample is at most 300 seconds old, where a fresh sample's is usually up to about 150.
* A request a few seconds later gets the new sample, with `source_stale: false`.
* A market with no recent sample still waits for the build.
* The MCP tool `get_market_top_holders` and the CLI's `market top-holders` return the field too, and the SDK type `MarketTopHolders` gains `source_stale: boolean`.

**Backward compatible.** The field is new and every other field keeps its meaning.

**What to change:** Nothing. If you need positions no more than about 150 seconds old, check `source_stale` and request again a few seconds later when it is `true`.

**November 2, 2026**

Top holders mark a wallet 0xinsider has no record of as untracked, not under the floor

[`GET /api/v1/market/{condition_id}/top-holders`](https://docs.0xinsider.com/api-reference/endpoint/get-market-top-holders) now sends `category_win_rate_status: "untracked"` for a holder 0xinsider has no record of. Such a holder also has `grade`, `in_scope_realized_pnl` and `in_scope_volume` set to `null`. `not_enough_data` now means only that the wallet is on file and has fewer than 5 decided markets in the category.

Before this change, the route sent `not_enough_data` for both cases, so a wallet nobody had measured read as a small sample. On one live tennis market, 37 of the 44 holders marked `not_enough_data` had no record. When the wallet record read fails, an unmeasured holder now reads `unavailable` instead of `not_enough_data`.

The OpenAPI enum on `MarketHolder` and `PickHolder` lists the new value too, because they share the type. [`GET /api/v1/market/{condition_id}/holders`](https://docs.0xinsider.com/api-reference/endpoint/get-market-holders) and Pick of the Day never send it: every wallet they list is graded and on file.

**Backward compatible** for clients that treat an unknown status as "no rate". The SDK type `category_win_rate_status` gains `"untracked"`, so an exhaustive TypeScript `switch` on it needs a new case.

**What to change:** Read `untracked` as "no record, nothing measured", not as a small sample. Where you branch on the status, add the case.

**November 2, 2026**

Esports score frames on the stream carry each finished map's winner and round score

[`GET /api/v1/stream`](https://docs.0xinsider.com/api-reference/endpoint/get-stream) `LiveScoreChanged` frames for an esports series now carry the same score as the market page: each finished map's winner in `live_score.scores[].map_results`, each map's round score in `live_score.scores[].maps`, and a game that Polymarket's series state finished before the live feed counted it.

Before this change these frames carried only the live feed's series totals and current map, so a stream client saw `map_results` and `maps` empty during play.

* 0xinsider composes each live esports series every 5 seconds or more, and sends a new frame when the composed score shows something the last frame did not. Such a frame can have the same `source_revision` as the frame before it.
* Frames continue for up to 2 minutes after the series' ended frame, so the final map's winner and round score arrive after `ended: true`.
* Other sports are unchanged.

**Backward compatible.** The fields and their types are unchanged; they are now filled during play.

**What to change:** If you order score frames by `source_revision` and drop a frame whose revision is not newer, accept an equal revision for an esports series, or you keep the earlier frame without the map history. Keep applying frames for a series after it ends.

**November 2, 2026**

@0xinsider/mcp 3.10.0 and @0xinsider/sdk 0.35.0 are published with the past-date Pick of the Day read

`@0xinsider/mcp` 3.10.0 and `@0xinsider/sdk` 0.35.0 are on npm.

* The CLI adds `0xinsider pick date <YYYY-MM-DD>`, which reads a past date's picks.
* The local MCP server's `get_pick_of_the_day` tool takes the optional `date` argument the remote tool already takes. The tool count stays at 69.
* The SDK adds `getPickOfTheDayForDate(date)` and `getMarketTopHolders(conditionId, { limit })`.
* SDK 0.35.0 is the first SDK release since 0.32.0. It also adds the methods the entries below say arrive in a later release: `getGameSharpMoney`, `getGameHolders`, `listGameMarkets`, `listGameTrades`, `getMarketWalletsInOut`, `getSportLeaderboard`, `listLeaderboardLeagues`, `getCategoryLeaderboard`, `listCategoryLeaders`, `getResolutionReport` and `getPickOfTheDayStats`. `listLeaderboard` accepts `sort`, `dir` and `activity`.

The [CLI](https://docs.0xinsider.com/integrations/cli.md), [MCP](https://docs.0xinsider.com/integrations/mcp.md) and [introduction](https://docs.0xinsider.com/index.md) pages now install `@0xinsider/mcp@3.10.0`.

**Backward compatible.** Both releases add commands, arguments and methods. Nothing is removed or renamed.

**What to change:** Run `npm install --global @0xinsider/mcp@3.10.0`, or change a client's `@0xinsider/mcp@3.9.0` argument to `@0xinsider/mcp@3.10.0`. Run `npm install @0xinsider/sdk@0.35.0` to use the new SDK methods. `0xinsider --version` prints `3.10.0` once the update is in place.

**November 2, 2026**

GET /api/v1/pick-of-the-day takes a date to read a past day's picks

[`GET /api/v1/pick-of-the-day`](https://docs.0xinsider.com/api-reference/endpoint/get-pick-of-the-day) now takes an optional `date` query parameter (`YYYY-MM-DD`, on the `America/New_York` calendar). With a past date, it returns that date's picks as the website's page for that date shows them, under the same plan access. The `get_pick_of_the_day` MCP tool takes the same `date` argument.

Before this change, the endpoint served only today's picks. A past date's picks were readable only on the website, and the internal dated route refused an API key with `401`.

* Without `date`, or with today's date, the response is unchanged.
* A past date returns no `scheduled_picks`.
* A past date with no published pick returns `404`, `error.code` `not_found`, `error.param` `date`, with no `Retry-After`. Do not retry it.
* A date after today, or a malformed one, returns `400`, `error.code` `bad_request`, `error.param` `date`.
* `@0xinsider/sdk` 0.35.0 adds `getPickOfTheDayForDate(date)`, and the `0xinsider` CLI in `@0xinsider/mcp` 3.10.0 adds `0xinsider pick date <YYYY-MM-DD>`. Both were published on November 2, 2026.

**Backward compatible.** The parameter is optional, and no field or type changes.

**What to change:** Nothing. To read a past date's picks, send `date`; the [archive](https://docs.0xinsider.com/api-reference/endpoint/get-pick-of-the-day-archive.md) still lists every published pick with its `pick_date`.

**November 2, 2026**

GET /api/v1/trader last\_active is the wallet's last trade, not its sync time

[`GET /api/v1/trader/{address}`](https://docs.0xinsider.com/api-reference/endpoint/get-trader) now sends `last_active` as the time the wallet last traded, as the field was documented. [`POST /api/v1/traders/batch`](https://docs.0xinsider.com/api-reference/endpoint/batch-get-traders), [`GET /api/v1/trader/{address}/context`](https://docs.0xinsider.com/api-reference/endpoint/get-trader-context), and the `get_trader` MCP tool send the same value.

Before this change, `last_active` carried the time 0xinsider last synced the wallet, the same value as `synced_at`. On November 2, 2026, a wallet that last traded on August 26 showed a `last_active` from that morning.

* `last_active` now matches `last_active` on [`GET /api/v1/leaderboard`](https://docs.0xinsider.com/api-reference/endpoint/get-leaderboard), which refreshes it hourly.
* A cached response can be up to 60 seconds behind a new trade.
* `last_active` is left out when 0xinsider has recorded no trade for the wallet, even if the wallet has synced. About 1 in 5 synced wallets had no recorded trade on November 2, 2026.
* `data_quality`'s `sync` group no longer covers `last_active`, and no other group does, because the value is itself the time of a trade. With `expand=trust`, `trust.last_active` names `trader_last_activity.last_activity_at` as its source, with freshness `unknown`.

**Backward compatible.** The field name and type are unchanged, and the value now matches the published description. A client that used `last_active` to see whether a wallet still trades now gets the right answer.

**What to change:** If you read `last_active` as the time 0xinsider last synced the wallet, read `synced_at` instead. Handle `last_active` being absent for a synced wallet.

**November 2, 2026**

Game sharp money dollar fields serve a zero as 0, never -0.0

[`GET /api/v1/games/{event_slug}/markets`](https://docs.0xinsider.com/api-reference/endpoint/list-game-markets) with `expand=sharp_money` and [`GET /api/v1/games/{event_slug}/sharp-money`](https://docs.0xinsider.com/api-reference/endpoint/get-game-sharp-money) now serve a zero dollar amount as `0.0`, never `-0.0`. The `list_game_markets` and `get_game_sharp_money` MCP tools change the same way.

Before this change, a side with no S, A or B holder could serve `"usd": -0.0` on a line's `sharp_money.outcomes`. On November 2, 2026, 2 of 14 computed lines on one NBA game did. These fields are sent unrounded, so the October 27 fix for rounded fields did not reach them.

* `data[].sharp_money.outcomes[].usd` on the game markets list.
* `data.outcomes[].usd`, `data.total_usd` and `data.unallocated_usd` on game sharp money.
* Only the sign of a zero changes. Every other value keeps its full precision.

**Backward compatible.** `-0.0` and `0.0` are equal numbers, and no field or type changes.

**What to change:** Nothing. A guard that hid `-$0.00` in your client is no longer needed.

**November 2, 2026**

@0xinsider/mcp 3.9.0 is published with every CLI and MCP addition since 3.7.0

`@0xinsider/mcp` 3.9.0 is on npm. It is the first release after 3.7.0 and carries every CLI command and MCP tool added since. Version 3.8.0 was never published, so the sport leaderboard entry below now names 3.9.0 for its commands.

The local MCP server goes from 55 tools in 3.7.0 to 69. The new tools are `get_account`, `get_usage`, `get_sport_leaderboard`, `get_leaderboard_leagues`, `get_category_leaderboard`, `list_category_leaders`, `get_market_top_holders`, `get_market_wallets_in_out`, `get_game_holders`, `get_game_sharp_money`, `get_game_trades`, `list_game_markets`, `get_resolution_report` and `get_pick_of_the_day_stats`. The CLI adds these commands:

* `leaderboard sport <sport>`, `leaderboard leagues`, `leaderboard category <slug>` and `leaderboard categories`.
* `market top-holders <condition_id>` and `market wallets-in-out <condition_id>`.
* `games sharp-money <event_slug>` and `games trades <event_slug>`.
* `pick stats` and `reports resolutions <date>`.

The [CLI](https://docs.0xinsider.com/integrations/cli.md), [MCP](https://docs.0xinsider.com/integrations/mcp.md) and [introduction](https://docs.0xinsider.com/index.md) pages now install `@0xinsider/mcp@3.9.0`.

**Backward compatible.** This adds commands and tools. No command or tool is removed or renamed.

**What to change:** Run `npm install --global @0xinsider/mcp@3.9.0`, or change a client's `@0xinsider/mcp@3.6.1` or `@0xinsider/mcp@3.7.0` argument to `@0xinsider/mcp@3.9.0`. Refresh a cached `tools/list`. `0xinsider --version` prints `3.9.0` once the update is in place.

**November 2, 2026**

GET /api/v1/leaderboard last\_active is the wallet's last trade, not its sync time

[`GET /api/v1/leaderboard`](https://docs.0xinsider.com/api-reference/endpoint/get-leaderboard) entries now send `last_active` as the time the wallet last traded, as the field was documented. The `get_leaderboard` MCP tool returns the same value.

Before this change, `last_active` carried the time 0xinsider last synced the wallet, which is usually within the past week whether or not the wallet traded. On November 2, 2026, all 100 wallets on an `activity=inactive` page showed a `last_active` from the past 7 days, though none had traded in 30 days.

* `last_active` now agrees with the `activity` filter: every wallet `activity=inactive` lists last traded more than 30 days ago.
* The value is refreshed hourly, so a trade in the last hour may not show yet.
* The field name, its type, and when it is left out are unchanged.
* [`GET /api/v1/trader/{address}`](https://docs.0xinsider.com/api-reference/endpoint/get-trader) still sends its `last_active` as the sync time, the same value as `synced_at`. A later change will correct it.

**Backward compatible.** The value now matches the published description. A client that used `last_active` to see whether a wallet still trades now gets the right answer.

**What to change:** Nothing. If you read `last_active` as the time 0xinsider last synced the wallet, read `synced_at` on [`GET /api/v1/trader/{address}`](https://docs.0xinsider.com/api-reference/endpoint/get-trader) instead.

**November 2, 2026**

Market top holders lists a market's largest holders of every grade

[`GET /api/v1/market/{condition_id}/top-holders`](https://docs.0xinsider.com/api-reference/endpoint/get-market-top-holders) is a new operation. It lists up to 100 holders per side, largest `shares` first, with C, D, F and ungraded wallets included. This is the Top holders table on the market's event page. Each row carries the wallet's `grade`, its position (`shares`, `current_value_usd`, `avg_entry_price`, position P\&L), and `totals` over the whole sample. On an open market a position can be up to about 150 seconds old: `positions_as_of` says when Polymarket's holder board was fetched, and `computed_at` when the sample was built.

[`GET /api/v1/market/{condition_id}/holders`](https://docs.0xinsider.com/api-reference/endpoint/get-market-holders) is unchanged. It still returns S, A and B holders only, from a complete scan with exact counts. Use it for the profitable-wallet roster, and use top holders for the biggest positions whatever their grade.

* The SDK adds `getMarketTopHolders(conditionId, { limit })`.
* The CLI adds `market top-holders <condition_id>`.
* MCP adds the `get_market_top_holders` tool.

**Backward compatible.** This adds an operation. Existing operations are unchanged.

**What to change:** Nothing. To list every large holder of a market, call `top-holders` with `limit=100`.

**November 2, 2026**

GET /api/v1/leaderboard entries carry price\_edge, and sort=edge orders by it

[`GET /api/v1/leaderboard`](https://docs.0xinsider.com/api-reference/endpoint/get-leaderboard) entries now carry `price_edge`, the wallet's edge over the price it paid, and `sort=edge` orders the list by it. The `get_leaderboard` MCP tool, the SDK's `listLeaderboard` method and the CLI accept `sort=edge` too.

Before this change, the entry had no edge field and `sort=edge` returned `400` with `error.param` `sort`.

* `price_edge` holds `markets`, `hit_rate`, `avg_price`, `edge` (`hit_rate` minus `avg_price`), `status`, and `hold` when one applies. It is left out when the wallet has no settled sports or esports market of \$20 or more at a known entry price.
* `status` is `ranked`, `too_few_markets` or `sample_mismatch`. `hold` is `record_incomplete` and appears only on a `ranked` edge.
* `sort=edge` lists wallets with a `ranked` edge and no `hold`, highest `edge` first. Every other wallet sorts as having no edge.
* The leaderboard page ranks those wallets by their edge pulled toward the sports and esports average, which the API does not send, so the two orders can differ.

**Backward compatible.** `price_edge` is a new optional field, and `sort=edge` was refused before.

**What to change:** Nothing is required. To rank by edge, send `sort=edge` and keep it on every page.

**November 2, 2026**

GET /api/v1/markets/search refuses a q with fewer than two letters or digits

[`GET /api/v1/markets/search`](https://docs.0xinsider.com/api-reference/endpoint/search-markets) now answers `400 bad_request` with `error.param` `q` when `q` holds fewer than two letters or digits after trimming. The MCP tool `search_markets` returns the same error, and its `q` schema now has `minLength` 2.

* Refused: `a`, `7`, `?`, `-`, and `a?`.
* Still searched: `ny`, `g2`, `t1`, `-7.5`, and every longer query.

Before this change, such a query returned `200` with a page that matched almost every market and ranked them on no real signal: `a` listed draw markets, and `?` listed markets in an arbitrary order. It also took 300 to 550 ms to answer.

**Breaking** for clients that send a one-character `q`, such as a search box that calls on the first keystroke.

**What to change:** Send at least two letters or digits. In a search box, wait for the second character before you call.

**November 2, 2026**

The leaderboard answers 503 with Retry-After while its rankings are refreshing

[`GET /api/v1/leaderboard`](https://docs.0xinsider.com/api-reference/endpoint/get-leaderboard) now answers `503` with `error.reason: "read_model_warming"` and `Retry-After: 30` when its precomputed rankings are missing or were last checked 180 seconds ago or more. Every `200` page comes from those rankings, and `meta.cached` and `meta.cache_age_s` say how old they are.

Before this change that state answered `200` from a slower read of the live ranking tables, which could take several seconds. We measured no request in that state over the week before the change, so most clients will never see the `503`.

**Breaking** for clients that treat every `503` from this route as a rate-limiter outage or do not retry it.

**What to change:** On a `503` whose `error.reason` is `read_model_warming`, retry this route after `Retry-After` (or `error.retry_at`). Keep it out of any backoff you share with other routes. A `503` with no `error.reason` is still the rate-limiter outage.

**November 2, 2026**

GET /api/v1/leaderboard sorts by P\&L, volume, predictions, win rate or grade

[`GET /api/v1/leaderboard`](https://docs.0xinsider.com/api-reference/endpoint/get-leaderboard) now takes `sort`, `dir` and `activity`, the same orders and 30-day filter as the [leaderboard page](https://0xinsider.com/skill-leaderboard). The `get_leaderboard` MCP tool, the SDK's `listLeaderboard` method and the CLI pass them through.

Before this change, the endpoint listed wallets only in the board's own order, highest `score` first, with no way to sort by P\&L or filter out inactive wallets.

* `sort` is `rank` (the default), `grade`, `volume`, `predictions`, `pnl` or `win_rate`. `win_rate` ranks a wallet's rate once 5 of its markets are decided.
* `dir` is `asc` or `desc`. It defaults to the column's natural direction: rank 1 first, and the largest value first for every other column.
* `activity` is `all` (the default), `active` (traded in the last 30 days) or `inactive`.
* `next_cursor` is tied to the `sort`, `dir` and `activity` of its page. A cursor sent with another `sort` or `dir` returns `400` with `error.param` `cursor`; one sent with another `activity` returns `400` with `error.reason` `cursor_expired`.
* A sorted page can return `503` with `error.reason` `read_model_warming` and `Retry-After` while its ranking copy is more than 5 minutes old.
* A sort changes the order only: the same S, A, and B wallets are listed. `activity` is the one new filter.

**Backward compatible.** Without the new parameters, the order, the rows and the cursor are unchanged.

**What to change:** Nothing is required. To sort, send `sort` and keep the same `sort`, `dir` and `activity` on every page. Retry a sorted `503` after `Retry-After`.

**November 2, 2026**

Per-line sharp money keeps filling a game's lines for two minutes after a read

[`GET /api/v1/games/{event_slug}/markets`](https://docs.0xinsider.com/api-reference/endpoint/list-game-markets) with `expand=sharp_money` now keeps the game's split refilling for two minutes after each read, so a later read in that time answers more of the lines the game page splits. A read that arrives while the game's lines are being listed serves the last split held for the game, dated by `money_as_of`, instead of `unavailable` on every row.

Before this change, refilling stopped 30 seconds after a read, so a game read once kept most of its lines `unavailable`. A read more than about two and a half minutes after the last one could answer every row `unavailable`.

* `not_computed` is unchanged, and the reference now names what it covers: player props, the lines beyond the seven around each family's main line, and closed or settled lines. The game page splits none of them.
* The status values and the `sharp_money` fields are unchanged.

**Backward compatible.** More rows read `computed`; no field, value or status was added or removed.

**What to change:** Nothing. To fill a game, read it, then read it again after a minute or two for the rows that were `unavailable`.

**November 2, 2026**

Two new v1 reads rank each sport's wallets by how surely they beat the price

[`GET /api/v1/leaderboard/categories/{slug}`](https://docs.0xinsider.com/api-reference/endpoint/get-category-leaderboard) returns one sport's or esports' edge board, the board the site's category pages show. It ranks wallets by `edge_lower_bound`, the 95% lower bound of their edge over the prices they paid, and lists only wallets whose lower bound is above zero. It takes `active_within` (`all`, `7d`, `30d`, `90d`), `min_events`, `limit`, and `cursor`, Pro and Max:

* [`GET /api/v1/leaderboard/categories`](https://docs.0xinsider.com/api-reference/endpoint/list-category-leaders) returns every category's top three in one read, the site's categories index, in the same row shape.
* Each row carries `rank`, `category`, `id`, `address`, `username`, `platform`, `grade`, `edge_lower_bound`, `independent_events`, `unresolved_events`, `n_resolved`, `win_rate`, `pnl`, and `as_of`.
* A cursor issued before the hourly ranking refresh returns `400` with `error.reason` `cursor_expired`.

The MCP server adds `get_category_leaderboard` and `list_category_leaders`, and the [CLI](https://docs.0xinsider.com/integrations/cli.md) in `@0xinsider/mcp` 3.9.0 adds `leaderboard category <slug>` and `leaderboard categories`. SDK 0.34.0 adds `getCategoryLeaderboard` and `listCategoryLeaders`.

Before this change, the category boards were on the website only. The strategy pages' top traders were already readable as [`GET /api/v1/leaderboard?strategy=`](https://docs.0xinsider.com/api-reference/endpoint/get-leaderboard), and that is unchanged.

**Backward compatible.** Two new operations; every existing route, field, and tool is unchanged.

**What to change:** Nothing.

**November 2, 2026**

MCP get\_usage reads the minute budget and monthly quota left, at no quota cost

The MCP tool `get_usage` returns what [`GET /api/v1/usage`](https://docs.0xinsider.com/api-reference/endpoint/get-usage) does: `rate_limit` (the minute window's `used`, `limit`, `remaining` and `reset_at`), `monthly_quota` (the month's `limit`, `used`, `remaining`, `reset_at` and pay-as-you-go state) and `daily_usage`. `get_account` returns what [`GET /api/v1/me`](https://docs.0xinsider.com/api-reference/endpoint/get-account-identity) does: the credential kind, scopes and whether paid data access is active. Both are on remote MCP and in `@0xinsider/mcp`.

* Neither call counts against the minute budget or the monthly quota. They share the 100-per-minute allowance of the two REST reads.
* A lapsed account still gets `402` from the MCP endpoint, so it reads both over REST.
* The stdio server in `@0xinsider/mcp` 3.9.0 lists both tools.

Before this change, the quota was readable only from the `X-Monthly-Quota-*` and `X-RateLimit-*` response headers, which MCP clients do not show to the model, or over REST.

**Backward compatible.** Two new tools; every existing tool and its cost is unchanged.

**What to change:** Nothing. An agent that paces itself can call `get_usage` before a long run instead of waiting for a `429`.

**November 2, 2026**

GET /api/v1/games names where a page's time went in Server-Timing

[`GET /api/v1/games`](https://docs.0xinsider.com/api-reference/endpoint/list-games) now sends the parts of its processing time in `Server-Timing`, after `api;dur`. Before this change, the header carried only `api;dur`, the total.

* `catalog`: how long the page waited for the current list of games. Its `desc` is `cached`, `refreshing` (a newer copy was building and the current one served) or `rebuilt`.
* `slice`, `legs`, `metadata` and `game_ids`: the stored reads behind `status=ended`, `cancelled` and `postponed`, which pick the page's games, then read their markets, their team and league details, and their provider game ids.
* `sharp_money`: the `expand=sharp_money` work, when you ask for it.
* `respond`: building the response.

A part that ran more than once on a page carries `desc="N runs"` and its summed time. Parts can overlap, so they need not add up to `api;dur`: on a finished-status list the game list loads while the stored reads run. For example: `Server-Timing: api;dur=72.656, slice;dur=18.407;desc="2 runs", legs;dur=35.200;desc="3 runs", metadata;dur=1.131;desc="3 runs", catalog;dur=1.732;desc="cached", respond;dur=10.796`.

**Backward compatible.** `api;dur` is unchanged and stays the first value. The part names help you report a slow page; they are not a stable schema and can change.

**What to change:** Nothing. If you parse `Server-Timing` yourself, read the `api` metric by name. When you report a slow page, include the whole header.

**November 2, 2026**

New v1 reads rank a sport or league and serve the resolution report and pick stats

[`GET /api/v1/leaderboard/sports/{sport}`](https://docs.0xinsider.com/api-reference/endpoint/get-sport-leaderboard) returns the skill board of one sport, or with `league=` one league's, the board the site's sport pages show. `sort=edge` (the default) ranks the edge over the price paid, `sort=pnl` realized P\&L and `sort=win_rate` the Wilson lower bound of the win rate; `limit` takes 1-100 rows. Three more reads ship with it, Pro and Max:

* [`GET /api/v1/leaderboard/leagues`](https://docs.0xinsider.com/api-reference/endpoint/list-leaderboard-leagues) lists every league with its own board, with the `sport` and `slug` values the board route takes.
* [`GET /api/v1/reports/resolutions?date=`](https://docs.0xinsider.com/api-reference/endpoint/get-resolution-report) returns one UTC day of resolved sports and esports markets: how often the side the profitable (S, A and B) wallets held won, beside every qualifying wallet's side. `view=totals` drops the market list.
* [`GET /api/v1/pick-of-the-day/stats`](https://docs.0xinsider.com/api-reference/endpoint/get-pick-of-the-day-stats) returns the Pick of the Day record broken down by day, sport, league, access group, month, entry-price band, market type and totals side, with streaks, records and every void pick. It is computed from the same rows the archive publishes.

The MCP server adds `get_sport_leaderboard`, `get_leaderboard_leagues`, `get_resolution_report` and `get_pick_of_the_day_stats`, and the [CLI](https://docs.0xinsider.com/integrations/cli.md) in `@0xinsider/mcp` 3.9.0 adds `leaderboard sport <sport>`, `leaderboard leagues`, `reports resolutions <date>` and `pick stats`. SDK 0.33.0 adds `getSportLeaderboard`, `listLeaderboardLeagues`, `getResolutionReport` and `getPickOfTheDayStats`.

Before this change, [`GET /api/v1/leaderboard`](https://docs.0xinsider.com/api-reference/endpoint/get-leaderboard) ranked every wallet across all sports with no league filter, and the resolution report and the stats breakdown were on the website only.

**Backward compatible.** Four new operations; every existing route, field and tool is unchanged.

**What to change:** Nothing. To rank one league, read its `sport` and `slug` from `GET /api/v1/leaderboard/leagues` and call `GET /api/v1/leaderboard/sports/{sport}?league={slug}`.

**November 2, 2026**

Market search puts a market first when you search its exact title

[`GET /api/v1/markets/search`](https://docs.0xinsider.com/api-reference/endpoint/search-markets) now ranks an event first when one of its markets has the exact title you searched for, whatever the game's date. That market is the one returned for the event, even when it is a spread or a total. The match ignores case, spaces at either end, and a closing `?`, `.` or `!`, so a title pasted with or without its question mark counts. The `search_markets` MCP tool calls the same route and returns the same results.

Before this change, ranking was only how closely a title matched, multiplied by how close the game is to today. An exact title for a game a few days out could lose to partial matches dated today. On November 2, 2026, `Will Stade Rennais FC 1901 win on 2026-11-05?` returned its own game 82nd, and `Will Atlanta United FC win on 2026-11-07?` did not return its game in 100 results.

* Every event with an exact-title market ranks ahead of every event without one. Among those events, and among all others, ranking is unchanged: title match times how close the game is to today.
* A matchup title that repeats across games, such as `Red Wings vs. Panthers`, now lists every game with that title first, the nearest date first.
* A query that matches no title exactly, such as `lakers`, returns the same results in the same order as before.

**Backward compatible.** The response shape is unchanged. A cursor issued before the change, for a query that is a market's exact title, can skip that market's event; start again from the first page.

**What to change:** Nothing. To find a market you already know, search its full title; it is the first result.

**November 2, 2026**

Per-line sharp money on list game markets, and a game holders batch

[`GET /api/v1/games/{event_slug}/markets`](https://docs.0xinsider.com/api-reference/endpoint/list-game-markets) takes `expand=sharp_money`. Each row then carries `sharp_money`: how much S, A and B wallet money holds each side of that line, the split the game page shows for every spread, total and prop. [`GET /api/v1/games/{event_slug}/holders`](https://docs.0xinsider.com/api-reference/endpoint/get-game-holders) is new: it returns the graded holders of up to 25 of a game's markets in one request. Both need a Pro or Max key.

Before this change you had to call market holders once per line and add the rows yourself.

* `sharp_money` carries `status` (`computed`, `not_computed` or `unavailable`), `trader_count`, `outcomes[]` with `index`, `usd` and the `s`, `a` and `b` wallet counts, and `money_as_of`.
* Each `ok` game holders item is what market holders returns for that market, unfiltered and cut to `limit`. A market from another game is that item's `not_found`. The route spends the batch item budget, one unit per id.
* The `list_game_markets` MCP tool takes `expand`, the new `get_game_holders` MCP tool calls the holders route, and the SDK adds `getGameHolders` in its next release.

**Backward compatible.** The route, the `expand` parameter and the `sharp_money` field are additive. Without `expand`, game market rows are unchanged.

**What to change:** Nothing is required. A strict schema that rejects unknown keys must accept `sharp_money` on a game market when you send `expand`.

**November 2, 2026**

Game trades name a main spread line once: Spread -3.5, not Spread: Spread -3.5

[`GET /api/v1/games/{event_slug}/trades`](https://docs.0xinsider.com/api-reference/endpoint/list-game-trades) now sends a main spread line's `market.line_label` as Polymarket names it, such as `Spread -3.5`. Before this change, a game that also had half or quarter spreads at the same line put a second `Spread: ` in front, so the label read `Spread: Spread -3.5`.

* Only a label that already starts with its line type changes, such as a main spread line that starts with `Spread`. Before, it got that same word in front a second time when another line type in the game shared its number.
* Half and quarter spread lines keep their prefix, such as `1st Half Spread: 1H Spread -3.5`, so each spread line still reads differently from the others.
* Every other `line_label` is unchanged.

**Backward compatible.** The field and its type are unchanged; only the text of these labels is shorter.

**What to change:** Nothing. If you matched the text `Spread: Spread`, match `Spread -` at the start of the label instead.

**November 2, 2026**

GET /api/v1/games adds window=now, which lists the games on now

[`GET /api/v1/games`](https://docs.0xinsider.com/api-reference/endpoint/list-games) accepts `window=now`, which returns what is on now. The remote MCP tool `list_games` takes the same `window` argument, and the stdio server, the TypeScript client and the CLI help in the next `@0xinsider/mcp` and `@0xinsider/sdk` releases name it.

Before this change, a request with no filters returned the whole catalog in kickoff order. Its first page could hold only games from earlier days: on November 1 at 21:37 UTC it ran from October 10 to the afternoon of November 1, and no live or upcoming game was on it.

* `window=now` keeps every game Polymarket reports `live` or `paused`, and every other game whose kickoff was at most 3 hours ago or is still to come. Games with no published kickoff stay and sort last.
* It leaves out `ended`, `postponed` and `cancelled` games, and any game not in play that kicked off more than 3 hours ago.
* `window=all`, the default, is the catalog as before. Any other value returns `400` `invalid_query` with `error.param` set to `window`.

**Backward compatible.** A request without `window` returns the same games in the same order, and the cursor format is unchanged.

**What to change:** Nothing is required. To read tonight's slate, add `window=now`, or `--query window=now` on the CLI's `games list`.

**November 2, 2026**

One market's biggest net buyers and sellers over 24 hours or 7 days

[`GET /api/v1/market/{condition_id}/wallets-in-out`](https://docs.0xinsider.com/api-reference/endpoint/get-market-wallets-in-out) is new. It returns the 25 wallets that put the most money into one market and the 25 that took the most out, over the last 24 hours (`window=24h`, the default) or 7 days (`window=7d`), and how many wallets were on each side in total. These are the numbers in the Wallets In / Out panel that the 0xinsider market page shows a Pro viewer, and they are live.

* Each wallet carries its display name, today's grade, its net in USD, and its fill count in the window.
* A net is buys minus sells across both outcomes, not a side. Use [Market holders](https://docs.0xinsider.com/api-reference/endpoint/get-market-holders.md) to see which outcome a wallet holds.
* Any `window` other than `24h` or `7d` answers `400`, and an unknown market answers `404`.
* New MCP tool `get_market_wallets_in_out`, CLI command `market wallets-in-out <condition_id>`, and TypeScript client method `getMarketWalletsInOut`.

Before this change, these numbers were only on the market page.

**Backward compatible.** This adds a route and changes no existing one.

**What to change:** Nothing.

**November 2, 2026**

Games show how much each game has traded and how deep each winner market is

[`GET /api/v1/games`](https://docs.0xinsider.com/api-reference/endpoint/list-games) and [`GET /api/v1/games/{event_slug}`](https://docs.0xinsider.com/api-reference/endpoint/get-game) now return Polymarket's traded volume for each game and its reported liquidity for each winner market, each with where it came from and when we read it:

* `volume` on each game: `value`, `unit` (`taker_shares`: one side of each trade, counted in shares, not dollars), `basis` (`game_lines` for the game's own lines, or `event_total` for every market in the Polymarket event), `source` (`polymarket_data` or `gamma`), `observed_at` and `fresh_for_seconds`.
* `liquidity` on each entry in `markets`: `value`, the liquidity Polymarket's market API (Gamma) reports for that market, `source` (always `gamma`) and `observed_at`.

Before this change neither route returned volume or liquidity, so ranking games by activity or skipping thin markets took a separate read per market.

A figure Polymarket does not report is left out, never sent as `0`. A finished game read after it leaves the live board carries neither field. Per-market volume is not included: the catalog holds no sourced, dated figure for each market. The TypeScript client types (`GameVolume`, `GameMarketLiquidity`) and the `list_games` and `get_game` MCP output schemas describe the same fields.

**Backward compatible.** Both fields are optional additions; nothing else in the response changed.

**What to change:** Nothing. To rank games by activity, read `volume.value` and check `volume.basis`: `event_total` counts every market in the event, not only the game lines. Treat volume as shares, not dollars.

**November 2, 2026**

A game's live fills in one read, and event\_slug on large trades and sharp-money flows

[`GET /api/v1/games/{event_slug}/trades`](https://docs.0xinsider.com/api-reference/endpoint/list-game-trades) is new. It returns a game's newest fills across every market in it, newest first and live, the same rows the 0xinsider game page shows a Pro viewer. Each fill carries the wallet's display name and today's grade, and the market's `line_label`, its name within the game.

* `event_slug` is a new filter on [`GET /api/v1/large-trades`](https://docs.0xinsider.com/api-reference/endpoint/get-large-trades), [`GET /api/v1/large-trades/history`](https://docs.0xinsider.com/api-reference/endpoint/get-large-trades-history), and [`GET /api/v1/markets/sharp-money-flows`](https://docs.0xinsider.com/api-reference/endpoint/sharp-money-flows). It keeps only the game's markets, and an unknown game is a `404` with `error.param` set to `event_slug`.
* `condition_id` is a new filter on `GET /api/v1/large-trades` and `GET /api/v1/markets/sharp-money-flows`. History already had it.
* `condition_id` and `event_slug` cannot be sent together. On `GET /api/v1/large-trades`, neither works with `since`, and `event_slug` works with `sort=recent` only. Each of these answers `400`.
* The deprecated `whale-trades` and `smart-money-flows` paths take the same filters.
* New MCP tool `get_game_trades`. `get_large_trades`, `get_large_trades_history`, and `get_sharp_money_flows` take `event_slug`, and the first and last take `condition_id`.
* New CLI command `games trades <event_slug>`, and TypeScript client methods `listGameTrades` and `listGameTradesConditional()`, which returns a typed `304` for polling.

Before this change, a game's fills were only on the game page, and a list could not be narrowed to one game.

**Backward compatible.** Requests without the new parameters return what they did before, and sharp-money-flows cursors from earlier pages stay valid.

**What to change:** Nothing. To follow a game, poll `GET /api/v1/games/{event_slug}/trades` with `If-None-Match` and drop fills whose `id` you have already seen.

**November 2, 2026**

Finished games carry their league, so a league filter on the ended list returns them

[`GET /api/v1/games`](https://docs.0xinsider.com/api-reference/endpoint/list-games) with `status=ended`, `cancelled` or `postponed`, and [`GET /api/v1/games/{event_slug}`](https://docs.0xinsider.com/api-reference/endpoint/get-game) for a finished game, now set `league` on games from leagues without their own board, such as `acle`, `bl3` and `es3`. The value is the league code Polymarket's sports list gives the game's series, the code `coverage.leagues` lists, so `sport=Soccer&status=ended&league=acle` now returns the finished AFC Champions League Elite games.

Before this change, these games returned no `league`, and a league filter on the ended list returned no rows for them. On November 2, 5,326 of the 7,169 finished games in the 7-day window had no `league`, among them 488 of 1,075 soccer, 219 of 291 basketball, and 153 of 199 hockey games.

* A finished game that already had a `league` keeps it.
* Finished tennis and cricket games read Polymarket's league code, such as `itf` or `cricranji`. An open game in the same tournament can read the tournament name instead.
* `league` stays absent when Polymarket's sports list names no league for the game's series.

**Backward compatible.** The response shape is unchanged; more finished games carry `league`.

**What to change:** Nothing. If you matched finished games to a league by their slug, filter with `league=` instead.

**November 2, 2026**

Finished games no longer appear twice when Polymarket copies a game

[`GET /api/v1/games`](https://docs.0xinsider.com/api-reference/endpoint/list-games) with `status=ended`, `cancelled` or `postponed` now lists each finished game once. Polymarket sometimes posts a Protocol V2 copy of a game as a second event, whose slug is the game's slug with a `polyv2` prefix. The list now leaves that copy out and keeps the original game, as the live games list already did.

Before this change, a finished game with a copy appeared twice. On November 2, the 7-day window listed six such pairs, for example `nba-det-nyk-2026-10-27` and `polyv2-nba-det-nyk-2026-10-27`. The copy had `league: null` and no score.

* [`GET /api/v1/games/{event_slug}`](https://docs.0xinsider.com/api-reference/endpoint/get-game) with a copy's slug now returns `404`. Read the original game's slug instead.
* A copy stays in the list, under its own slug, when 0xinsider has no record of the original game. It is then the only record of that game.

**Backward compatible.** The response shape is unchanged. The list returns one row per game instead of two.

**What to change:** Nothing. If you removed `polyv2` copies yourself, you can stop.

**November 2, 2026**

The games catalog adds NCAA women's college basketball

[`GET /api/v1/games`](https://docs.0xinsider.com/api-reference/endpoint/list-games) now includes NCAA women's college basketball games as `league=cwbb`, under `sport=Basketball`. `coverage.leagues` lists `cwbb`. Use `sport=Basketball&league=cwbb` to list them, then [`GET /api/v1/games/{event_slug}`](https://docs.0xinsider.com/api-reference/endpoint/get-game) for one game's linked markets.

Before this change, an open `cwbb-*` game was missing from the list while it was upcoming, and `GET /api/v1/games/{event_slug}` returned `404` for it. Most of these games are thinly traded: the median open game had \$30 of liquidity on November 2, 2026.

* [`GET /api/v1/sports/pre-game-side-observations`](https://docs.0xinsider.com/api-reference/endpoint/get-pre-game-side-observations) includes upcoming women's college basketball games in its basketball supply.
* `funnel.sports[].board_upcoming_unavailable_scopes` can contain `cwbb` when that upcoming source is unavailable. The OpenAPI enum and generated SDK types include the value.

**Backward compatible.** Coverage and the unavailable-scope value are additive. Request parameters and response fields are unchanged.

**What to change:** Nothing unless you validate the unavailable-scope values against a fixed list; add `cwbb`. Use `league=cwbb` when you want only women's college basketball games.

**November 2, 2026**

Market search finds every open game, not only games with a \$10,000 trade

[`GET /api/v1/markets/search`](https://docs.0xinsider.com/api-reference/endpoint/search-markets) now searches every unresolved game market (a game's winner market, or an outright) whether or not it has traded, together with every market that has had a single trade of \$10,000 or more. The `search_markets` MCP tool and the TypeScript client `searchMarkets` call the same route and return the same results.

Before this change the search covered only markets with a \$10,000 trade, so an open game nobody had traded that large returned nothing for any query, its exact title included. On November 2, 2026 that hid 31,150 of 31,231 open game markets, among them almost every college basketball game.

* A game's winner market and its larger-traded spreads, totals and props still collapse into one result per event.
* Ranking is unchanged: title match times how close the game date is to today. Open games without large trades now rank beside the ones with them.
* A resolved market without a \$10,000 trade is still not returned.

**Backward compatible.** The response shape is unchanged; queries return more open games.

**What to change:** Nothing. If you worked around missing games by reading `GET /api/v1/games`, search now finds them too.

**November 2, 2026**

Finished soccer games name both teams, with provider IDs

[`GET /api/v1/games/{event_slug}`](https://docs.0xinsider.com/api-reference/endpoint/get-game) and [`GET /api/v1/games`](https://docs.0xinsider.com/api-reference/endpoint/list-games) with `status=ended`, `cancelled` or `postponed` now name both sides of a finished game that has no live score and no moneyline named by team. A soccer game's three 1X2 legs read `Yes` and `No`, so this covers most soccer leagues without a live-score feed. These games now carry `competitors[].name`, `provider_id`, and `logo` from Polymarket's teams for the event, and `coverage.competitors` reads `provider_ids`.

Before this change, these games returned `competitors: []` with `coverage.competitors` `unavailable`. On November 2, 492 of the 1,068 finished soccer games in the 7-day window read this way, for example `acle-nef-itj-2026-10-26` in the AFC Champions League Elite.

* A finished game that already had names keeps them, from its final score or its moneyline's outcome labels.
* `competitors` stays empty and `unavailable` when no team record exists for the game.
* `coverage.scores` is unchanged: a game no live-score feed reported still has no score.

**Backward compatible.** The response shape is unchanged; more finished games carry `competitors`.

**What to change:** Nothing. If you looked up a second source to name these games, read `competitors` instead.

**November 2, 2026**

New game sharp money read, also on list\_games with expand=sharp\_money

[`GET /api/v1/games/{event_slug}/sharp-money`](https://docs.0xinsider.com/api-reference/endpoint/get-game-sharp-money) returns how much S, A and B grade money backs each side of one game, and the verdict the game page shows for it. [`GET /api/v1/games`](https://docs.0xinsider.com/api-reference/endpoint/list-games) attaches the same object to every game on a page when you send `expand=sharp_money`. Both need a Pro or Max key.

Before this change you had to page market holders for every market of a game and add the rows yourself. The new object carries:

* `outcomes[]`: per side, `usd`, `pct`, `is_leader`, and the S, A and B wallet counts.
* `verdict`, keyed by `kind`, plus `total_usd`, `allocation`, `unallocated_usd`, `trader_count` and `holders_partial`.
* `status`, `lifecycle`, `computed_at` and `money_as_of`.

The same read is the `get_game_sharp_money` MCP tool, `list_games` takes `expand`, and the CLI adds `0xinsider games sharp-money <slug>` in its next release. The SDK adds `getGameSharpMoney` in its next release.

**Backward compatible.** The route, the `expand` parameter and the `sharp_money` field are additive. Without `expand`, `list_games` rows are unchanged.

**What to change:** Nothing is required. A strict schema that rejects unknown keys must accept `sharp_money` on a game when you send `expand`.

**November 2, 2026**

The games catalog adds NCAA men's college basketball

[`GET /api/v1/games`](https://docs.0xinsider.com/api-reference/endpoint/list-games) now includes NCAA men's college basketball games as `league=cbb`, under `sport=Basketball`. `coverage.leagues` lists `cbb`. Use `sport=Basketball&league=cbb` to list them, then [`GET /api/v1/games/{event_slug}`](https://docs.0xinsider.com/api-reference/endpoint/get-game) for one game's linked markets.

Before this change, no scope covered college basketball. An open game such as `cbb-warwil-ncat-2026-11-03` was missing from the list while it was upcoming, and `GET /api/v1/games/{event_slug}` returned `404` for it.

* [`GET /api/v1/sports/pre-game-side-observations`](https://docs.0xinsider.com/api-reference/endpoint/get-pre-game-side-observations) includes upcoming college basketball games in its basketball supply.
* `funnel.sports[].board_upcoming_unavailable_scopes` can contain `ncaa-basketball` when that upcoming source is unavailable. The OpenAPI enum and generated SDK types include the value.
* Women's college basketball is not included.

**Backward compatible.** Coverage and the unavailable-scope value are additive. Request parameters and response fields are unchanged.

**What to change:** Nothing unless you validate the unavailable-scope values against a fixed list; add `ncaa-basketball`. Use `league=cbb` when you want only college basketball games.

**November 2, 2026**

Game status fields come only from a live-score feed, never from labels of our own

[`GET /api/v1/games`](https://docs.0xinsider.com/api-reference/endpoint/list-games) and [`GET /api/v1/games/{event_slug}`](https://docs.0xinsider.com/api-reference/endpoint/get-game) now send `status.match_status`, `status.provider_status`, and `status.live` only when a live-score feed has reported the game. `coverage.scores` reads `available` only when that feed supplied a score.

Before this change, a listed game that no live-score feed had reported carried labels the API derived itself. On November 1, 1,986 of 2,023 listed games read this way:

* `status.provider_status` was `Scheduled`, or `Started`, a string no provider sent.
* `status.match_status` was `scheduled` and `status.live` was `false`.
* `coverage.scores` was `available` with no score and no `freshness.scores_observed_at`.

A game read from Polymarket's event data, with no status from the live-score feed, also stops sending `status.provider_status`: its `Live`, `Finished`, or `Scheduled` was a label of our own. `status.state` is unchanged. A game that Polymarket lists as open, neither in play nor ended, still reads `scheduled` when no feed has reported it, also after its kickoff.

**Breaking** for clients that read `status.provider_status` `Scheduled` or `status.live` `false` to find games that have not started. Every one of these fields was already optional and documented as omitted when no live-score frame exists.

**What to change:** Read `status.state` to tell a scheduled game from a live one. Treat a missing `status.live` as unknown, not as `false`, and check `coverage.scores` before you read `competitors[].score`.

**November 2, 2026**

GET /api/v1/games lists finished games with status=ended, cancelled or postponed

[`GET /api/v1/games`](https://docs.0xinsider.com/api-reference/endpoint/list-games) with `status=ended`, `cancelled` or `postponed` now lists finished games that have left the live board. They come from the same stored records [`GET /api/v1/games/{event_slug}`](https://docs.0xinsider.com/api-reference/endpoint/get-game) serves, with `freshness.source` `stored`, merged with any finished game still on the board in the usual `scheduled_at`, then `event_slug` order.

Before this change the list drew only on the live and upcoming board, so `status=ended` returned only the few games that had not left it yet.

* Stored games cover kickoffs from `starts_after` to `starts_before`. Without `starts_after` the window reaches back 7 days from `starts_before`, which defaults to, and is capped at, the time of the read.
* Each read scans a bounded slice of that window, so a page can hold fewer than `limit` games, or none, while `has_more` is `true`.
* A stored game reads as it does on the detail: `status.state` `ended`, `cancelled` or `postponed`, the final score when one was recorded, moneyline `markets[]` without `prices`, and no `title`.
* `as_of` is the time of the read for these statuses. Without a finished `status`, the list is unchanged.

**Backward compatible.** The response shape is unchanged; a finished `status` returns more games.

**What to change:** Page on `has_more` and `next_cursor`, never on a short or empty page. If you switch on `freshness.source` exhaustively, handle `stored`.

**November 2, 2026**

New GET /api/v1/games/\{event\_slug}/markets lists every market of a game

[`GET /api/v1/games/{event_slug}/markets`](https://docs.0xinsider.com/api-reference/endpoint/list-game-markets) is new. It lists every stored Polymarket market of one game, including spreads, totals, team totals, period lines and player props, with each market's `condition_id`, `sports_market_type`, `line` and outcome token ids. The new `list_game_markets` MCP tool and the SDK's `listGameMarkets` method call it.

Before this change, no endpoint listed a game's spreads, totals or props. The game object's `markets` holds only the winner markets, and the docs said it held every linked market. [Search markets](https://docs.0xinsider.com/api-reference/endpoint/search-markets.md) returns one market per game.

* `families` counts each market type the game has, whatever the filters.
* A soccer game's child events (exact score, halftime result, more markets) are included, and each row's `event_slug` names its own event.
* [`GET /api/v1/markets/search`](https://docs.0xinsider.com/api-reference/endpoint/search-markets) results now carry `event_slug`, so you can go from a search result to the game's full market list.
* The descriptions of `list_games`, `get_game` and `search_markets` now say what they return: the winner markets, and one market per event.

**Backward compatible.** The endpoint, the MCP tool and the `event_slug` field are additive. Existing responses are unchanged.

**What to change:** Nothing is required. To find a game's props, call the new endpoint with the game's `event_slug`. A strict schema that rejects unknown keys must accept `event_slug` on search results.

**November 2, 2026**

A finished game stays readable by its slug, served from its stored record

[`GET /api/v1/games/{event_slug}`](https://docs.0xinsider.com/api-reference/endpoint/get-game) now returns a finished game after it leaves [`GET /api/v1/games`](https://docs.0xinsider.com/api-reference/endpoint/list-games). Once the provider reports the game final, awarded, forfeited, cancelled or postponed, or every moneyline leg has resolved, it is served from its stored record with `freshness.source` `stored`.

Before this change the detail drew only on the live and upcoming board, so a game returned `404` within minutes of its final whistle.

* `freshness.source` adds the value `stored`. `freshness.source_freshness` is `not_applicable` and `freshness.source_observed_at` is the later of the last live-score write and the last leg settlement.
* `status.state` reads `ended`, `cancelled` or `postponed`. `competitors[].score` carries the final score when a live-score frame recorded one.
* `markets[]` lists the moneyline markets without `prices`, and `title` is omitted.
* A game the board dropped while it was still in play still returns `404`. `GET /api/v1/games` is unchanged and lists only live and upcoming games.

**Backward compatible.** Live and upcoming games read exactly as before.

**What to change:** If you switch on `freshness.source` exhaustively, handle `stored`. To read a result after the game ends, call the detail by its `event_slug` instead of looking for it in the list.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.