Pick of the Day publishes no pick earlier than 4 hours before kickoff
GET /api/v1/pick-of-the-day no longer publishes a pick while its game starts more than 4 hours later. A pick chosen earlier stays in scheduled_picks with release_at set to 4 hours before the current kickoff, and moves if the kickoff moves. Every publication check runs again at that instant, so a pick can still leave the schedule unpublished. A pick still publishes no later than 30 minutes before kickoff, and never before 3:00 AM Eastern.Before this change a pick published as soon as it qualified. On October 28, 2026, one published 16 hours before its game, and over the 30 days before, 246 of 480 picks published more than 4 hours before kickoff.Backward compatible. No field is added, removed, or retyped. 404 pick_not_released can last longer on a day whose first pick waits for its hold.What to change: Nothing, if you schedule reads from release_at and retry_at. If you assumed a qualified pick publishes at once, read the release time from scheduled_picks instead.Position timeline usdc_notional is documented as shares times price, fees excluded (corrected October 29)
On
GET /api/v1/trader/{address}/position-timeline and GET /api/v1/traders/{trader}/position-timeline, the reference now says exactly what usdc_notional is: the fill’s shares times its price, rounded to 6 decimals, with the trading fee excluded.Correction, October 29, 2026. The first version of this entry said that usdc_notional changed on fills recorded from the Polymarket activity feed, and that it had carried Polymarket’s fee-bearing usdcSize. That was wrong for this endpoint. The position timeline reads only fills recorded from the on-chain order log, which were always on this basis: from October 1 to 8, 2026, 0 of 3,391 timeline fills differed from shares times price by more than 1%. No value on this endpoint changed.Backward compatible. Nothing is added, removed, retyped, or changed in value.What to change: Nothing.Large positions min_grade matches the grade each row shows
GET /api/v1/large-positions now applies min_grade to the trader.grade each row returns, which is the wallet’s current grade. Every row in a filtered response shows a grade at or above the floor.Before this change, min_grade matched the grade stored when the position was last scanned. If the wallet’s grade moved after that scan, a row could be listed under a filter its own trader.grade did not meet, and a wallet just promoted could be left out.On October 28, 2026, 39 of 1,610 stored positions held a grade other than the wallet’s current one. None of them was at or above the $50,000 listing floor, so no served row was affected that day.Backward compatible. No field, parameter, or value changes. Only which rows a min_grade filter returns can differ, and only for a wallet whose grade moved since its last scan.What to change: Nothing.Edge Hunter wider_holder excludes only what view=signals lists; new signals_as_of
GET /api/v1/edge-hunter?view=observations now excludes from cohort=wider_holder exactly the markets view=signals lists at its widest request (horizon_hours=48, min_grade=B, no selector). Every observations response names that signals snapshot in the new signals_as_of.Before this change, wider_holder excluded every market the signals view considered, before its holder checks. A market that failed those checks left wider_holder as primary_slate_candidate, but view=signals did not list it, so neither view showed it until kickoff. On October 28, 2026, at least 2 of the 9 Basketball markets counted as primary_slate_candidate were in that gap.signals_as_of(date-time ornull): theranked_atof theview=signalssnapshot whose markets this snapshot excluded.nullmeans no signals snapshot could be read and no market was excluded. Omitted on an unmappable legacycategory.departures[].reasonfollowsview=signalswhile an entry is open: it becomesprimary_slate_candidatewhen a later snapshot excludes the market, and takes that snapshot’s outcome for the market when one no longer does.departed_atand the reason values are unchanged.- A sport’s
funnelcount ofprimary_slate_candidateis now at most its number ofview=signalsrows at the widest request. - The SDK’s
EdgeHunterObservationsResponsetype and theget_edge_hunterMCP output schema carrysignals_as_of.
primary_slate_candidate departure to its signal, read view=signals&horizon_hours=48 and pair it with the observations response whose signals_as_of equals its rows’ ranked_at.Rust client oxinsider 0.4.0 is on crates.io; install with cargo add oxinsider
The Rust client
oxinsider 0.4.0 is published on crates.io. Install it with cargo add oxinsider, and read its API reference on docs.rs.Before this change, the crate had no crates.io release, and you added it from its GitHub repository with a --git install.Backward compatible. The crate’s API is unchanged; only where you install it from is new.What to change: Nothing. To take crates.io releases instead of the repository’s main, replace the git dependency in your Cargo.toml with oxinsider = "0.4".sync_coverage counts the combo markets a wallet traded; new markets_combo
GET /api/v1/trader/{address}/context now returns position_summary.markets_combo, and position_summary.sync_coverage adds it to the synced, pruned, and unstored markets before dividing by markets_total.Before this change, a wallet that traded combos read below 1.0 even when every market it held was synced. Polymarket counts each combo as one market in markets_total, and no position list includes one. One wallet with all 62 of its markets synced and 67 combos read 0.48.position_summary.markets_combo(integer, always sent): combo markets the wallet traded, as maker or taker.0when it traded none. No other count inposition_summaryincludes them.GET /api/v1/trader/{address}/export:completeness.sync_coverageuses the same numerator, so such a wallet can now readcomplete.- The
context.mdcoverage line names them, for example100% (62 synced plus 67 combo markets, of 129 Polymarket markets traded, every category). - The
get_trader_contextMCP tool and the SDK’sPositionSummarytype carry the new field.
(markets_synced + markets_pruned + markets_unstored + markets_combo) / markets_total.sync_coverage counts new markets of other categories; new markets_unstored
GET /api/v1/trader/{address}/context now returns position_summary.markets_unstored, and position_summary.sync_coverage divides markets_synced plus markets_pruned plus markets_unstored by markets_total.Before this change, a market of another category that a wallet first traded on or after October 26, 2026 was neither stored nor counted. A wallet that kept trading other categories read below 1.0, and its export read partial.position_summary.markets_unstored(integer, always sent): markets of other categories the wallet first traded on or after October 26, 2026. 0xinsider does not store them and counts them as the wallet syncs.0when there are none. No other count inposition_summaryincludes them.GET /api/v1/trader/{address}/export:completeness.sync_coverageuses the same numerator.GET /api/v1/trader/{address}:pnl.in_scope.markets_out_of_scopealso counts these markets once the wallet’s record is next computed.- The
context.mdcoverage line names them, for example98% (431 synced plus 1794 pruned and 39 not stored outside sports and esports, of 2310 Polymarket markets traded, every category). - The
get_trader_contextMCP tool and the SDK’sPositionSummarytype carry the new field. - A market of another category that a wallet traded and closed between October 26, 2026 and this change can stay uncounted.
(markets_synced + markets_pruned + markets_unstored) / markets_total.Large trades: recorded_review_score reads the sports and esports win rate
GET /api/v1/large-trades, GET /api/v1/large-trades/{id} and GET /api/v1/large-trades/history now record recorded_review_score from the wallet’s win rate on sports and esports markets, for every trade recorded after this change. The deprecated /api/v1/whale-trades routes, the large-trade MCP tools, and recorded_signal_score change the same way.Before this change, the win-rate part of recorded_review_score used the wallet’s win rate over every Polymarket market. review_score moved to the sports and esports win rate on October 27.- The score’s formula, its size, price, and age parts, and its 0 to 1 scale are unchanged.
- A trade recorded before this change keeps the value it was recorded with.
- A wallet with no sports and esports record yet gets the same fixed win-rate part a wallet with no measured win rate got before.
review_score and recorded_review_score differ only by the trade’s age.sync_coverage counts deleted other-category markets again; new markets_pruned
GET /api/v1/trader/{address}/context now returns position_summary.markets_pruned, and position_summary.sync_coverage divides markets_synced plus markets_pruned by markets_total. A fully synced wallet reads 1.0 again.Before this change, sync_coverage divided only the wallet’s synced sports and esports markets by Polymarket’s count of every market it traded. Since October 27, 2026, a wallet that also traded other markets read below 1.0, and its export read partial.position_summary.markets_pruned(integer, always sent): markets of other categories whose rows 0xinsider deleted, counted when they were deleted.0when none were. No other count inposition_summaryincludes them.GET /api/v1/trader/{address}/export:completeness.sync_coverageuses the same numerator, so a fully synced wallet readscompleteagain. A wallet with nothing synced and nopnlday readsempty, whatever its coverage.- The
context.mdcoverage line names both parts, for example100% (12157 synced plus 575 pruned outside sports and esports, of 12608 Polymarket markets traded, every category). - The
get_trader_contextMCP tool and the SDK’sPositionSummarytype carry the new field. - A market of another category first traded on or after October 26, 2026 is neither synced nor counted. A wallet that keeps trading other categories reads below
1.0by those markets.
(markets_synced + markets_pruned) / markets_total.Trader position totals and unrealized P&L now cover sports and esports markets
GET /api/v1/trader/{address}/context and GET /api/v1/trader/{address} now count only a wallet’s sports and esports markets in its position totals. Since October 27, 2026, 0xinsider keeps no other market of a wallet that holds a sports or esports market.Before this change, these figures counted every Polymarket market the wallet traded, and the spec, the SDK types, and the get_trader_context MCP tool said so.position_summary:markets_synced,markets_resolved,markets_open,unrealized_mtm,cost_basis_locked,resolved_wins,resolved_decided, andresolved_win_rate.pnl.unrealizedon the trader.- The
context.mddocument: its heading is nowPosition breakdown (synced sports and esports markets), and its unrealized line readsUnrealized P&L (open sports and esports positions). The realized line leaves out “0 other Polymarket markets” when there are none. - Three figures still cover every market the wallet traded, and their descriptions now say so:
position_summary.total_realized_pnl,position_summary.synced_realized_pnl, andposition_summary.markets_total. position_summary.sync_coverageandGET /api/v1/trader/{address}/export’scompleteness.sync_coveragedivide sports and esports markets bymarkets_total. A fully synced wallet that also traded other markets now reads below1.0, and its export readspartial.- A wallet with no sports or esports market can still show older markets of other categories until 0xinsider deletes them.
pnl.in_scope.realized_pnl for sports and esports realized P&L, not position_summary.total_realized_pnl. Do not read a sync_coverage below 1.0 as missing sports and esports markets.An export cut by a deploy restarts within seconds instead of failing after 90 minutes
A trader export or whale dataset job that is running when 0xinsider restarts its backend for a deploy now reads
queued again at once, and the next worker starts it again within seconds. GET /api/v1/trader/{address}/export/status and GET /api/v1/datasets/whale-trades/{job_id} show it.Before this change, such a job read running with no progress for up to 90 minutes, then failed with error set to export provider artifact retired without a ready object.- A requeued job reads
queuedwitherrorsaying why:export worker restarted; export requeuedafter a deploy, orworker lease expired; export requeuedwhen a worker stopped without handing the job back. The second case now requeues within a minute of the 30-minute lease lapsing, not up to an hour after it. - A deploy restart does not use one of the job’s 3 attempts, so
attemptsteps back by one when the job readsqueuedfor that reason. The 24-hourexpires_atstill bounds every job. - A job you asked to cancel reads
cancelledas the worker shuts down, not after its lease lapses. - A
reconcile_requiredjob is read back within a minute, not at the next hourly pass. A failed readback still retries an hour later.
poll_after_s is unchanged.What to change: Nothing. If your client treated a queued job with an error as failed, keep polling it instead: it is waiting for a worker.Rounded category-skill, Edge Hunter and Pick of the Day numbers serve a zero as 0, never -0.0
The
/api/v1 numbers that 0xinsider rounds to the nearest decimal, rather than truncating, now also serve a zero as 0.0, never -0.0. The MCP tools that return the same data change the same way.Before this change, a small negative value that rounded to zero kept its sign. For example, a category-skill edge_mean of -0.00001 served as -0.0.- The
category_skillobject on trader rows, such asGET /api/v1/trader/{address}/contextandGET /api/v1/leaderboard, and on holder category evidence:edge_mean,edge_lower_95, and the other edge scores. GET /api/v1/edge-hunter:directional_confidenceand thecategory_skillfractions, such asweighted_edge_mean.GET /api/v1/pick-of-the-day/archive:hit_rate.roi_pct.- Only the sign of a zero changes. Every other value, and the rounding itself, stay as they were.
-0.0 and 0.0 are equal numbers, and no field or type changes. An Edge Hunter cursor issued before the change still pages the same rows.What to change: Nothing. A guard that hid -0.0 in your client is no longer needed.Truncated money, share, price and rate fields serve a zero as 0, never -0.0
Every
/api/v1 number that 0xinsider truncates to two or four decimals, such as money, share counts, prices and rates, now serves a zero as 0.0, never -0.0. The MCP tools that return the same data change the same way.Before this change, a negative value that truncated to zero kept its sign. For example, GET /api/v1/large-positions served "in_scope_realized_pnl": -0.0 for a wallet whose sports and esports P&L is -$0.000026, and `Intl.NumberFormat` prints that as `-$0.00`.- Only the sign of a zero changes. Every other value, and the truncation toward zero, stay as they were.
- Signed fields can show the change: P&L, unrealized P&L, and share changes such as
amount_deltaon a position timeline. Prices and rates are never negative.
-0.0 and 0.0 are equal numbers, and no field or type changes.What to change: Nothing. A guard that hid -$0.00 in your client is no longer needed.Edge Hunter: a holder read that was never sent reports holder_deadline_unavailable
GET /api/v1/edge-hunter observations now report holder_deadline_unavailable when a market’s holder read was never sent to Polymarket because 0xinsider’s own request capacity ran out, and no earlier read is recent enough to serve.Before this change, that read was reported provider_unavailable, the reason for a read Polymarket failed. On October 27, 47 of 49 failed holder reads in one deployment were reads that never left 0xinsider.provider_unavailablenow means only a holder read that failed at Polymarket: a timeout, an error status, a body that could not be read, or a read held back while Polymarket is refusing these requests.- The change applies to the
funnelterminal counts and todepartures[].reason. Expect fewerprovider_unavailableand moreholder_deadline_unavailable. - A market with a recent enough earlier read still serves it, as before, with
provider_read_sourceset tocached.
provider_unavailable as a Polymarket outage, it now counts only reads that failed at Polymarket.Edge Hunter observations keep a card when one holder read fails
GET /api/v1/edge-hunter observations now keep a market’s row when the latest holder read for it fails and an earlier read is recent enough to serve. The row carries that earlier read under the limits that already applied to a read that did not finish: up to 15 minutes old for wider_holder and emerging_pile, up to 10 minutes for in_play, never a pre-kickoff read on an in_play row.Before this change, one failed read took the card out of data for that snapshot with the funnel reason provider_unavailable, and a wider_holder read listed it in departures.- The reused row keeps the earlier read’s
holder_snapshot_at, andprovider_read_sourceiscached. provider_unavailablenow means the read failed and the market had no earlier read to serve. Expect fewer of them infunnelanddepartures.
provider_read_source: "cached" as fresh, check holder_snapshot_at instead.Trader export provider observations no longer carry Polymarket's all-time leaderboard figures
In the JSON and NDJSON files from
POST /api/v1/trader/{address}/export, export_metadata.provider_observations.rows now holds one row, positions_value: the wallet’s open position value.Before this change the array also held the all row: Polymarket’s all-time leaderboard P&L and volume across every market the wallet traded. 0xinsider wallet figures cover sports and esports markets only, and the day, week and month rows left the file earlier today.rows[].facttakes only the valuepositions_value. No field of that row changes, and the rest ofprovider_observationsis unchanged.trader.positions_valueand thepositions_valuerow still cover every Polymarket market: Polymarket values the whole book in one observation, and no exact sports and esports open value exists.export_metadata.scope_notesays so.- Files exported before this change keep the
allrow. A submit withoutfresh=truecan return such a file until it expires, 24 hours after it was queued.
all row.What to change: Read the wallet’s P&L from trader.product_scope_pnl.realized_pnl, the sports and esports figure its 0xinsider profile shows.Large trades: review_score reads the wallet's sports and esports win rate
GET /api/v1/large-trades, GET /api/v1/large-trades/{id} and GET /api/v1/large-trades/history now compute review_score from the wallet’s win rate on sports and esports markets, the rate its 0xinsider profile shows. The deprecated /api/v1/whale-trades routes and the large-trade MCP tools change the same way.Before this change, the win-rate part of review_score used the wallet’s win rate over every Polymarket market.- The score’s size, price, and age parts and its 0 to 1 scale are unchanged.
- A wallet with no sports and esports record yet gets the same fixed win-rate part a wallet with no measured win rate got before.
recorded_review_scoreis unchanged. It keeps the value stored at insert, which read the every-market win rate, so it can now differ fromreview_scoreby more than the trade’s age.signal_scorekeeps carrying the same value asreview_score.
review_score with recorded_review_score, expect a gap for wallets that also trade other markets.Leaderboard and trending wallets carry sports and esports figures only, and their wallet-wide P&L fields are retired
GET /api/v1/leaderboard and GET /api/v1/leaderboard/trending now describe each wallet by its sports and esports record, the figures its 0xinsider profile shows. The get_leaderboard and get_trending_wallets MCP tools change the same way.Before this change, both lists also sent figures that covered every Polymarket market the wallet traded.- On the leaderboard,
pnl,realized_pnl,pnl_correctionandvolumeare never sent. The wallet’s P&L isin_scope.realized_pnl. - On the leaderboard,
markets_tradedandwin_ratekeep their names and types and now restatein_scope.marketsandin_scope.win_rate. Both are absent for a wallet with noin_scoperecord yet. - On trending wallets,
all_time_pnl_usdandpnl_correctionare never sent.in_scope_realized_pnlis new: the wallet’s realized P&L on sports and esports markets, in USD, absent until the wallet’s record is computed. The list order,trending_pnl_usdand the window figures do not change.
deprecated: true and x-never-sent: true, so generated code still compiles.Breaking for clients that read the retired fields, or that compare markets_traded or win_rate with a wallet-wide figure.What to change: Read the wallet’s P&L from in_scope.realized_pnl on the leaderboard and from in_scope_realized_pnl on trending wallets. Expect lower market counts and a different win rate for wallets that also trade other markets.Position and large-position traders carry sports and esports figures, and trader.pnl is retired
GET /api/v1/positions and GET /api/v1/large-positions now describe each row’s wallet by its sports and esports record, the figures its 0xinsider profile shows. The get_positions and get_large_positions MCP tools change the same way.Before this change, trader.pnl was Polymarket’s total P&L over every market of the wallet, and trader.win_rate and the market count covered every market too.trader.pnlis never sent. It stays in the OpenAPI document withdeprecated: trueandx-never-sent: true, so generated code still compiles.trader.in_scope_realized_pnlis new: the wallet’s realized P&L on sports and esports markets, in USD. It is absent until the wallet’s record is computed.trader.win_rateandtrader.markets(trader.markets_tradedon large positions) keep their names and types and now count sports and esports markets only. Both are absent for a wallet with no record yet.
consistency=snapshot cursor on positions taken before this change returns its rows in the old shape until it expires, at most 5 minutes later.Breaking for clients that read trader.pnl, or that compare trader.win_rate or the market count with a wallet-wide figure.What to change: Read the wallet’s P&L from trader.in_scope_realized_pnl. Expect lower market counts and a different win rate for wallets that also trade other markets.The sandbox stops serving the retired trader fields, and the OpenAPI document marks them x-never-sent
The sandbox no longer returns trader fields that production stopped sending.
POST /sandbox/api/v1/traders/batch omits pnl.total, pnl.net_total, pnl.realized, pnl.correction, pnl.exact, stats.daily_win_rate, quant_metrics and, with expand=trust, trust.pnl_correction. GET /sandbox/api/v1/trader/{address}?expand=quant_metrics accepts quant_metrics and adds nothing, as production does.Before this change, the sandbox answered these fields with sample values, so a client built against the sandbox read figures the live API never returns.In the OpenAPI document, each of these properties now carries "x-never-sent": true beside deprecated: true. The schemas stay, so code generated from the document still compiles. A deprecated field that is still sent, such as signal_score on large trades, carries no marker.Backward compatible. No production response changes.What to change: Nothing. To skip retired fields in code you generate from the document, filter properties that carry x-never-sent.The dataset export's trader figures, risk_metrics and duration and hour buckets cover sports and esports markets
In a file from
POST /api/v1/trader/{address}/export, the trader figures, risk_metrics and category_performance.by_duration and by_hour_bucket now cover the wallet’s sports and esports markets only, the figures its 0xinsider profile shows.Before this change, these figures covered every Polymarket market the wallet traded, while trades, markets and pnl in the same file held sports and esports markets only.trader.realized_pnl,trader.markets_tradedandtrader.win_ratecome fromtrader.product_scope_pnl, andtrader.pnl_tieris the tier of that realized P&L. All four arenulluntil the record is computed.trader.total_volumeis the wallet’s sports and esports trade volume, both sides, the same figure asstats.total_volumeonGET /api/v1/trader/{address}.trader.total_pnl,trader.daily_win_rate,trader.biggest_win,trader.total_fees_paidandtrader.calibration_edgeare alwaysnull. No sports and esports figure exists for them. The career fee total stays intrader.pnl_accounting.fees_paid.risk_metricsand the duration and hour buckets are the figures of the wallet’s sports and esports markets.risk_metrics.concentrationis the concentration of the wallet’s sports and esports volume across categories.summary(and the position-summary keys thattraderrepeats),trader.pnl_accounting,trader.unrealized_pnl,trader.positions_valueandexport_metadata.provider_observationsstill cover every market of the wallet.export_metadata.scope_notelists which sections cover what.
trader figures or compare the scoped figures with Polymarket’s wallet-wide figures. No field is removed or retyped, and generation.product_scope stays sports_esports_v1.What to change: Read the wallet’s P&L from trader.product_scope_pnl.realized_pnl. A file whose scope_note does not list risk_metrics was written before this change. A submit without fresh=true can return such a file until it expires, 24 hours after it was queued.Trader stats cover sports and esports markets, and wallet-wide P&L fields are retired
GET /api/v1/trader/{address}, POST /api/v1/traders/batch, GET /api/v1/trader/{address}/context, its Markdown twin and the get_trader MCP tool now report a wallet’s figures over sports and esports markets only. pnl.in_scope is the wallet’s P&L, and stats comes from the same record.Before this change, pnl.total, pnl.net_total, pnl.realized, pnl.correction and every stats figure covered every Polymarket market the wallet traded, while the 0xinsider profile shows sports and esports markets only.pnl.total,pnl.net_total,pnl.realized,pnl.correction,pnl.exactandstats.daily_win_rateare no longer sent. The OpenAPI document keeps them, markeddeprecated, so code generated from it still compiles. Withexpand=trust,trust.total_pnl,trust.net_total_pnl,trust.realized_pnlandtrust.daily_win_ratereportnot_computed, andtrust.pnl_correctionis no longer sent.stats.markets_tradedis the wallet’s sports and esports market count,pnl.in_scope.markets.stats.win_rateis the share of its decided sports and esports markets it won,pnl.in_scope.win_ratetruncated to 4 places. Both are omitted until the record is computed.stats.total_volumeandstats.exact.total_volumeare the wallet’s sports and esports trade volume, both sides, from its stored trading days. Before this change they were Polymarket’s full-history figure for the whole wallet. They are omitted before the first completed sync and while a stored day is not computed yet, and read0for a synced wallet with no trading day.data_quality.field_groupshas six groups:sync,sports_record,ranking,leaderboard_rank,volumeandpositions.sports_recorddatespnl.in_scope,stats.markets_tradedandstats.win_rate.leaderboard_pnlis removed withpnl.total.pnl.unrealizedstill covers every open position of the wallet, and the context’sposition_summarystill covers every synced market. The Markdown document labels both.
pnl fields or stats.daily_win_rate, and for clients that compare stats with Polymarket’s wallet-wide figures. No request fails, and no field changes type.What to change: Read pnl.in_scope.realized_pnl for the wallet’s P&L and check pnl.correction_pending before you treat it as final. For Polymarket’s own wallet-wide figures, read Polymarket’s API.Trader export provider observations no longer carry the day, week and month leaderboard figures
In the JSON and NDJSON files from
POST /api/v1/trader/{address}/export, export_metadata.provider_observations.rows now holds two rows: all, the wallet’s all-time Polymarket leaderboard figures, and positions_value, its open position value.Before this change the array also held day, week and month rows: Polymarket’s leaderboard P&L and volume over the past day, week and month across every market the wallet traded. 0xinsider wallet figures cover sports and esports markets only, so 0xinsider no longer reads those three periods. Their stored values had a median age of 22 days.rows[].facttakes only the valuesallandpositions_value. No field of a remaining row changes, and the rest ofprovider_observationsis unchanged.- Files exported before this change keep their five rows.
day, week or month row.What to change: Stop reading those rows. For the wallet’s sports and esports P&L over a window, add up pnl[].daily_change over the window in the same export, or read GET /api/v1/trader/{address}/pnl.Trader daily volume counts trade size without fees, as Polymarket counts it
entries[].total_volume on GET /api/v1/trader/{address}/pnl, and pnl[].total_volume and volume_reconciliation.exported_activity_volume in the Pro dataset export, now add up each fill’s size times its price: the measure Polymarket reports as a wallet’s volume.Before this change these figures added up the cash each fill moved. Since April 28, 2026 a taker’s cash includes the trading fee, so a buy counted above its size times price and a sell below it, and a wallet’s volume could read a fraction of a percent above or below Polymarket’s.- Trading days from this release use the new measure. Days stored before it keep the earlier measure until they are recomputed.
trades[].usdc_sizein the export is unchanged: it is still the cash the fill moved, fee included.trader.total_volumeis unchanged: it is Polymarket’s own full-history figure.
trades[].usdc_size.Trader quant_metrics is retired, and the export's quant metrics cover sports and esports
GET /api/v1/trader/{address} and POST /api/v1/traders/batch no longer return quant_metrics. Both still accept expand=quant_metrics, so no request fails, and with expand=trust the entry trust.quant_metrics reports not_computed.Before this change, expand=quant_metrics returned 9 figures over every Polymarket market the wallet traded. 0xinsider wallet figures now cover sports and esports markets only, and 6 of the 9 ranked the wallet against every other wallet across all markets, so they have no sports and esports version.- The OpenAPI document keeps
Trader.quant_metrics, markeddeprecated, so code generated from it still compiles. The SDK types and theget_traderMCP tools describe the same change. - The Pro dataset export’s
quant_metricsand the ratios in itsrisk_summary(sharpe_ratio,sortino_ratio,max_drawdown,profit_factor,var_95,calmar_ratio) now come from the wallet’s sports and esports P&L by day. Before this change they covered every market. A wallet whose sports and esports record is not computed yet exports an emptyquant_metricsandnullratios. - The export’s
risk_metrics,summary, and the duration and hour buckets ofcategory_performancestill cover every market of the wallet. Itspnlalready covers sports and esports markets, as the entry on the export’s daily P&L below describes.
quant_metrics, including copy_score and smart_score. The field was already optional and absent whenever its figures were more than 6 hours old.What to change: Stop requesting expand=quant_metrics. For the wallet’s sports and esports record, read pnl.in_scope; for its P&L by day and drawdown, read GET /api/v1/trader/{address}/pnl.Trader export snapshot P&L dates and pnl_days count the days the export file carries
GET /api/v1/trader/{address}/export now reports source_range.first_pnl_date, source_range.last_pnl_date and counts.pnl_days from the export file’s pnl section: the wallet’s sports and esports realized P&L by UTC day. They are the file’s export_metadata.pnl_date_from, pnl_date_to and pnl_rows.Before this change, they counted the days of the wallet’s P&L curve across every market, which no longer matched the file after its pnl section moved to sports and esports. For one wallet read on October 27, 2026, the snapshot reported 693 days while the file held 288.source_range.pnl_series_statusis new:ready, orpendingwhile 0xinsider has not computed the wallet’s daily series. While it ispending, the dates arenullandpnl_daysis0, which then does not mean the wallet has no days. It is the file’sexport_metadata.pnl_series_status.completeness.statusreadsemptyfor a wallet with no synced market and no day in the file’spnlsection. It used to readpartialwhen the wallet-wide curve had days.reconciliation.exported_activity_volumeis unchanged. It is the same figure as the file’ssummary.volume_reconciliation.exported_activity_volume.
pnl_series_status is additive. The values of the dates and pnl_days change for every wallet that traded markets outside sports and esports.What to change: Read source_range.pnl_series_status before you read pnl_days. If you size or validate an export file from pnl_days, the count now matches the file’s pnl rows.The dataset export's daily P&L covers sports and esports markets only
The
pnl section of a file from POST /api/v1/trader/{address}/export now holds the wallet’s realized P&L in sports and esports markets, one row per UTC day: a day on which it realized P&L in those markets or traded them. daily_change and pair_profit are the day’s realized P&L, and cumulative_profit and total_pnl its running total, which ends at the sum of the days.Before this change, pnl held the daily changes of Polymarket’s P&L curve for the whole wallet, every market included, so its running total could differ from the wallet’s sports and esports P&L in size and sign.export_metadata.pnl_series_statusis new:ready, orpendingwhile 0xinsider has not computed the wallet’s daily series. While it ispending,pnlis empty, and an emptypnldoes not mean zero.export_metadata.pnl_freshness_atis new: when the series was computed,nullwhile pending.export_metadata.pnl_realizedis new:basis,realized_pnl(the same figure astrader.product_scope_pnl.realized_pnl),dated_pnl(the sum of every day), andundated_pnl, the part no day carries, such as the rebate share.nullwhile pending.markets_tradedcounts the day’s markets only when every stored fill of that day is in a sports or esports market, and isnullotherwise. On a day with realized P&L and no fill,markets_tradedandtotal_volumeare0.summary.volume_reconciliation.exported_activity_volumeis unchanged. It is the same figure asGET /api/v1/trader/{address}/exportreports, and it is not always the sum ofpnl[].total_volume.
pnl change for every wallet that trades markets outside sports and esports.What to change: Read export_metadata.pnl_series_status before you read pnl. A file without it was written before this change and still holds the whole-wallet values; a submit without fresh=true can return such a file until it expires, 24 hours after it was queued. To replace pnl rows you stored from an earlier export, submit again with fresh=true.Grade 90-day forecasting edge and S and A capital floors read sports and esports markets
The forecasting edge over the last 90 days inside
grade and score is now measured on the wallet’s resolved sports and esports positions. The capital an S or A grade requires now counts the dollars the wallet put into sports and esports positions.Before this change, the 90-day edge read every market the wallet trades, and the capital requirement read the wallet’s Polymarket trading volume across every market.- The lifetime forecasting edge and the Sortino ratio inside the grade still read every market the wallet trades: measured on sports and esports alone, the lifetime edge ranked wallets’ later results worse.
stats.total_volumeand the other volume fields are unchanged. Only the grade stops reading volume.gradechanges wherever it is returned, including large trades, positions and theirmin_gradefilters. On a copy of production from October 26, 574 of 162,572 graded wallets (0.4%) changed letter, 99 of them to or fromS,AorB. Another 2,083 wallets, which could not be graded without a volume figure, get their first grade. The share of graded wallets atS,AorBmoved from 6.07% to 6.09%.- A wallet’s
gradeandscorechange at its next grading pass after the release. A wallet whose sports and esports 90-day edge 0xinsider has not computed yet keeps the previous one; computing every wallet takes about two hours after the release.
Market holders returns 400 for a page cursor issued before October 2
GET /api/v1/market/{condition_id}/holders now returns 400 with param: "cursor" for a page-only cursor, the format the API stopped issuing on October 2, 2026. Every next_cursor the API has returned since then still works.Before this change the API still accepted a page-only cursor and served the page at its original limit.Breaking for clients that saved a cursor before October 2, 2026, or built one by hand. A cursor continues a live list, so a cursor that old does not resume anything a fresh first page does not show.What to change: Treat cursor as opaque and send back the next_cursor from your previous response. On a 400 with param: "cursor", restart without a cursor.SDK 0.32.0 removes the old method and type names from the September renames
@0xinsider/sdk 0.32.0 removes nine deprecated methods and 17 deprecated types. They were kept as aliases after the September 2026 renames. Each new name takes the same arguments and returns the same data.- The removed methods called the deprecated routes. The new methods call the canonical routes, so a response carries the canonical envelope
object:large_trade,suspicious_trade,market_flowandmarket_flow_batchinstead ofwhale_trade,radar_flag,market_intelandmarket_intel_batch. call(),list()andpaginate()no longer accept the 11 deprecated operation IDs.UNSUPPORTED_OPERATIONSlists each one with the operation to use instead.WebhookEventstill includes the old event typeswhale_trades_inserted,whale_trader_synced,insider_radar_flag_raisedandsmart_money_flow_detected, because a subscription made under an old name still receives it. Only the named TypeScript types for them are removed.- From the next
@0xinsider/mcprelease, which compiles this SDK source,0xinsider market inteland0xinsider whales listkeep working but read the canonical routes, somarket intelprintsobject: "market_flow".0xinsider api callrefuses the deprecated operation IDs. - The deprecated routes still answer until their sunset on February 1, 2027. A client that calls them directly, not through the SDK, is unaffected by this release.
^0.31 range does not install 0.32.0.What to change: Replace each removed name with the name in the “Use instead” column, and match the canonical object if your code branches on it. To narrow a webhook delivery that uses an old event name, check event.type.Leaderboard strategy filter lists the 6 current trading styles only
The
strategy filter of GET /api/v1/leaderboard and the get_leaderboard MCP tool now list only the 6 current trading styles: two_sided, category_focused, high_activity, diversified, mixed and unclassified.Before this change, the OpenAPI enum, the TypeScript SDK’s LEADERBOARD_STRATEGIES and the MCP input schema also listed the 10 styles the classifier wrote before October 1, 2026: accumulator, algo_trader, arbitrageur, directional, event_driven, market_maker, momentum, scalper, speculator and swing_trader. No wallet has carried one since every wallet was reclassified, so those filters always returned an empty list.- The API still accepts the 10 historical values and still returns an empty list for each. Any other unknown value still returns
400witherror.paramset tostrategy. - The SDK types and the MCP tool input schemas list only the 6 current styles. The
@0xinsider/mcpstdio package checks its input against that schema, so it refuses a historical value before calling the API. strategy_typein responses only ever holds one of the 6 current styles.
listLeaderboard, which no longer type-checks, and for stdio MCP calls that send one.What to change: Remove the 10 historical values from your code. A filter on one of them never matched a wallet.Deprecated V1 routes and MCP alias tools are removed on February 1, 2027
The 11 deprecated V1 routes and their 9 MCP alias tools now have a sunset date: 2027-02-01T00:00:00Z. Each route now sends
Sunset: Mon, 01 Feb 2027 00:00:00 GMT (RFC 8594) beside its Deprecation header and its Link to the successor. Until that date every alias answers exactly as it does today. From it, a deprecated route returns 410 with error.code endpoint_retired, and the MCP alias tools are removed.Before this change, the aliases had no end date and sent no Sunset header. The OpenAPI document, the MCP tool descriptions and the versioning policy now name the date.Each successor returns the same data. The single-trade and flow successors use their own envelope
object (large_trade, suspicious_trade, market_flow, market_flow_batch) where the alias kept the old one (whale_trade, radar_flag, market_intel, market_intel_batch).Backward compatible until 2027-02-01. Breaking from that date for clients that call a deprecated route or MCP alias tool.What to change: Call the route or tool in the “Use instead” column before 2027-02-01, and match the new envelope object if your client branches on it. The Link header with rel="successor-version" on every alias response names the exact URL to call. A client that already calls the canonical names needs no change.