Skip to content
Patch notes

Patch 2026.09.23

All releases
FixedPlatform

Pay as you go stays available while a payment retry is in progress, so API access and usage reporting agree. The live_sports_updated webhook event starts delivering a bounded per-game pulse. The API sandbox answers four operations it used to refuse, so an integration can be written against every documented operation but the live event stream without an account.

API

  • GET /api/v1/large-trades, GET /api/v1/large-trades/{id}, GET /api/v1/large-trades/history, their /api/v1/whale-trades aliases and expand=trade on GET /api/v1/events/feed/since now return review_score and recorded_review_score beside signal_score and recorded_signal_score, with the same values. The older keys stay on the wire and are marked deprecated. The SDK types the new keys (@0xinsider/sdk 0.10.0), and the MCP package adds the market_review prompt, with trading_signals kept as its alias (@0xinsider/mcp 2.5.0). Additive: existing calls are unchanged.
  • NewGET /api/v1/market/{condition_id}/intel and POST /api/v1/markets/intel/batch now return sharp_money.oldest_snapshot_as_of, and the same field on the deprecated smart_money alias: the time of the oldest position behind top_positions, so you can tell how current that list is. It is null when the list is empty. Additive (@0xinsider/sdk 0.9.0).
  • The API sandbox now matches the live API in six more places: POST /api/v1/mcp refuses a malformed message with a JSON-RPC error object and X-Mcp-Error-Code, answers an unknown method with -32601 and an id-less ping or notification with 202; min_grade visibly drops lower-graded rows, and GET /api/v1/market/{condition_id}/holders lists S, A and B holders only; a trader posted to POST /api/v1/traders/batch carries its own username or none, and expand: null there gets 400; the single-market routes describe the condition_id in their path; and GET /api/v1/webhooks/events gives every event its real description and payload shape.
  • The API sandbox now answers the way the live API does: a body over 1 MiB gets 413; a null the schema does not allow, a string past its length limit, a wrong const, a from that is not an RFC 3339 timestamp or more than 25 wallet values across repeats gets 400; an unknown expand value is ignored; a mkt_, wt_ or rf_ id in POST /api/v1/traders/batch is a per-item error; and responses carry the live id formats (pos_, wt_, rf_, pe_, mkt_), the posted condition_id in POST /api/v1/markets/intel/batch, only the trader sections expand asks for, all eleven events in GET /api/v1/webhooks/events, and an X-Effective-Query that names only the filters applied.
  • GET /api/v1/trader/{address} now includes forecast_score (0-100) and forecast_evidence (0-1) beside the grade when forecasting data is available; unavailable values are omitted.
  • NewGET /api/v1/games and GET /api/v1/games/{event_slug} return one game per row: both sides with their provider ids and live scores, the UTC kickoff, the provider's status, the esports series format, and every linked Polymarket market with its condition_id and outcome token ids. Filter by sport, league, status, starts_after and starts_before; each page carries the sports and leagues covered. Draws, postponements and cancellations each keep their own status.state (@0xinsider/sdk 0.7.0).
  • The TypeScript SDK's mcp() now sends initialize, ping, tools/list and notifications without an API key, as the MCP server allows, and always sends jsonrpc: "2.0"; downloadTraderExport keeps your signal and downloadTimeoutMs active until the file body is read. npx -y @0xinsider/mcp init now writes through a config that is a dangling symlink instead of replacing it, and merges its change into ~/.claude.json again if Claude Code saved the file meanwhile.
  • NewThe export job resource (POST /api/v1/trader/{address}/export, GET .../export/status) now says what a client should do next: terminal, next_action, poll_after_s, the lifecycle timestamps, expires_at, the file's data_as_of and, once ready, its artifact; a job past its retention window reads expired, its download answers 410 with error.reason export_expired, and fresh=true skips reusing an older file. Every field is additive.
  • When GET /api/v1/stream ends with an event: error frame (key revoked, account lapsed, credential store unavailable), the TypeScript SDK now throws the typed error it carries, such as SubscriptionRequiredError, instead of delivering the frame as a feed event and ending quietly. The frame never reaches onEvent or moves the cursor, and retry: false stops streamFeedResilient from reconnecting.
  • MCP tools now match their routes: the stdio get_sports_edge_signals returns the route's meta (including directional_source), and get_leaderboard lists the ten strategy values on both the stdio and remote servers, so an unknown strategy is refused by the tool schema instead of the route.
  • NewMCP adds list_games and get_game, so an agent reads the fixture list directly instead of assembling a game from market searches and team names. They call GET /api/v1/games and GET /api/v1/games/{event_slug}, take the same arguments, and return the same page on both the remote and stdio servers, including the coverage that says which sports are served (@0xinsider/mcp 2.4.0).
  • In the TypeScript SDK, call, list, text, paginatePages, paginate and collect now require the options argument for an operation with path parameters or a request body, so client.call("createWebhook") is a compile error instead of a request the API refuses. Calls that already pass their options are unchanged.
  • The TypeScript SDK's streamFeed now holds every frame to maxFrameBytes, including one that arrives with its blank-line delimiter in the same chunk: an oversized frame throws StreamProtocolError (frame_too_large) before it is parsed, delivered or moves cursor.seq. Frames under the limit are unchanged.
  • In the TypeScript SDK, error.reason now carries every documented reason the API sends: subscription_inactive on SubscriptionRequiredError, monthly_quota_exceeded, ip_rate_limited and ip_throttled on RateLimitedError, and invalid_body, payload_too_large and the other request reasons on BadRequestError. Twelve of the 24 read null before. An unrecognized reason still reads null and stays on error.error.reason.
  • GET /api/v1/market/{condition_id}/holders answers 200 with an empty holders list and zero totals for a market no S, A or B wallet holds; it answered 503 with Retry-After, a retry that could never succeed.Was503 Retry-Afternow200, empty roster
  • Pay as you go remains available while a payment retry is in progress, and GET /api/keys/usage reports it as available; accounts that have canceled or exhausted payment retries remain refused past the included quota.
  • Pre-game sides get canonical paths: GET /api/v1/sports/pre-game-sides and GET /api/v1/sports/pre-game-side-observations, with the PreGameSide and PreGameSideObservation schemas. Every row now carries side, ranked_at, backing_score and side_share beside the piled_side, signal_created_at, conviction_score and smart_score keys, which keep the same values. The /api/v1/sports-edge-signals and /api/v1/sports-edge-observations paths stay live as deprecated aliases and answer with Deprecation and successor Link headers. The SDK adds listPreGameSides, listPreGameSideObservations and listPreGameSideObservationsConditional (@0xinsider/sdk 0.8.0), and MCP adds get_pre_game_sides and get_pre_game_side_observations (@0xinsider/mcp 2.3.0). Additive: existing calls are unchanged.
  • Large trades get canonical paths: GET /api/v1/large-trades, /api/v1/large-trades/{id}, /api/v1/large-trades/history, and the two counterparties reads under /api/v1/large-trades/{id}, with the LargeTrade schema. Responses that named whale fields now carry the large spelling beside them: top_large_trades, total_large_trades and total_large_trade_volume on reports, rep_large_trades, large_trade_count, large_trade_signal and the other large_trade_* market fields on GET /api/v1/markets/explore, and large_trades in platform capabilities. The /api/v1/whale-trades paths and every whale field stay live as deprecated aliases with the same values. The SDK adds listLargeTrades, getLargeTrade and listLargeTradeHistory (@0xinsider/sdk 0.6.0), MCP adds get_large_trades, get_large_trade and get_large_trades_history, and the CLI adds large-trades list (@0xinsider/mcp 2.2.0). Additive: existing calls are unchanged.
  • market_volume_share on every large trade from GET /api/v1/whale-trades, /whale-trades/history, /whale-trades/{id} and the replay's expand=trade now always reads between 0 and 1, measured against a market volume figure recorded no earlier than the trade, and is absent when no such figure is available. It previously read above 1 on 412 of 3,086 trades, the highest at 18,358.WasUp to 18,358now0 to 1
  • V1 query diagnostics now decode + as a space in X-Effective-Query, and strict validation rejects an unknown name even when its percent escape is incomplete; existing callers need no change.
  • The live_sports_updated webhook event now delivers. Subscribe to it on POST /api/v1/webhooks and every live game sends a bounded pulse when its scores, status, period or live/ended state moves: at most one delivery per game per 20 seconds, with a live or ended transition never held back and the game clock alone never firing one. data carries event_slug, game_id, league, version, changed, observed_at, published_at, status, period, clock, live, ended, scores, series_format and snapshot_url. It needs no Pro subscription, and GET /api/v1/webhooks/events now lists it as active (@0xinsider/sdk 0.5.1 types the payload).WasSubscribable, never deliverednowDelivered as a per-game pulse
  • The sandbox at https://0xinsider.com/sandbox/api/v1 answers GET /api/v1/trader/{address}/context.md and GET /api/v1/market/{condition_id}/context.md with a Markdown document, and GET /api/v1/trader/{address}/export/download with its documented 302 to a sample export file. All three answered 400 before.
  • GET /api/v1/mcp on the sandbox answers 405 with Allow: POST, the same as the live API, and the documented body for that answer is now the JSON-RPC error the live API sends rather than the REST error envelope.
  • GET /api/v1/stream is now named as the one operation the sandbox does not answer, in the OpenAPI document, the registration response and the SDK.
  • A Polymarket fill now has to be at least 0.1% of its market's traded volume to count as a large trade, on top of the $10,000 floor ($1,000 in earnings markets). The same rule decides the live feed and GET /api/v1/whale-trades. Over the 14 days before it shipped it would have left out 351 of 6,499 fills, every one of them in a politics or geopolitics market large enough that $10,000 was rounding error. Rows stored before 2026-09-23 are unchanged.Was$10,000now$10,000 and 0.1% of the market
  • The API sandbox now answers initialize on POST /api/v1/mcp the way the live API does: serverInfo, capabilities, instructions and a protocolVersion negotiated against the revisions the live server supports, with Mcp-Session-Id on the answer. It answered the endpoint's tools/list example before. A MCP-Protocol-Version header naming a revision the live API does not serve now answers 400 with -32600 there too.WasA tools/list examplenowThe live handshake

Reports

  • The daily reports calendar now shades the last day of the month for viewers east of UTC. It was left blank, as if nothing had traded that day.

Market pages

  • The Holders count on a market page and on a game page's holders rail now reads 100+ for a side with more holders than the 100 the page ranks, and says the count covers the 100 biggest holders on each side. It read 100, which made a market with thousands of holders look like a market with exactly 100.Was100now100+

Research

  • NewCan you use 0xinsider for Kalshi or DraftKings? now carries a dated addendum scoring its 81 captured games against their results. All three venues beat the base rate by a wide margin and the interval on every pairwise difference spans zero, so the study still names no venue as more accurate, and it now says so with the games played rather than before them.