> ## 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.

# API changelog

> Externally visible changes to the 0xinsider REST API.

This changelog tracks externally visible REST API changes only. Documentation-only edits are intentionally excluded.

<Update label="July 14, 2026" description="Observation-only wider-holder and in-play sports cohorts">
  Added [`GET /api/v1/sports-edge-observations`](/api-reference/endpoint/get-sports-edge-observations), an Insider-tier evidence endpoint for sports opportunities that do not enter the funded Sports Edge slate.

  Choose one required `cohort`: `wider_holder` measures pre-game markets with current graded-holder consensus even when no recent graded whale flow exists, while `in_play` measures only provider-confirmed live games with fresh holder and directional evidence. Provider `event_status` is authoritative for in-play classification when present (`Live` and `Paused` are in progress; `Ended` is not), with the legacy score overlay used only when that field is absent. A stale or unavailable provider live-board snapshot also fails `in_play` closed. Every row has `observation_only: true`, provider and holder freshness fields, and an explicit directional status. The response includes a per-sport funnel that accounts for every input as an emitted observation or a terminal exclusion reason. `capacity_limited` records intentional bounded admission and does not by itself mark the snapshot degraded. Directional degradation is cohort-specific: `wider_holder` can emit a row with `directional_status: "unavailable"`, while `in_play` fails that candidate closed under `in_play_directional_unavailable`.

  Omit `category` to evaluate all 14 observation sports. Board reads use bounded fair waves, and cold holder admission gives each represented canonical sport a first-candidate attempt before any sport repeats; terminal gates can still leave a sport with no emitted row. All category scopes share one global observation provider-work admission, so independent cache keys cannot multiply concurrent provider fan-out. That registry includes **Table Tennis** and **Pickleball**, classified from provider-confirmed tags and kept separate from Tennis. The `table-tennis`, `table tennis`, and `pickleball` filters resolve through the canonical taxonomy. Those two sports remain outside the 12-sport funded projection.

  Every `200` response includes required top-level `degraded: boolean`, the snapshot-wide operational or unknown-completeness verdict. A healthy `wider_holder` request can reuse a snapshot for about 180 seconds; `in_play` never serves one older than about 30 seconds. Conditional reads use a weak semantic `ETag` over stable page content, including `next_cursor` and excluding request-specific `meta`. Malformed typed query values return the standard JSON `400 bad_request` envelope. Refresh or global-admission contention, or the route's compute deadline elapsing before a usable cache, universe, or exact raw funded-slate membership result exists, returns `503` with `error.reason: "read_model_warming"`; later operational failures are represented in a degraded `200` funnel where possible. The public API's outer 30-second transport timeout remains an empty-body `408`, so clients must check the status before parsing JSON. It does not change or feed [`GET /api/v1/sports-edge-signals`](/api-reference/endpoint/get-sports-edge-signals), Pick of the Day, or any order executor. Promotion remains closed until a separate review pre-registers and then satisfies sample-size, independent-event, fee-inclusive-return, uncertainty, and unknown-coverage thresholds.
</Update>

<Update label="July 13, 2026" description="Sports Edge can surface Golf, Formula 1, NBA Summer League, CFL and Boxing">
  [`GET /api/v1/sports-edge-signals`](/api-reference/endpoint/get-sports-edge-signals) and [`GET /api/v1/pick-of-the-day`](/api-reference/endpoint/get-pick-of-the-day) can now surface eligible markets for **Golf**, **Formula 1** and NASCAR, **NBA Summer League**, **CFL**, and **Boxing**.

  Polymarket sends only generic sports metadata for some of these markets. 0xinsider now classifies the provider tags it actually receives - including `pga`, `pga-tour`, `formula1`, `nba-summer-league`, and `cfl` - before applying the existing smart-money, calibration, liquidity, and kickoff gates. `Racing` and `Boxing` are now admitted canonical buckets.

  **Correction:** the earlier version of this entry also named Table Tennis and Pickleball. The final funded release did not admit either sport. They are registered for observation-only evaluation through the endpoint added July 14, and do not feed funded signals or Pick of the Day.

  No request or response shape changed, and no existing category was renamed. For the funded taxonomy changes in this July 13 release, open markets can adopt the corrected category on a provider refresh; historical rows require a controlled refold and are not implied to have reclassified automatically.
</Update>

<Update label="July 6, 2026" description="Sports Edge Signals: ranked pre-game sports markets where graded smart money is piled">
  Added [`GET /api/v1/sports-edge-signals`](/api-reference/endpoint/get-sports-edge-signals) - the ranked list of upcoming pre-game sports markets (moneyline and props) where graded (S/A/B) smart money is piled on one side, computed server-side in one call.

  Each signal returns the piled side and its CLOB `token_id`, the pile's grade distribution (`s_count`/`a_count`/`b_count`), dollar concentration (`sharp_pct`, `backed_sharp_usd`), the market's `game_start_time` (kickoff), and a grade-weighted `conviction_score`. Ranking is grade-distribution driven - a market with more top-grade (S/A) traders on the piled side ranks higher - and roughly-50/50 markets with no clear pile are excluded. Bearer + insider tier, ETag-cached, cursor-paginated with a snapshot-pinned cursor.
</Update>

<Update label="July 5, 2026" description="Pick of the Day returns 404 outside today's pick, and adds a game_started field">
  Two changes to [`GET /api/v1/pick-of-the-day`](/api-reference/endpoint/get-pick-of-the-day):

  * **New field `game_started`** (boolean): true once the backed game's kickoff has passed, so the snapshotted pre-game price is no longer actionable. Absent for a legacy pick with no stored kickoff (treat as not-started). Additive and optional - existing clients are unaffected. Separately, the `is_locked` description was corrected: it is a pre-release embargo flag (effectively always false on a served pick), not a "kicked off" signal - use `game_started` for kickoff.
  * **Behavior change (non-breaking):** the endpoint now returns `404` when today has no published pick yet, instead of serving the most recent prior day's (often already-settled) pick. The response shape is unchanged and `404` was already a documented response; this conforms the endpoint to its "today's Pick of the Day" contract so an automated consumer never acts on a finished game. Prior picks stay available through the archive endpoint.
</Update>

<Update label="July 4, 2026" description="Sandbox / test-mode API keys removed; a single live key class remains">
  Sandbox / test-mode API keys (`oxi_sk_test_...`) are removed. The API now has a single key class: `oxi_sk_live_...`, sent as `Authorization: Bearer oxi_sk_live_...`, which requires an active Insider subscription and always returns live data.

  Any request still authenticating with an `oxi_sk_test_...` key will fail. Generate a live key from your account's API keys page and switch clients over before this lands. There is no fixture/deterministic-data mode - every request now reads live data.
</Update>

<Update label="July 2, 2026" description="Pick of the Day: fixed 19:00 Europe/Berlin release and a multi-sport candidate pool">
  Two behavior changes to [`GET /api/v1/pick-of-the-day`](/api-reference/endpoint/get-pick-of-the-day) and its archive. No fields were added, removed, or retyped - existing clients are unaffected - but two value semantics changed:

  * `release_at` is now a fixed daily instant: 19:00 Europe/Berlin (19:00 CEST in summer, 19:00 CET in winter), every day, instead of a kickoff-relative time that moved with whichever game was picked. `next_drop_deadline` counts down to the same fixed instant. If no candidate qualifies at the release slot, the selector keeps retrying every 15 minutes until one does (or the day's eligible-kickoff window closes), so on a thin day the actual publish can trail `release_at` by minutes to hours.
  * The pick can now be any sport or prop bet. The candidate pool evaluates every sport category with real smart-money flow that day - soccer, tennis, baseball, basketball, hockey, MMA, cricket, golf, and esports, including prop markets such as totals, spreads, and exact scores - instead of only whatever survived a global hot-markets ranking (which one surging sport could monopolize). Expect `category` values beyond `Soccer` in the archive going forward. Selection guardrails and the ranking metric are unchanged.
</Update>

<Update label="July 1, 2026" description="Whale trades now expose the traded outcome and its CLOB token id">
  Each whale trade ([`GET /api/v1/whale-trades`](/api-reference/endpoint/get-whale-trades), [`/whale-trades/history`](/api-reference/endpoint/get-whale-trades-history), [`/whale-trades/{id}`](/api-reference/endpoint/get-whale-trade)) now returns the traded `outcome` (the provider outcome label - which leg the trade was on, e.g. Yes/No/team) and its per-outcome Polymarket CLOB `token_id`, alongside the existing `side` (BUY/SELL, unchanged). Previously only BUY/SELL was exposed, so you could not tell which outcome a whale trade was on, or get that outcome's on-chain token id.

  `outcome` is null only for a multi-outcome or unsynced market with no stored label; a Kalshi trade carries its provider label here (only `token_id` is null for Kalshi, since there is no CLOB token). Both fields are additive and nullable, so existing clients are unaffected.
</Update>

<Update label="July 1, 2026" description="Every V1 YES/NO/outcome now carries its Polymarket CLOB token id">
  Reads that expose an outcome, side, or net-flow direction now also return a per-outcome Polymarket CLOB `token_id`, so you can go straight from a YES/NO/outcome label to its on-chain ERC1155 asset id without a second lookup. Use it for order placement, per-token price history, and on-chain reconciliation.

  The value is a decimal string for a synced Polymarket market and `null` when unavailable (for example Kalshi markets, or markets that have not synced yet). It is always present and never in a `required` set, so the change is purely additive and safe for existing clients.

  The endpoints that gained it:

  * [`GET /api/v1/positions`](/api-reference/endpoint/get-positions): `token_id` alongside `side`.
  * [`GET /api/v1/large-positions`](/api-reference/endpoint/list-large-positions): `token_id` alongside `outcome_label`.
  * [`GET /api/v1/market/{condition_id}/intel`](/api-reference/endpoint/get-market-intel) and [`POST /api/v1/markets/intel/batch`](/api-reference/endpoint/batch-get-market-intel): `token_id` on `smart_money` (alongside `direction`) and on every `smart_money.top_positions` entry.
  * [`GET /api/v1/markets/smart-money-flows`](/api-reference/endpoint/smart-money-flows): `token_id` on `smart_money`, alongside `direction`.
  * [`GET /api/v1/trader/{address}/position-timeline`](/api-reference/endpoint/get-position-timeline) and [`GET /api/v1/traders/{trader}/position-timeline`](/api-reference/endpoint/get-trader-position-timeline): `token_id` alongside `outcome_side`.
  * [`GET /api/v1/markets/explore`](/api-reference/endpoint/explore-markets): `token_id_yes` and `token_id_no` alongside `outcome_yes` / `outcome_no`. These are CLOB token ids (decimal strings), distinct from the integer `outcome_yes_provider_id` / `outcome_no_provider_id` Gamma ids.
  * [`GET /api/v1/reports/daily`](/api-reference/endpoint/get-daily-report-snapshot), [`weekly`](/api-reference/endpoint/get-weekly-report-snapshot), and [`monthly`](/api-reference/endpoint/get-monthly-report-snapshot): `token_id` on every `top_whale_trades` entry.
</Update>

<Update label="July 1, 2026" description="Pick of the Day archive adds a cumulative track-record series for charting">
  `GET /api/v1/pick-of-the-day/archive` now returns a `hit_rate.series` array — the cumulative track record of the Pick of the Day, ready to chart without recomputing it on the client.

  Each element is one resolved (win or loss) pick, in ascending `pick_date` order, and carries:

  * `date` — the pick's publish date (`YYYY-MM-DD`).
  * `net_profit_usd` — the running cumulative profit of a \$100 stake on every resolved, priced pick through that date.
  * `hit_rate_pct` — the running hit rate (wins / decided) through that date, to one decimal.

  The final point equals the top-level `hit_rate.net_profit_usd` and `hit_rate.pct`, so a chart of the series always ends exactly on the headline numbers. The array is empty until at least one pick has resolved. Every existing `hit_rate` field is unchanged — this is purely additive.
</Update>

<Update label="June 29, 2026" description="Trader quant_metrics is now a documented, fixed field set">
  [`GET /api/v1/trader/{address}`](/api-reference/endpoint/get-trader) and [`POST /api/v1/traders/batch`](/api-reference/endpoint/batch-get-traders) now return a curated, documented `quant_metrics` object when you pass `?expand=quant_metrics`, instead of an unconstrained pass-through of internal metrics.

  When expanded, the object always carries these nine fields, each a number or `null` (`null` means insufficient trade history and is never `0`):

  * `copy_score`, `smart_score`: 0-100 composite scores. `smart_score` blends risk-adjusted return, profit factor, edge consistency, return on capital, equity smoothness, and diversification. `copy_score` is that same base minus penalties for traits that make a strategy hard to replicate (small sample, concentration, oversized position sizing, large single losses, inconsistent edge).
  * `sharpe_30d`, `sharpe_7d`: risk-adjusted return over the trailing 30 and 7 days.
  * `profit_factor`: gross profit divided by gross loss (capped at 1000).
  * `edge_consistency`: stability of the trader's edge over time (0-1).
  * `sharpe_percentile`, `pf_percentile`, `consistency_percentile`: cross-sectional ranks versus all traders (0-100).

  Every field is defined in the [trader endpoint reference](/api-reference/endpoint/get-trader), and the new [Quant metrics guide](/concepts/quant-metrics) explains what each score and metric means, its range, and how to read `null`. Undocumented internal and experimental metrics that previously leaked through the pass-through are no longer returned.
</Update>

<Update label="June 1, 2026" description="Smart-money flow market discovery endpoint">
  Added [`GET /api/v1/markets/smart-money-flows`](/api-reference/endpoint/smart-money-flows), a ranked discovery feed that answers where smart money is flowing before you know a `condition_id`.

  It ranks markets by absolute net flow from S, A, and B grade traders over a `1h`, `4h`, `24h`, or `7d` window, with `platform`, `category`, `min_grade`, and `direction` filters. Pagination uses an opaque cursor anchored to the first page's `as_of`, so new whale trades do not reorder later pages. Drill into a single market with [`GET /api/v1/market/{condition_id}/intel`](/api-reference/endpoint/get-market-intel).
</Update>

<Update label="June 1, 2026" description="Remote MCP read parity, round-trippable IDs, usage and caching headers, and easier discovery">
  **Remote MCP read parity.** [`POST /api/v1/mcp`](/api-reference/endpoint/remote-mcp) now exposes 21 read-only tools through `tools/list`, covering the public V1 reads: batch reads, history, event replay, webhook reads, reports, market snapshots, and trader exports. Webhook mutations stay REST-only, and the endpoint is tools-only (no resources or prompts).

  **See your usage.** Added [`GET /api/v1/usage`](/api-reference/endpoint/get-usage), an authenticated peek at your current per-minute limiter window and UTC-day usage. It doesn't spend primary quota, but has its own 100 reads/minute guard.

  **Cheaper polling, safe retries.** Deterministic reads now support `ETag` / `If-None-Match` conditional GETs, so an unchanged read returns `304` with no body. Webhook create/update/delete/rotate accept an `Idempotency-Key`.

  **Easier discovery.** Added [`GET /api/v1`](/api-reference/endpoint/get-api-discovery) (an API discovery document) and [`GET /api/v1/openapi.json`](/api-reference/endpoint/redirect-api-openapi-spec) (a redirect to the canonical OpenAPI spec). Operation IDs are now codegen-friendly, with examples, code samples, and response-header metadata.

  **Round-trippable IDs.** Market Intel and Market Snapshot now accept the `mkt_...` market ID or the raw `condition_id`. New [`GET /api/v1/whale-trades/{id}`](/api-reference/endpoint/get-whale-trade) and [`GET /api/v1/insider-radar/{id}`](/api-reference/endpoint/get-insider-radar-flag) dereference a single `wt_...` / `rf_...` record. Non-market prefixes return `400 bad_request`.
</Update>

<Update label="May 8, 2026" description="Remote MCP exposes position and market discovery tools">
  [`POST /api/v1/mcp`](/api-reference/endpoint/remote-mcp) now exposes nine read-only tools through `tools/list`.

  The new tools are `get_positions`, `get_position_timeline`, and `explore_markets`. Each dispatches to the existing public REST handler, so MCP clients receive the same auth, pagination, and payload contracts as direct REST callers.
</Update>

<Update label="May 8, 2026" description="Builder API expansion adds batch, history, events, webhooks, reports, and market snapshots">
  Added task-shaped builder endpoints for lower-call-count integrations:

  * [`POST /api/v1/traders/batch`](/api-reference/endpoint/batch-get-traders)
  * [`POST /api/v1/markets/intel/batch`](/api-reference/endpoint/batch-get-market-intel)
  * [`GET /api/v1/whale-trades/history`](/api-reference/endpoint/get-whale-trades-history)
  * [`GET /api/v1/events/feed/since`](/api-reference/endpoint/get-event-replay-since)
  * [`GET /api/v1/market/{condition_id}/snapshot`](/api-reference/endpoint/get-market-snapshot)
  * [`GET /api/v1/reports/daily`](/api-reference/endpoint/get-daily-report-snapshot), [`weekly`](/api-reference/endpoint/get-weekly-report-snapshot), and [`monthly`](/api-reference/endpoint/get-monthly-report-snapshot)
  * [`GET /api/v1/trader/{address}/export`](/api-reference/endpoint/get-trader-export-snapshot)
  * [`GET /api/v1/webhooks`](/api-reference/endpoint/list-webhooks) plus webhook create, read, update, delete, verify, and rotate-secret operations

  Batch endpoints expose item-weighted cost headers. New snapshot/history/report payloads document source, freshness, completeness, and reconciliation semantics so clients can distinguish provider-backed, cached, partial, stale, and unavailable values.
</Update>

<Update label="May 8, 2026" description="TypeScript client source added">
  Added [TypeScript client guidance](/integrations/typescript-client) for the repo-owned client source in `web/src/lib/api-client`.

  The client source is drift-tested against OpenAPI and handles bearer auth, path params, repeated query params, JSON bodies, and V1 error envelopes. It is not a published npm package yet.
</Update>

<Update label="May 7, 2026" description="Market Intel rejects prefixed market IDs">
  [`GET /api/v1/market/{condition_id}/intel`](/api-reference/endpoint/get-market-intel) now returns a clearer `400 bad_request` when callers pass a prefixed `market.id` value such as `mkt_...` instead of the raw `condition_id`.

  Use [`GET /api/v1/markets/search`](/api-reference/endpoint/search-markets) first, then pass the returned `condition_id` into the Market Intel path.
</Update>

<Update label="April 14, 2026" description="Trader lookup accepts usernames and plain expand params">
  [`GET /api/v1/trader/{address}`](/api-reference/endpoint/get-trader) now accepts a known trader username in the path in addition to an Ethereum wallet address.

  Heavy trader fields can be requested with repeated `expand` query params, and the legacy `expand[]` form remains supported for existing clients.
</Update>

<Update label="April 2, 2026" description="Leaderboard strategy fields can be null">
  [`GET /api/v1/leaderboard`](/api-reference/endpoint/get-leaderboard) now safely returns traders without a classified strategy.

  Clients should treat `strategy_type` as nullable for ranked traders without a strategy classification.
</Update>

<Update label="April 1, 2026" description="Explore Markets excludes untitled rows">
  [`GET /api/v1/markets/explore`](/api-reference/endpoint/explore-markets) no longer returns untitled markets.

  This tightens the response set to titled, user-facing markets only.
</Update>

<Update label="March 28, 2026" description="Trader realized P&L corrected">
  [`GET /api/v1/trader/{address}`](/api-reference/endpoint/get-trader) now returns the canonical realized P\&L from the `realized_pnl` source-of-truth field.

  The `pnl.realized` field stopped deriving realized P\&L from an inconsistent approximation.
</Update>

<Update label="March 26, 2026" description="Explore Markets endpoint launched">
  Added [`GET /api/v1/markets/explore`](/api-reference/endpoint/explore-markets) for cursor-paginated market discovery.

  The endpoint supports category, status, platform, and text filters, plus primary-market injection so grouped events include a main market when one exists.
</Update>

<Update label="March 25, 2026" description="Initial V1 launch">
  Launched the first public developer API:

  * [`GET /api/v1/trader/{address}`](/api-reference/endpoint/get-trader)
  * [`GET /api/v1/whale-trades`](/api-reference/endpoint/get-whale-trades)
  * [`GET /api/v1/leaderboard`](/api-reference/endpoint/get-leaderboard)
  * [`GET /api/v1/markets/search`](/api-reference/endpoint/search-markets)
  * [`GET /api/v1/market/{condition_id}/intel`](/api-reference/endpoint/get-market-intel)
  * [`GET /api/v1/insider-radar`](/api-reference/endpoint/get-insider-radar)
  * [`GET /api/v1/health`](/api-reference/endpoint/health)

  The initial contract shipped with Bearer auth, `expand[]`, cursor pagination, prefixed IDs, and rate-limit headers.
</Update>

<Update label="March 25, 2026" description="Numeric precision standardized">
  Money values and scores are truncated to 2 decimal places across V1 responses.

  Prices and rates are truncated to 4 decimal places.
</Update>
