Skip to content
Patch notes

Patch 2026.09.22

FixedPlatform

The Pick of the Day record is now stated at a flat $1,000 a pick instead of $100, for every pick ever published. The TypeScript SDK gains a keyless sandbox client, and its batch trader lookup now sends the required request shape; remote MCP acknowledges supported notifications without a JSON-RPC reply and tells a client on GET that it offers no server-to-client stream, so clients stop reconnecting every second. Every API response carries one request ID in the header and the body, and every API failure answers the error envelope. GET /api/v1/events/feed/since no longer skips a large trade that lands out of order. Pay as you go gains a 1,000,000 request monthly ceiling. A report is final only once it is built after its period ends.

Pick of the Day

  • The public record now states every result at a flat $1,000 a pick instead of $100, for every pick ever published: a win returns $1,000 divided by the frozen price, a loss forfeits the $1,000. Profit, total staked and each pick's payout read ten times larger; win rate, ROI and units are the same numbers as before. The verifiable ledger at github.com/0xinsider/picks recomputes on the same basis.Was$100 a picknow$1,000 a pick
  • RemovedPick of the Day cards no longer show the redundant Why explanation; the side, price, result and holders remain on every current and historical pick.

Pages

  • RemovedThe Earnings markets page is retired: /earnings now sends you to the Polymarket hub. The Earnings category stays in the terminal and in category P&L.

API

  • NewGET /api/v1/pick-of-the-day and GET /api/v1/pick-of-the-day/archive add stake_usd (1000) and return_usd beside return_per_100 on every priced pick, and hit_rate adds stake_usd; payout_display, profit_display, net_profit_usd and staked_usd are now stated on the $1,000 stake, while return_per_100, unit_score, roi_pct and the hit rate are unchanged. Additive: a client that reads return_per_100 needs no change (@0xinsider/sdk 0.2.6).
  • NewThe TypeScript SDK's OxinsiderApiClient.sandbox() calls the API sandbox at https://0xinsider.com/sandbox/api/v1 with no key, lifts its X-Oxi-Sandbox header to meta.sandbox, turns sandbox_status into the same typed error production would throw, and refuses a live key; a baseUrl with a path now keeps that path (@0xinsider/sdk 0.2.2).
  • NewEvery /api/v1 response adds the browser-readable Server-Timing header with its processing time in milliseconds; existing clients need no changes.
  • NewGET /api/v1/me adds credential_status and entitlement.paid_data_access / entitlement.recovery_action, and a valid credential with lapsed paid access can read GET /api/v1/usage to inspect its budget. Additive: paid-data routes still return 402 subscription_required, and existing clients can ignore the new fields.
  • NewV1 query handling stays compatible by default while successful responses expose X-Query-Ignored and X-Effective-Query; clients can send X-Query-Validation: strict to receive 400 with error.reason=unknown_query_parameter for an unsupported name. Additive: existing callers need no change.
  • GET /api/v1/leaderboard/trending binds its cursor to the original limit, window and ranked board; a changed board or pagination scope returns 400 with error.reason=cursor_expired, and legacy page-only cursors restart from page one.WasPage-only cursornowBoard- and scope-bound cursor
  • NewGET /api/v1/insider-radar accepts mode=stable for a bounded walk over one published scoring generation; its cursor carries the limit and filters, and a republished score set returns 400 with error.reason=cursor_expired so clients restart from the first page. mode=live remains the default.
  • NewThe Go SDK's OpenStream reads GET /api/v1/stream frame by frame with a 1 MiB ceiling per frame and closes on context cancel, fails visibly with StreamProtocolError on a frame that is not JSON, not an envelope, has no usable sequence or is a malformed resync marker, and a client from New refuses the generated GetStreamWithResponse, which read the stream to its end and never returned (github.com/0xinsider/0xinsider-go 0.2.0).
  • NewThe Python and Go SDKs send an API key or OAuth token over https:// only, or over http:// to localhost, 127.0.0.1 or [::1] for a backend you run yourself; a base URL that would send it anywhere else raises InsecureTransportError before any request, and a redirect to plain http:// never carries the credential (0xinsider 0.2.0 on PyPI, github.com/0xinsider/0xinsider-go 0.2.0).
  • NewThe Python and Go SDKs now carry every one of the 64 API operations, adding POST /api/v1/agents/register, GET /api/v1/trader/{address}/categories, GET /api/v1/pick-of-the-day/ledger, GET /api/v1/market/{condition_id}/holders, POST /api/v1/webhooks/{id}/deliveries/{delivery_id}/redeliver, GET /api/v1/market/{condition_id}/context.md and GET /api/v1/me, and each release states the OpenAPI document it was generated from (OPENAPI_SHA256 and APP_COMMIT in Python, OpenAPISHA256 and AppCommit in Go; 0xinsider 0.2.0 on PyPI, github.com/0xinsider/0xinsider-go 0.2.0).
  • NewThe agent discovery catalog also answers at /.well-known/ard.json, the Agentic Resource Discovery path, and now lists both MCP servers and all seven skills (the two under /.well-known/agent-skills/ and the five in the Agent Plugin) with sample queries a registry can search on; the OpenAPI document, developers.json, the plugin manifest and AGENTS.md are linked from the entries, and every page's <head> names the catalog with rel="ard".
  • NewBuilder webhooks add staged signing-secret rotation through POST /api/v1/webhooks/{id}/rotate-secret/prepare, /activate, and /retire: deploy the prepared secret before activation, accept both signatures for one hour, then retire the previous secret. The existing immediate rotation endpoint remains available for emergency replacement; existing webhook clients continue to work.

Bug Fixes

API

  • The Python SDK's download_trader_export now follows GET /api/v1/trader/{address}/export/download's redirect to the finished file and returns a streaming Download with the file's content type, size, filename and a SHA-256 of what save wrote, sending the API key to the API only and never to the file host; before, the redirect was raised as an error (0xinsider 0.2.0 on PyPI).
  • The TypeScript SDK's batchGetTraders now sends the traders array POST /api/v1/traders/batch requires and accepts expand (strategy, categories, quant_metrics, trust) for every item, so the call answers with the ordered batch instead of a traders missing error (@0xinsider/sdk 0.2.1).
  • GET /api/v1/reports and the daily, weekly and monthly routes call a report final only once it was built after the period ended plus 2 hours 5 minutes, so a body built before the close no longer counts as final; until then snapshot.status stays rolling with the new snapshot.period_closed and snapshot.final_after saying when it will be, snapshot.source_read_started_at says when the body was read, and snapshot.mutable_until names the date the final body can first be built.WasFinal at the UTC closenowFinal 2 h 5 min after the close
  • Weekly report requests using an ISO week remain durable canonical snapshots; an explicit from/to range returns the exact requested UTC range for up to 31 inclusive days with snapshot.storage=ephemeral, and a wider range returns 400 invalid_query.
  • The TypeScript SDK's streamFeedResilient no longer reconnects at once when a 429 asks for a wait longer than about 24.8 days; a Retry-After past maxRetryAfterMs (60 s by default) now throws StreamRetryDeferredError with retryAt and lastSeq for you to schedule, and both the stream and REST retries read an HTTP-date Retry-After as well as seconds (@0xinsider/sdk 0.2.3).
  • The TypeScript SDK's paginate, paginatePages and collect now throw PaginationError on a page that says has_more: true without a next_cursor or repeats a cursor already requested, instead of ending as if the list were complete or requesting the same page again; maxPages is checked before the first request, and a progress option reports whether a walk stopped at maxPages or at the end of the list, with the cursor to continue from (@0xinsider/sdk 0.2.4).
  • The TypeScript SDK's streamFeed and streamFeedResilient now throw StreamProtocolError on a GET /api/v1/stream frame that is not JSON, not an envelope, has no usable sequence, or is a malformed resync marker, on a successful response that is not text/event-stream, and on a frame past maxFrameBytes (1 MiB by default), instead of skipping the frame and moving the resume cursor past it; the error names lastSeq and frameId, and the reconnect loop does not retry it (@0xinsider/sdk 0.2.5).
  • The TypeScript SDK now retries a failed write only on the five operations that honour Idempotency-Key (createWebhook, updateWebhook, deleteWebhook, rotateWebhookSecret, redeliverWebhookDelivery) and only with a key, refuses idempotencyKey on any other operation before sending, and retries the read-only POST /api/v1/traders/batch and POST /api/v1/markets/intel/batch like a GET; a key on verifyWebhook or submitTraderExport used to make the SDK retry a request the API would repeat (@0xinsider/sdk 0.2.6).
  • The TypeScript SDK's verifySignature now throws on a toleranceSeconds that is NaN, infinite or negative instead of accepting a correctly signed webhook delivery of any age; the 300-second default and the boundary (exactly 300 seconds passes) are unchanged (@0xinsider/sdk 0.2.7).
  • Webhook delivery logs now include next_attempt_at and nullable retry_schedule_reason, so receivers can see whether the next attempt follows a bounded Retry-After, a transient failure, a permanent or auth response, a manual redelivery, or a configuration change.
  • POST /api/v1/mcp answers supported notifications with HTTP 202 and no body; a request with an ID still receives one matching JSON-RPC reply.Was`id: null` replynowEmpty HTTP 202
  • A remote MCP tools/call on POST /api/v1/mcp whose arguments fall outside the tool's advertised inputSchema (a non-object, an unknown key, a wrong type, a number out of range, a value outside an enum, or both of two exclusive arguments) now answers a tool result with isError naming the field, instead of running with the arguments that fit.
  • GET /api/v1/mcp with a credential now answers HTTP 405 with Allow: POST, the MCP answer for a server that offers no server-to-client stream, so an MCP client connects once and stops reconnecting every second; the TypeScript SDK drops the openMcpEventStream row from its operation table (@0xinsider/sdk 0.2.4).Was200, stream closed at oncenow405, `Allow: POST`
  • The search_markets MCP tool, on POST /api/v1/mcp and in @0xinsider/mcp, now takes cursor and answers data, has_more and next_cursor, so a search with more than one page can be read to the end; the stdio tool answered a bare array with no cursor before.WasFirst page onlynowEvery page by cursor
  • Pay as you go now stops at 1,000,000 API requests a month: past it an account answers 429 monthly_quota_exceeded until the month resets, the same as an account without pay as you go does at 250,000, from 1 October 2026, and one email says so when it happens; GET /api/v1/usage monthly_quota gains ceiling, the number that binds the account.WasNo upper boundnow1,000,000 a month
  • Every /api/v1 response now carries the same request ID in the X-Request-Id header and in meta.request_id, and that one ID is what support and usage records are keyed by; before, the header and the body carried two different IDs. The header now also appears on 304, 408 and CORS preflight responses. A client-supplied X-Request-Id request header is never echoed.WasTwo IDs per responsenowOne ID per response
  • Every /api/v1 failure now answers the standard error envelope, including a request that never reached a handler: a body that is not JSON or misses a required field (400, error.reason invalid_body, error.param naming the field), a query or path value that does not parse (400, invalid_query or invalid_path), a body without Content-Type: application/json (415, unsupported_media_type), a body over 1 MiB (413, payload_too_large), a method the path does not serve (405, method_not_allowed), and the 30-second timeout (408, error.code request_timeout, with Retry-After on GET). Before, these answered plain text or an empty body with no meta.request_id. The TypeScript SDK throws ServerTimeoutError on a 408 and retries it like a 503 (@0xinsider/sdk 0.2.5).WasPlain text or empty bodynowError envelope with code, reason, param
  • A 429 from the per-address budget on /api/v1 (the 1,200 requests a minute every caller behind one IP shares, counted before authentication) now answers the standard error envelope with error.code rate_limited, error.reason ip_rate_limited, error.retry_at and meta.request_id, keeping Retry-After and the RateLimit-* headers; a throttled address answers the same envelope with error.reason ip_throttled. Before, both answered a flat body with no request ID and no retry_at, which the API reference had never described. The TypeScript SDK's API_ERROR_REASONS carries both values (@0xinsider/sdk 0.2.6).WasFlat body, no request IDnowError envelope with reason and retry_at
  • GET /api/v1/events/feed/since now delivers every large trade after your cursor, including one recorded out of order that a stored cursor used to skip for good; meta.replay.ordering reads commit_visibility_then_id_asc, data.sequence can step backwards, the new meta.replay.pending_beyond_horizon says when a caught-up page still has trades on the way, and cursors you already hold keep working.Waswhale_alerts_id_ascnowcommit_visibility_then_id_asc
  • GET /api/v1/markets/sharp-money-flows and its deprecated smart-money-flows alias now return cursor_expired when the effective filters or collection revision changes, so clients restart from the first page instead of silently walking a different result set; cursors issued before this change receive the same recovery response.
  • /api/v1/mcp now answers 400 to an MCP-Protocol-Version header naming a revision it does not serve (it serves 2025-11-25, 2025-06-18, 2025-03-26 and 2024-11-05; no header still works), a browser's preflight may send the header, and https://0xinsider.com/api/v1/mcp echoes the Mcp-Session-Id a client sends instead of minting a new one.WasAny header value acceptednowUnsupported value answers 400
  • Every MCP tool result, on POST /api/v1/mcp and in @0xinsider/mcp, now carries the same meta the REST route returns (request_id, cached, cost, and a route's source, completeness, ranking_source or directional_source) beside the payload, and a failed tool call carries the REST error fields (code, reason, param, doc_url, retry_at) plus retry_after_seconds, request_id and status under structuredContent.error beside its text.
  • An open GET /api/v1/stream connection now ends within 40 seconds of its API key being revoked, expiring or being rotated, or of its account being deleted, locked or losing its subscription, with one final event: error frame whose error.code names the cause (invalid_api_key, subscription_required, forbidden, account_locked or insufficient_scope) and retry: false; a stream whose key cannot be confirmed for 90 seconds ends with database_unavailable and retry: true, and a reconnect after error.retry_at resumes from the frame's id.
  • GET /api/v1/market/{condition_id}/candles now URL-decodes its recognized time bounds, keeps to inclusive, and returns 400 when from is after to.