Skip to main content
These are the API changelog entries from October 12 to 16, 2026, newest first. The newest changes are on the API changelog.
Edge Hunter upcoming boards drop their 3,000-row limit; only the size limit remains
GET /api/v1/edge-hunter now reports board_upcoming_status: "capacity_limited" for a cached upcoming board only when the board reaches its 5,000,000-byte limit. A busy soccer week can now carry about 1,100 matches before that happens, up from 1,000.Before this change, a cached upcoming board was also cut at 3,000 rows, which the soccer board was close to reaching on a full weekend.Backward compatible.What to change: Nothing. Keep reading capacity_limited as an intentionally bounded list, not a complete schedule.
Untraded sports markets far from kickoff refresh every 3 days; snapshots can read stale
GET /api/v1/market/{condition_id}/snapshot and MCP get_market_snapshot now refresh market_data every three days, not every 20 hours, for a sports market with no volume whose kickoff is more than 12.5 hours away or unknown. Between refreshes its market_data.status can read stale, with reason provider_refresh_older_than_24h, for up to two days.Before this change, every open sports market was refreshed at least every 20 hours, so market_data.status for these markets stayed fresh under its 24-hour bound.
  • A sports market with any volume, past its kickoff, or within 12.5 hours of it keeps the 20-hour refresh. A market inside a kickoff window is still refreshed every 30 minutes.
  • The rule for status does not change: stale means the provider data is older than stale_after_s (86,400 seconds), and as_of gives the last refresh.
  • On October 14, 2026, these markets were 72% of open sports markets.
Backward compatible. No field is added, removed, or retyped.What to change: Nothing. For these markets, expect stale between refreshes; it clears at the next refresh, or when the market comes within 12 hours of kickoff.
SDK 0.28.0 requires Node.js 22 or newer
@0xinsider/sdk 0.28.0 declares engines.node >=22 and joins each request’s deadline and your signal with AbortSignal.any. On Node.js 22 and later, every method and helper behaves as in 0.27.1.Before this change, the package declared Node.js 18 or newer, though Node.js 18 reached end of life on April 30, 2025, and Node.js 20 on April 30, 2026. The SDK also carried a manual fallback for runtimes without AbortSignal.any.
  • On Node.js 18 or 20, npm install @0xinsider/sdk@0.28.0 warns with EBADENGINE, and fails when npm’s engine-strict is set.
  • On a runtime without AbortSignal.any (Node.js before 18.17, or 20.0 through 20.2), a call that passes signal now throws a TypeError unless timeoutMs is null.
  • Two error messages that named Node 18+ now name Node 22+.
Breaking for Node.js 18 and 20.What to change: Run Node.js 22 or newer to use 0.28.0, or stay on 0.27.1 until you upgrade.
Scheduled pick previews end when their release time arrives
GET /api/v1/pick-of-the-day now returns scheduled previews only for future release times on the current date. At or after release_at, the preview disappears; the selection can be published or closed without publication.Before this change, an overdue selection could remain visible as a delayed release. Published picks keep their original ledger records, and published picks awaiting readable proof keep their existing retry guidance.Breaking for clients that keep overdue scheduled previews. Response fields, access rules, and ordinary settlement and withdrawal behavior are unchanged.What to change: Remove a scheduled preview when its returned release_at arrives, and use the latest response. Keep honoring returned retry times; a scheduled preview does not guarantee publication.
Daily picks can become available more promptly
GET /api/v1/pick-of-the-day can now make daily picks available more promptly when ready. Before this change, some ready selections could remain unavailable longer.Backward compatible. Current and archive response fields and returned retry guidance are unchanged.What to change: Nothing. Continue to honor returned release times and retry guidance.
MCP 3.6.1 and SDK 0.27.1 refresh descriptions and correct a response type
@0xinsider/mcp 3.6.1, Remote MCP, and @0xinsider/sdk 0.27.1 refresh Pick of the Day and archive descriptions to match the current API. The SDK also corrects the getMarketHolders result type: total is required, matching a field the API always returns. SDK 0.27.1 is also the first release whose webhook payload types are generated from the OpenAPI webhooks map, under the same names, and it adds the WebhookEventData export, which pairs each event type with its payload.Before this change, some MCP descriptions still named the earlier daily limit, and the SDK treated the holder-list total as optional. The refreshed MCP descriptions state the public daily access: Pro opens 5 selections in total, and Max opens every available daily selection, up to 20.Breaking for TypeScript code that constructs a getMarketHolders result without total. Live API calls, tool names, inputs, response fields, and runtime behavior are unchanged.What to change: Include total in constructed or mocked holder-list results. Refresh a cached Remote MCP tools/list. Update local clients to @0xinsider/mcp 3.6.1 or @0xinsider/sdk 0.27.1 for the refreshed descriptions and type correction.
Pick of the Day increases the public daily capacity from 15 to 20
GET /api/v1/pick-of-the-day, its dated reads, and MCP get_pick_of_the_day now support up to 20 active recommendations per date in America/New_York. Max opens all available published recommendations; Pro keeps its allowance of 5, including the designated free selection.Before this change, the public daily capacity and Max allowance were 15. After withdrawals, later additions can now use compatibility pick_rank values through 25, while the date still has at most 20 active recommendations.
  • Withdrawal gaps do not change existing pick IDs, order, or proof bytes. Use pick_id for identity and publication_order for presentation.
  • The archive keeps the same access rules and excludes withdrawn recommendations. The public ledger retains published commitments.
  • A date can have fewer than 20 recommendations. The private feed keeps its independent capacity.
  • potd-trader v0.4.2 accepts up to 20 daily recommendations and compatibility ranks through 25 for Polymarket and Kalshi. Its default spending limits are unchanged.
Breaking for clients that enforce the old pick-count or rank bounds. The response fields and types are unchanged.What to change: Remove assumptions that a public date has at most 15 active recommendations or that pick_rank cannot exceed 20. Stop older potd-trader watchers and upgrade to v0.4.2 before using the expanded slate. Honor the returned access fields, entry authorizations, and your own spending limits.
Edge Hunter observations use the original live source clock for freshness
GET /api/v1/edge-hunter?view=observations now accepts coherent provider-live evidence for up to 30 seconds from its original observation time. A website refresh becoming due no longer rejects that evidence on its own.Before this change, the website’s 2-second refresh marker could expire while the provider observation was still within the observation view’s 30-second liveness limit, leaving live cohorts unavailable. First-page holder collection also now gets bounded priority and rotates markets awaiting evidence, so repeated attempts do not always start with the same markets.
  • The live source must remain valid and within 30 seconds during computation and when cached in-play rows are returned. Snapshot completion, cache reuse, and a missed-refresh grace period do not restart that clock.
  • Provider-confirmed live membership has its own original source clock, independent of rendered scores and enrichment. A UI score invalidation or refresh becoming due does not invalidate that separate membership evidence.
  • Invalidated provider sources, incomplete or invalid observations, and missing, future-dated, or expired source clocks are not accepted. An in-play snapshot whose live source has expired returns 503 with error.reason: read_model_warming until a fresh snapshot is available.
  • Original holder clocks, holder populations, incomplete-scan reporting, ranked views, and deeper holder completion rules are unchanged. Bounded collection does not guarantee complete coverage; continue to read degraded, degradation_reasons, and coverage.
Backward compatible. No response field, type, query parameter, or access requirement changes.What to change: Nothing. Keep handling 503 read_model_warming with its Retry-After, and check source clocks and coverage before using a small or empty result.
Edge Hunter recognizes fresh position reads even when balances stay unchanged
GET /api/v1/edge-hunter now uses a verified complete position observation to date unchanged positions when that observation covers them. This corrects directional measurements on the board, ranked signals, and observations.Before this change, an unchanged position kept the timestamp of its last value change. It could therefore leave directional measurements unknown even after a fresh complete position read.
  • directional_confidence, one_way_holder_count, hedged_holder_count, and one_way_graded_usd can become available for positions whose freshness is now recognized.
  • directional_rank_score and ordering can change when corrected evidence changes the measurements. The ranking calculation is unchanged.
  • The freshness window and hedge classification are unchanged. Missing, stale, or unclassifiable evidence still remains unknown; null never means zero.
  • Published picks keep their frozen values.
Backward compatible. No response field, type, parameter, or access requirement changes.What to change: Nothing. Continue to accept unknown directional measurements and read their provenance separately from quote freshness.
Edge Hunter keeps ranked board markets covered by live quote subscriptions
GET /api/v1/edge-hunter with view=board now keeps bounded live quote coverage active for its ranked board markets. Requests with selection filters also renew coverage for the rows they return.Before this change, a market could rank on the board without an active quote subscription, leaving outcomes[].current_price and signal.current_price as null unless another surface supplied a verified quote.Responses still read verified caches without making inline CLOB REST requests. A first request for a market without quote coverage can still return null while its first order-book update is pending. Available quotes retain their original ts and retention limit.Backward compatible. The response fields, ranking, and access requirements are unchanged.What to change: Nothing. Continue to accept null quotes and read quote ts separately from ranking as_of.
Combo fills fixes intermittent timeouts for open combos filtered by wallet grade
GET /api/v1/combos/fills now uses targeted reads for open combos filtered by wallet grade, such as grades=S,A with result=pending.Before this change, requests with grades=S,A could intermittently time out, especially with result=pending, even when matching fills existed. Adding B to the selection could return results while the S,A request failed.Backward compatible. The parameters, pagination, and response fields are unchanged.What to change: Nothing.
The market holders response always carries total, and the schema now says so
GET /api/v1/market/{condition_id}/holders now documents total as a field every response carries. total is the number of holders that match the request’s filters across every page.Before this change, the OpenAPI document listed total as optional, although the API has always sent it. The response itself does not change.
  • The OpenAPI document lists total in the response’s required fields.
  • @0xinsider/sdk types it total: number instead of total?: number from 0.27.1.
  • Remote MCP get_market_holders lists total among the required keys of its output schema.
Breaking only for Go code generated from the document, where total changes from a pointer to a value.What to change: Nothing. After you update the SDK or regenerate a client, you can drop any check for a missing total.
Market snapshot top_of_book stays available while a streamed book is quiet
GET /api/v1/market/{condition_id}/snapshot now returns a streamed market’s cached book in outcomes[].top_of_book for as long as 0xinsider streams it, however long the book goes without a change.Before this change, top_of_book answered status unavailable with reason cache_miss once a book had gone about 24 seconds without a change, while current_price was still priced from that same book. A polled market with a quiet book answered cache_miss on most reads.
  • A book that changes often reads as before.
  • freshness.top_of_book follows the outcomes: it is available whenever an outcome’s book is cached.
  • A book with one side empty still answers cache_miss, because it has no best bid and ask to report.
  • The first read of a market outside 0xinsider’s standing set still answers cache_miss and starts streaming that market.
Backward compatible. No field is added, removed, or retyped; top_of_book is available on more reads.What to change: Nothing.
MCP 3.6.0 installs 4 packages instead of 96 and also serves the 2026-07-28 protocol
@0xinsider/mcp 3.6.0 moves to the MCP TypeScript SDK v2 (@modelcontextprotocol/server), so npx -y @0xinsider/mcp installs 4 packages (18 MB) instead of 96 (28 MB). Its stdio server also answers clients that open with the 2026-07-28 MCP revision.Before this change, the package depended on @modelcontextprotocol/sdk 1.x, which pulls in the dependencies of every transport and of OAuth, Express and Hono included, though this server speaks only stdio. A client that opened with 2026-07-28 fell back to the 2025-11-25 initialize handshake.
  • Every initialize revision that 3.5.0 accepted, 2024-10-07 through 2025-11-25, negotiates as before.
  • The 55 tools, 4 prompts and 4 resources keep their names, descriptions, annotations, input schema keywords and results. The server instructions are unchanged.
  • Each tool’s inputSchema now declares "$schema": "https://json-schema.org/draft/2020-12/schema", the MCP default dialect. It declared http://json-schema.org/draft-07/schema# before.
  • Tools no longer list "execution": {"taskSupport": "forbidden"}. An absent execution means the same thing: the tool cannot run as a task.
  • A call to a tool name that tools/list does not return now gets a JSON-RPC error with code -32602, the protocol error the MCP specification describes for it. Before, it got a result with isError: true and the text MCP error -32602: Tool <name> not found.
  • SDK error messages drop the MCP error -32602: prefix. An input validation message now names the field first, as in Input validation error: Invalid arguments for tool get_trader: address: Invalid input: expected string, received undefined, and an unknown resource reads Resource not found: <uri>.
Breaking for a client that calls a tool name tools/list does not return and reads the answer as a tool result, or that matches SDK error text.What to change: Nothing if your client calls only the tools tools/list returns. Otherwise, handle the -32602 JSON-RPC error for an unknown tool, and match error codes rather than message text. Update to 3.6.0 or later for the smaller install.
MCP 3.5.0 adds 10 read tools, max_age_s on get_trader, and trust on get_market_snapshot
@0xinsider/mcp 3.5.0 and Remote MCP add 10 tools, one for each /api/v1 read that had no tool. get_trader now takes max_age_s, and get_market_snapshot takes expand: ["trust"].Before this change, these reads and both parameters were REST-only. An agent on MCP could not reach them, and nothing listed which reads MCP left out or why.
  • Traders: get_trader_context reads the trader context object, get_trader_categories the win record in each category, and get_trader_grade_at the grade recorded at a past instant.
  • Markets: get_market_holders lists the S, A and B graded holders with market, scan and totals beside the page. get_market_candles reads daily or weekly price candles.
  • Combos, with a Pro or Max key: get_combo_fills (fills), get_combos_summary (live count) and get_combo (one combo).
  • Large trades: get_large_trade_counterparty_executions and get_large_trade_counterparty_makers page past the first counterparty page that get_large_trade embeds, on the same snapshot_id.
  • max_age_s on get_trader answers only when data_quality.status is fresh and data_quality.as_of is no older than the ceiling. Otherwise the call fails with reason freshness_ceiling_unsatisfied, and nothing is refreshed to meet it.
  • expand: ["trust"] on get_market_snapshot adds provenance for current_price and spread_bps.
  • These reads stay REST-only: discovery, health, the account reads, webhook management, the event stream, export and dataset job polling and downloads, the two context.md renderings, and the whole pick ledger.
Backward compatible. Existing tool names, inputs, and results are unchanged.What to change: Nothing. Refresh a cached Remote MCP tools/list to see the new tools, and update to @0xinsider/mcp 3.5.0 to call them over stdio.
A pick's odds_display rounds a half-tick price the way the web app does
odds_display in GET /api/v1/pick-of-the-day, including dated reads, GET /api/v1/pick-of-the-day/archive, and MCP get_pick_of_the_day now rounds the backed price’s decimal value half away from zero. That is the rule the 0xinsider web app uses for every price in cents. A backed price of 0.6615 now reads "66.2c"; it read "66.1c" before.Before this change, the label rounded the price multiplied by 100 as a binary floating-point number. For some prices whose fourth decimal is 5, that product falls just below the half, so the label read 0.1c lower than the web app showed for the same pick.
  • Only a price whose fourth decimal is 5 can change, and it moves up by 0.1c. Of the 492 picks with a backed price on October 14, 2026, 2 read differently.
  • The format does not change: cents to one decimal with a c suffix, omitted when the price is unknown.
  • backed_price does not change and remains the source value.
Not breaking. No field is added, removed, or retyped.What to change: Nothing. A client that formats backed_price itself should round the decimal value half away from zero to match.
Trader scores are republished when they move half a point, so ranking as_of can be older
GET /api/v1/trader/{address}, batch traders, trader context, GET /api/v1/leaderboard and the whale trade endpoints now publish a new score or forecast_score only when the hourly grading pass moves it by 0.5 points or more on its 0-100 scale. A grade change, a change of forecast_evidence, and a score that appears or disappears are still published in the pass that makes them.Before this change, nearly every pass rewrote every graded wallet’s scores for moves of about a tenth of a point, and restamped the ranking data-quality group each time.
  • score and forecast_score are each within 0.5 points of the latest pass’s value. Leaderboard order uses the published scores.
  • The ranking group’s as_of is when the published scores were last written. For a wallet whose scores hold still it can be several hours old, and data_quality.as_of takes the oldest group.
  • max_age_s on GET /api/v1/trader/{address} compares that as_of, so a ceiling of a few hours or less can answer 409 for such a wallet.
Breaking only for clients that send a max_age_s of a few hours or less and expect the ranking group to be at most one pass old. No field is added, removed, or retyped.What to change: Treat score and forecast_score as current to within half a point. If you send max_age_s, allow for a ranking group as_of that marks the last write, not the last check.
OpenAPI describes every webhook payload in a webhooks map
The OpenAPI document now describes every webhook delivery in its top-level webhooks map: one entry for each of the 16 event types. Each entry documents the signed delivery headers, the envelope (id, type, created_at, data), and the data payload as a schema, with each field’s type, whether it can be null, and what it means.Before this change, the document named the event types but described no payload, and @0xinsider/sdk declared its payload types by hand. Now the backend builds each payload from a typed struct, the API’s contract check holds every struct to its schema, and the SDK generates its payload types from the schemas. The payloads themselves do not change, and neither do the SDK types you import.The payload schemas are in components.schemas: LargeTradeInsertedV2Data, LargeTradesInsertedData, LiveSportsUpdatedData with LiveSportsScoreEntry, TraderSyncedData, LargePositionsUpdatedData, WalletGradeChangedData, SuspiciousTradeFlaggedData, SharpMoneyFlowDetectedData, and one for each export job event. The two spellings of a renamed event share one schema.What to change: Nothing. A client you generate from the document gains these 13 schemas as types.
OpenAPI marks 23 always-sent fields as required, and SDK 0.27.0 stops marking them optional
The OpenAPI document now lists in required 23 response fields that the API sends on every response. @0xinsider/sdk 0.27.0 types them without ?.Before this change, the document left these fields out of required, so the SDK typed them field?: T although no response omits them. The responses themselves do not change.The same check corrected 3 other descriptions:
  • monthly_quota.unavailable_reason is removed from GET /api/v1/usage. The entry of October 1, 2026 announced it, but this route has never sent it. When billing needs reconciliation, pay_as_you_go is false.
  • The remote MCP 200 response documents the optional error.data, as the MCP error response already did. The server omits it today.
  • The webhook list response’s next_cursor and total are omitted when they have no value. They were described as null.
Breaking for TypeScript code that reads monthly_quota.unavailable_reason from the SDK types, and for Go code generated from the document, where the 23 fields change from pointers to values.What to change: Remove reads of monthly_quota.unavailable_reason. After you update the SDK or regenerate a client, you can drop undefined checks on the 23 fields. Otherwise nothing.
A withdrawn pick no longer takes one of Pro's four nonfree daily picks
GET /api/v1/pick-of-the-day, including dated reads, GET /api/v1/pick-of-the-day/archive, and MCP get_pick_of_the_day now skip withdrawn picks when they count the four nonfree selections a Pro credential opens. Pro still opens the designated free selection and the first 4 nonfree selections in publication order.Before this change, a withdrawn pick was left out of every read but still took one of the four places. On a day when one of the first four nonfree picks was withdrawn, a Pro credential received three nonfree picks, and the next one stayed in locked_picks with required_tier: "max".
  • After a withdrawal, the next nonfree pick in publication order opens to Pro credentials: it moves from locked_picks to picks, or to scheduled_picks if it has not published yet.
  • A withdrawn pick keeps the access it had, and no pick a Pro credential could open closes. Max and free access do not change.
  • No pick published so far changes access: the one pick withdrawn before October 14, 2026 was a free selection.
Not breaking. No field is added, removed, or retyped.What to change: Nothing. A Pro client that caches locked_picks should expect a locked rank to open after a withdrawal.
Market snapshot current_price is the price Polymarket shows, not a wide book's middle
GET /api/v1/market/{condition_id}/snapshot now sets outcomes[].current_price to the price Polymarket shows: the midpoint of the cached best bid and ask when they are at most $0.10 apart, otherwise the outcome’s last trade price. SDK getMarketSnapshot, MCP get_market_snapshot, and Market context as Markdown carry the same value.Before this change, current_price was the midpoint of the cached bid and ask however far apart they were. A thin book bidding $0.02 and asking $0.98 returned 0.5, a price that neither Polymarket nor any 0xinsider page showed.
  • A book at most $0.10 wide returns the same midpoint as before.
  • A wider book returns the outcome’s last trade price when 0xinsider has one cached, and leaves current_price out when it does not. top_of_book still carries that book’s best_bid, best_ask, and spread_bps.
  • With expand=trust, trust.current_price is computed when an outcome has a price, and unavailable with a reason when a cached book was too wide to price.
  • The spec now describes current_price and bounds it from 0 to 1.
Breaking only for clients that expect current_price whenever top_of_book has a bid and an ask. The field was already optional, and no field is added, removed, or retyped.What to change: Treat a missing current_price as no price. If you need the middle of a wide book, compute it from top_of_book yourself.
SDK 0.26.0 types webhook trade_id as a number and fixed-set fields as literal unions
@0xinsider/sdk 0.26.0 types trade_id in the suspicious_trade_flagged and insider_radar_flag_raised webhook payloads as a number, the JSON number the API sends. Fields the API fills from a fixed set are now literal unions instead of string.Before this change, the SDK typed trade_id as a string, so event.data.trade_id === storedId with a string id compiled and never matched. The API has sent a number since the event shipped on June 21, 2026; the wire does not change.
  • track: "whale" | "fresh_conviction" | "sliced_position".
  • side (suspicious_trade_flagged) and dominant_side (sharp_money_flow_detected): "yes" | "no".
  • direction (wallet_grade_changed): "upgrade" | "downgrade".
  • old_grade, new_grade and grade_floor: Grade, "S" | "A" | "B" | "C" | "D" | "F".
Breaking for TypeScript code that treats trade_id as a string or compares a narrowed field with a value outside its set. JavaScript callers and the delivered JSON are unchanged.What to change: Compare trade_id with a number, for example event.data.trade_id === Number(storedId), and remove comparisons the compiler now reports as impossible.
MCP 3.4.1 accepts an OXINSIDER_API_URL that ends in /api/v1 for every tool
@0xinsider/mcp 3.4.1 reads an OXINSIDER_API_URL that ends in /api/v1 as the same server for every tool, the way @0xinsider/sdk reads its baseUrl. https://api.0xinsider.com/api/v1 and https://api.0xinsider.com now reach the same routes.Before this change, with a base ending in /api/v1, every tool except get_edge_hunter requested a doubled path such as /api/v1/api/v1/trader/{address} and failed with not_found and reason unknown_endpoint. The documented default, the bare origin, was not affected.
  • Which bases receive your API key is unchanged: https:, or http: for a loopback host only.
  • A refused OXINSIDER_API_URL still stops the server before any request. The message is now the SDK’s, which calls the setting baseUrl.
  • @0xinsider/sdk adds two exports in its next release. parseRetryAfterStrict reads Retry-After by the RFC 9110 grammar alone and returns whole seconds or null. isTimeoutAbort tells a deadline abort from other aborts. parseRetryAfter is unchanged.
Backward compatible. Tool names, inputs, results, and error codes are unchanged.What to change: Nothing. To use a base that ends in /api/v1, update to @0xinsider/mcp 3.4.1 or later.
Live esports in-game scores no longer go backwards or switch teams
scores[].map_score is now always the last in-game pair the provider reported for the game in play. This applies to sports.live_score in GET /api/v1/market/{condition_id}/snapshot, SDK getMarketSnapshot, MCP get_market_snapshot, and to live_sports_updated webhook events. map_score is the kills or rounds in the map being played. The series total stays in score.Before this change, when a provider update omitted the pair, which happens about once a minute in a live game, an API response could fill the gap with an older copy, up to five minutes old. A read could then show a lower count than the read before it. For a series the provider lists in the opposite team order, the two teams’ counts could also be exchanged while the series total was level. The webhook removed map_score for that update and listed scores in changed, and the next update put the pair back.
  • The pair is kept only within one live game of a series: the same period, the same series_format, and the same series score on both sides.
  • A new game, a changed series score, or the end of the series clears it. map_score is then absent until the provider reports a pair for the new game.
  • No webhook event is sent for an update whose only difference is the missing pair.
  • After a game ends, the provider can keep the old period for several minutes. map_score stays at the last reported pair during that time, which can be short of the game’s final count.
Backward compatible. No field is added, removed, or retyped.What to change: Nothing. Code that keeps the last map_score when an event omits it still works.
Overwatch series_format and period report the best-of length, not the wins needed
GET /api/v1/games and GET /api/v1/games/{event_slug} now report an Overwatch series’ series_format as its best-of length, such as Bo5, and status.period counts maps against that length, such as 4/5. sports.live_score in a market snapshot and the live_sports_updated webhook carry the same values.Before this change, an Overwatch best-of-5 read series_format Bo3 and period 4/3. Polymarket’s Overwatch score states the maps a team needs to win (first to 3), not the maps in the series, and 0xinsider passed that number through as the length.
  • An Overwatch series that needs N map wins now reads Bo followed by 2N-1: Bo3 becomes Bo5, and Bo4 becomes Bo7. This matches the (BO5) or (BO7) in the game’s title.
  • period keeps the current map number and changes the number after the slash the same way: 5/3 becomes 5/5.
  • Every other sport and esports title keeps the values it had.
  • A series that ended in the 24 hours before this release can read the earlier values until its cached final score expires, at most 24 hours after its last map.
Breaking only for clients that converted Overwatch values themselves. No field is added or removed.What to change: If your code turned an Overwatch Bo3 into a best-of-5, remove that step. Otherwise nothing.
SDK 0.25.0 types the large_trade_inserted_v2 webhook and exports ClientResponseMeta
@0xinsider/sdk 0.25.0 types every webhook event the API delivers. WEBHOOK_EVENT_TYPES now lists large_trade_inserted_v2, and parseWebhookEvent returns a typed payload for it, for large_trades_inserted, and for trader_synced.Before this change, the list had 15 of the 16 event types in the OpenAPI document, and the typed payloads covered 13. A case on any of the three missing types did not compile, although large_trade_inserted_v2 has been available since September 23, 2026.
  • LargeTradeInsertedV2Event carries one trade in data: event_id, whale_alert_id, condition_id, trader_id, wallet, grade (null for an ungraded wallet), size_usd, shares, price, side, outcome_index, traded_at, and platform. size_usd, shares, and price are decimal strings, and the event’s created_at is the time the trade filled.
  • LargeTradesInsertedEvent and TraderSyncedEvent type the canonical spellings. WhaleTradesInsertedEvent, WhaleTraderSyncedEvent, and their data types are marked deprecated and keep working.
  • ClientResponseMeta, the type of meta on ApiEnvelope and ApiListEnvelope, is now exported, so you can name it in your own code.
  • WEBHOOK_EVENT_TYPES has 16 entries. The new name is last, so the index of every earlier entry is unchanged.
Backward compatible. Every change adds a type, an export, or a list entry, and no webhook delivery or API response changed. One effect shows at compile time: a switch on event.type that ends in a never check stops compiling until it handles the three added types.What to change: Nothing at run time. Update to SDK 0.25.0 to handle large_trade_inserted_v2 with types, and add the three cases if your switch proves it is exhaustive.
Pick of the Day expands public selection coverage
GET /api/v1/pick-of-the-day can now include selections from markets that were previously omitted.Before this change, those markets were skipped. The private scanner feed is unchanged, and 15 is the daily maximum at this release, not a promised count.Backward compatible. Request and response fields are unchanged. Already selected and historical picks keep the rules they were selected under.What to change: Nothing.
Trader, leaderboard, and trending P&L add a labeled neg-risk conversion correction
GET /api/v1/trader/{address} now returns pnl.correction when 0xinsider corrects Polymarket’s P&L for a wallet’s neg-risk conversions. The leaderboard and trending wallets return the same object as pnl_correction.Before this change, every P&L field carried Polymarket’s figure. Polymarket misbooks neg-risk conversions that combine NO shares of two or more outcomes, in both directions. It charges part of the cost to inactive placeholder outcomes and never books it as a loss, so the wallet reads too high. Its position records also leave out shares the wallet really got, such as YES shares minted by a conversion, so the wallet reads too low.
  • The object carries basis (neg_risk_conversion_v1), amount in USD (negative when Polymarket overstates the wallet, positive when it understates it), realized and net_total (Polymarket’s figures plus amount), as_of, markets_measured, and markets_excluded. Leaderboard entries omit net_total.
  • A market where shares moved in or out of the wallet by direct transfer keeps Polymarket’s figure: it is left out of amount and counted in markets_excluded, which is omitted when there is none.
  • The amount is published only once every converted market of the wallet is measured and checked for transfers. A market that has not been read yet, or whose re-read has failed three times in a row, holds it back, and the last published amount stays until the set is complete again. A sum under $1 either way publishes no correction.
  • pnl.correction_pending is true while some of the wallet’s converted markets are still being measured or checked for transfers, so the correction may change, or arrive for a wallet that has none yet. It is omitted otherwise. Right after this release most wallets read pending for a few hours while their first transfer check runs.
  • It is omitted when no correction is published. pnl.net_total, pnl.realized, realized_pnl, all_time_pnl_usd, and trader.pnl on positions and large positions keep Polymarket’s own figures.
  • Grades and the leaderboard order now use the corrected realized P&L, and the 0xinsider profile shows the corrected total with Polymarket’s figure beside it.
  • expand=trust adds trust.pnl_correction when the object is present. context.md prints the corrected Total and Realized P&L, a correction line with Polymarket’s figures, and a pending line while the correction is pending.
  • SDK 0.25.0 adds the PnlCorrection type and pnl.correction_pending. The hosted MCP leaderboard tool declares pnl_correction in its output schema.
Backward compatible. The new fields are optional and no existing field changes value. For a corrected wallet, the grade and the leaderboard rank can change.What to change: To show the total the 0xinsider profile shows, read pnl.correction.net_total when it is present and pnl.net_total otherwise, and say the figure may change while pnl.correction_pending is true. Update to SDK 0.25.0 for the typed object.
Market snapshot marks the always-null market_type and market_result fields deprecated
GET /api/v1/market/{condition_id}/snapshot now marks market.market_type and market.market_result as deprecated in the OpenAPI spec and the SDK types. Both fields are always null.Before this change, the spec described both as ordinary nullable fields, although neither has ever carried a value on a Polymarket market. market_type read a database column that nothing wrote, and that column is now removed.
  • Both keys stay in every response, with the value null.
  • To tell whether a market has closed or resolved, read market.status and market.resolved_at.
Backward compatible. The response shape and its values are unchanged.What to change: Nothing is required. If your code reads either field, stop reading it: it is always null.
Edge Hunter observations keep conflicting same-page holder rows incomplete
GET /api/v1/edge-hunter?view=observations now leaves holder coverage incomplete when one provider page contains conflicting rows for the same wallet, token, and outcome. The API retains the previously observed partial population instead of publishing one conflicting row as complete.Before this change, equal-share duplicate rows within one page could silently replace earlier price, P&L, or profile values and pass holder completion.
  • Identical duplicate rows are still counted once.
  • Across different provider pages, unchanged holdings can still retain the latest price, P&L, and profile values from the same row.
  • Changed shares still prevent completion. Multi-page completion still requires 2 complete scans with matching holdings.
Backward compatible. Response fields and the Max requirement are unchanged.What to change: Nothing. Continue reading holder_scan_complete, degradation_reasons, and coverage; a retained partial population is not a complete holder population.
Pick of the Day supersedes_pick_id is deprecated and always null
GET /api/v1/pick-of-the-day, the archive, the ledger, and the ledger entry mark supersedes_pick_id deprecated. The field is always null, and the OpenAPI document, the TypeScript SDK types, and the Pick of the Day MCP tool now say so.Before this change the documentation described supersedes_pick_id as the ID of the pick a selection replaced. No pick ever carried a value: the field has been null on every response since it was added.Backward compatible. Every response keeps the key, still null, and no other field changes.What to change: Nothing. If your code reads supersedes_pick_id, do not expect it to name a pick. Identify a pick by pick_id.
Edge Hunter observations keep their last snapshot through one missed refresh
GET /api/v1/edge-hunter?view=observations now keeps serving the last observation snapshot when one scheduled refresh misses its deadline. That snapshot is served for up to 45 seconds past its usual age limit. For the in_play cohort, this means up to 75 seconds old instead of 30.Before this change, every observation request returned 503 read_model_warming until the next refresh finished, usually for 10 to 15 seconds. On October 11 and 12 the refresh missed its deadline 2 to 13 times an hour.
  • meta.cache_age_s gives the snapshot’s age in seconds, and snapshot_as_of gives its completion time.
  • A second missed refresh in a row, or a snapshot that is missing, still returns 503 read_model_warming with Retry-After: 5.
  • The board and signals views are unchanged.
Backward compatible. The response shape is unchanged, and fewer requests return 503.What to change: Nothing. If your in_play logic needs data no older than 30 seconds, check meta.cache_age_s before you act on a response.
Market snapshot polling renews cached order-book coverage
GET /api/v1/market/{condition_id}/snapshot now renews its request for cached order-book coverage on each open-market read, at most once per minute per market. Continued polling can keep that coverage active beyond the 5-minute hold.Before this change, a hold could expire after 5 minutes even when you kept polling the snapshot. Coverage still depends on available capacity and provider data; read each returned value’s availability and freshness.Backward compatible. Response fields and authentication are unchanged.What to change: Nothing. If you want to retain requested order-book coverage, continue polling at least once a minute and handle unavailable or stale values.
Edge Hunter board quotes use verified caches without waiting for provider requests
GET /api/v1/edge-hunter?view=board now reads its quotes from verified display-price and websocket caches without waiting for provider requests. An outcome without a usable cached quote returns current_price: null.Before this change, a missing cached quote could make the board wait for a provider request. Retained quotes keep their original observation clock and existing retention limit; each quote’s availability remains explicit.Backward compatible. Quote fields were already nullable, and the response schema is unchanged.What to change: Nothing if you already handle nullable quotes. Continue reading each quote’s source and clock, and treat null as unavailable rather than as a zero price.
Edge Hunter holder completion tolerates refreshed prices on unchanged holdings
GET /api/v1/edge-hunter?view=observations now retains the latest provider economics and profile values when repeated holder rows describe the same wallet, token, outcome, and share quantity.Before this change, a price, P&L, or profile update on a repeated row could prevent holder completion even when its holding was unchanged.
  • Changed shares, inconsistent token or outcome identities, malformed provider evidence, and invalid cursors still prevent completion. The API still refuses to mark a changing or unverifiable holder population complete.
  • Remaining incomplete scans and other snapshot quality reasons stay explicit. This correction does not change admission limits, response fields, SDK/MCP package versions, or the historical archive contract.
Backward compatible. Existing fields and query behavior remain.What to change: Nothing. Continue reading holder_scan_complete, degradation_reasons, and coverage; this correction does not promise a healthy or complete snapshot.
Edge Hunter observations explain degradation and separate source coverage from page counts
GET /api/v1/edge-hunter?view=observations now returns required degradation_reasons and coverage on every observation page. Admitted incomplete holder scans also attempt bounded completion using the same provider holder population before qualification.Before this change, the shared snapshot’s degraded flag could stay true without a failure terminal in the selected category. Intentional admission limits and a short page also had no separate source, selection, and page counts.
  • Each reason names its cause and canonical sport, or null for a cause affecting the whole snapshot. Reasons remain attached to the shared all-sports generation through category, cohort, league, and market selection.
  • On sports and esports responses, coverage.input_markets, capacity_limited_markets, emitted_observations, and incomplete_holder_markets describe that whole source generation. They are measured counts, not a complete provider census. A legacy category value that cannot resolve to a sport retains its zero-work empty result; its zero counts and empty reasons do not establish the all-sports snapshot’s health.
  • selected_observations counts matching cohort and selector records before pagination. returned_observations counts this page and equals data.length.
  • Intentional capacity_limited admission does not itself set degraded, and not_configured upcoming supply is not a provider failure. Admission limits remain unchanged; pagination cannot recover excluded markets.
  • Remaining incomplete holder scans and unavailable directional evidence stay explicit. A selected funnel with no failure terminal does not establish that the whole snapshot is healthy.
  • Older cached snapshots without the new quality evidence return 503 read_model_warming until a refreshed snapshot is ready. Honor Retry-After: 5.
  • SDK 0.24.0 and MCP/CLI runtime 3.4.0 expose the same typed evidence. The SDK validates its required shape, nonnegative integer counts, and current-page count.
This endpoint does not add a historical archive.Backward compatible for HTTP readers: response fields are additive, and existing fields and selection defaults remain. The new SDK requires the updated observation envelope and rejects responses missing its quality evidence.What to change: Update to SDK 0.24.0 or MCP 3.4.0, read the reasons alongside degraded, and compare source, selected, and returned counts separately. Keep incomplete holder counts and dollar totals scoped to the observed subset; sharp_pct is that subset’s ratio, not a full-population percentage lower bound. Restart pagination when its snapshot expires.
Edge Hunter board adds token IDs, its ranking clock, and aggregate category evidence
GET /api/v1/edge-hunter now exposes token IDs and existing ranking evidence directly in the default board. The website’s Max board and the API use the same full projection; the API remains Max-only.Before this change, board quotes omitted their token IDs, and full board signals omitted the ranking timestamp and category evidence already available in ranked records. You had to make another request to resolve a board outcome’s token ID or read the richer ranked view.
  • Each outcomes[] item adds required nullable token_id and stays in provider order.
  • Each full signal adds required nullable backed token_id, frozen ranked_at, and the existing aggregate category_skill object. The ranking clock stays attached to the served row when quotes refresh.
  • Category status, coverage, and nullable measurements describe evidence availability. They do not change market admission, row order, grade defaults, or backing measurements.
  • The website’s horizon maps to API horizon_hours. Cards and Table are layouts of view=board; the advanced views remain available for the former feed capabilities.
  • All selector, grade, limit, pagination, quote, and warming behavior is retained. This change does not introduce another cohort or ranking model.
  • SDK 0.23.0 adds the board evidence declarations and corrects 3 nullable reference types: outcomes[].current_price, signal.current_price, and rows[].signal. The HTTP fields were already nullable; generated types now reflect that contract. MCP runtime 3.3.0 exposes the same board evidence.
Backward compatible for HTTP readers. These response fields are additive; the SDK declaration correction can require null guards in code that treated nullable quotes or signal as always present.What to change: Update to SDK 0.23.0 or MCP 3.3.0 for the new typed board evidence. Use returned token IDs rather than resolving them through another snapshot request, handle null token IDs, quotes, and signal, and keep ranking, category, and quote clocks separate. Existing HTTP readers can continue using the board fields they already consume.
Edge Hunter adds shared market, sport, esports, and league selection to every view
GET /api/v1/edge-hunter now accepts shared selectors in its board, signals, and observation views. Every view still requires Max, and the 4 retired sports endpoints stay retired.Before this change, the board could only narrow its kickoff horizon, and advanced views could select a canonical category. A category alias such as NFL still means the whole Football bucket; league selection now has its own identity filter.
  • kind selects sports or esports.
  • The sports, leagues, market_types, condition_ids, event_slugs, and series_slugs lists accept repeated parameters or comma-separated values. Each list is bounded at 100 values before deduplication; values combine with OR inside one list and AND across axes. Sports, kind, and leagues ignore case; event, series, and market-type identities match exact case.
  • Each row adds nullable market_context, with nullable league, series, market-type, and metadata_updated_at fields when the object is present. The clock dates 0xinsider’s stored metadata update, not a provider observation. Copy these identities rather than inferring them from a title or slug.
  • League identity also uses recognized provider season series when explicit league metadata is absent; the initial selector rollout left these known identities null. Explicit sports league identities take precedence, and a series must agree with the canonical sport. Recognized esports game series identify the game, including cs2 for Counter-Strike.
  • Selected responses echo normalized requested axes under top-level selection. Cursors and conditional validators bind the selected representation. Unavailable selection metadata returns 503 read_model_warming for selected reads; missing individual identities remain unknown and cannot match that selected axis.
  • The league identity correction invalidates existing selected advanced cursors. A valid cursor whose selection or filters no longer match returns 400 with error.reason: cursor_expired; restart from page one. Malformed or invalidly signed cursors keep a generic 400 bad_request.
  • The board also accepts category, min_grade=S|A|B, and limit. Defaults remain B, 30 rows, and a 48-hour horizon; board limits clamp to 1 to 30. The advanced views keep their existing limits, cohort requirements, grade restrictions, and horizon behavior.
  • All three API views require ready snapshots and return 503 read_model_warming with Retry-After: 5 while unavailable. The observation funnel still accounts for its source/category scope rather than selected league, type, or ID counts.
  • SDK 0.22.0 and MCP/CLI runtime 3.2.0 support shared selector arrays. Their selected reads use strict query validation so an unsupported selector cannot silently become an unfiltered read. The official agent plugin 1.2.0 teaches identity discovery and selected views.
  • The hosted sandbox fixes mismatched example clocks in the board, keeping its horizon consistent with its fictional rows. Hosted MCP now accepts the same shared selector arrays as sandbox REST.
Backward compatible. Existing defaults and response envelopes remain; row metadata is additive.What to change: Update to SDK 0.22.0 or MCP 3.2.0 to use the new typed selectors, and refresh the official agent plugin to 1.2.0 if you use it. Read provider identities from market_context, use game coverage for discovery, and retain the same normalized selection across cursor pages and conditional reads. Handle null metadata and warming responses.Start a fresh advanced cursor sequence for selected reads from the initial rollout. Keep the returned ETags when you revalidate cached advanced responses.
Edge Hunter adds complete ranked signals, observation cohorts, filters, and pagination
GET /api/v1/edge-hunter now includes the former feeds’ complete capabilities under explicit views. The default quoted board stays available with no view parameter. Every view still requires Max, and all 4 old sports endpoints remain retired with 410 endpoint_retired.
  • view=signals returns ranked records, nullable backed token_id, category-skill evidence, and category, min_grade, horizon_hours, limit, and cursor filters. Its horizon defaults to 12 hours; page size defaults to 20 and clamps to 1 to 100. The S/A/B floor requires a holder at the selected grade or better on the backed side without removing other holders from the pile.
  • view=observations requires cohort=wider_holder, in_play, or emerging_pile, and supports category filtering and cursor pagination. It restores verified token IDs, midpoint price marks, observation and holder clocks, provider and directional status, scan completeness, snapshot_as_of, degraded, and per-sport funnel evidence.
  • Both advanced responses use object: "list", add view, and return rows in data. They support ETag and If-None-Match; a match returns 304 with no body. Both views require private revalidation. New cursors bind the view, filters, and snapshot; start a fresh walk when migrating.
  • Signals and observations read warmed snapshots. A source that cannot serve ready evidence returns 503 with error.reason: read_model_warming; honor Retry-After rather than interpreting this as an empty complete result. In-play evidence fails closed without fresh provider-live, holder, and directional reads.
  • SDK 0.21.0 adds literal-view result types, edgeHunter.signals(), edgeHunter.observations(), advanced-only getConditional(), and shared list/pagination support. MCP and CLI runtime 3.1.0 expose the same views through get_edge_hunter and getEdgeHunter.
  • The official agent plugin’s polymarket-sharp-money skill, version 1.1.0, teaches the advanced views and Max requirement alongside the quoted board.
  • Generated error types now include endpoint_retired, and Max guidance names Edge Hunter. Retired routes are removed from the OpenAPI introduction’s conditional GET list.
backed_price is an aggregate market midpoint at observed_at, not a wallet’s executed entry price. Quote, ranking, observation, and holder clocks remain separate; volume is shares. Emerging pile overlaps wider holder and is not holder-arrival history.Compatibility: Valid default-board requests and their data.rows response are unchanged. The advanced views are additive. A known parameter belonging to another view now returns 400; select the matching view before sending its filters.What to change: Update to SDK 0.21.0 or MCP 3.1.0. Migrate former ranked-feed calls to view=signals and former observation calls to view=observations with the required cohort. Read list rows from data, retain the page and evidence fields, and replace old cursors. Stop retrying the retired paths.