Category strengths and the export's price edge cover sports and esports markets only
category_strengths on GET /api/v1/trader/{address} with expand=categories now holds sports and esports categories only. A category outside them, such as Politics or Crypto, is left out. MCP tools and SDK calls that read this route return the same keys.In the dataset export file, trader.price_edge is now the wallet’s edge over the price it paid on sports and esports markets, checked against its sports and esports win rate. export_metadata.scope_note says so.Before this change, category_strengths held every category the wallet traded, and price_edge counted every market. 0xinsider no longer updates categories outside sports and esports, so their ranks would have gone stale.- The values for a sports or esports category are unchanged.
- A wallet’s
price_edgecan change. A wallet with fewer than 30 priced sports and esports markets now hasstatustoo_few_markets. - Trader category records already returned sports and esports categories only.
category_strengths as a map of the keys it holds.What to change: Do not expect a category_strengths key for a category outside sports and esports.Trader category_records list sports and esports categories only
category_records on GET /api/v1/trader/{address} with expand=categories now holds sports and esports categories only. A category outside them, such as Politics or Crypto, is left out. Batch traders, Trader context, the MCP get_trader tool, and SDK calls that read these routes return the same records.Before this change, category_records held a record for every category the wallet traded. On October 25, 2026, one wallet’s 106 records held 94 outside sports and esports.- A sports or esports record is unchanged, and so is
category_skill_model. - Trader category records and
category_strengthsalready returned sports and esports categories only.
category_records as a list of the records it holds.What to change: Do not expect a record for a category outside sports and esports.Large trade counterparties read ExchangeV3 fills, as exchange_family exchange_v3
GET /api/v1/large-trades/{id} and its counterparty executions now return the counterparties of a large trade in a Polymarket Protocol V2 binary or neg-risk market. Polymarket settles those markets on its ExchangeV3 contract, so exchange_family on each execution has a third value, exchange_v3.Before this change, 0xinsider never read the Polygon receipt of such a trade. Its counterparty_analysis stayed unavailable with unavailable_reason evaluation_not_seeded.ctf_v2andneg_risk_ctf_v2executions are unchanged.- A Protocol V2 combinatorial fill is not a large trade, so it never has an execution.
- The MCP tools that return these objects and the TypeScript SDK’s
CounterpartyExecutiontype name the new value.
exchange_v3 wherever you read exchange_family, or treat any value you do not know as another exchange.Market holders limits each account's uncached reads to 6 a minute
GET /api/v1/market/{condition_id}/holders now limits how many uncached markets each account can request. A request for a market whose holder list is not cached makes 0xinsider scan Polymarket, and each account may start 6 of these scans per minute, with bursts of up to 400. A request over that share returns 429 with error.code rate_limited, the new error.reason cold_read_limited, Retry-After, and error.retry_at.Before this change, an account could start as many scans as its per-minute request allowance allowed. On October 24, 2026, one account’s scans of uncached markets slowed holder reads for other callers.- Cached markets do not count and still answer, including a market that another caller has just read.
- The share is per account, across all of its keys, like the per-minute allowance.
- No scan runs for a refused request.
- On the 24 hours the share was sized on, no other account reached it.
429 rate_limited with Retry-After, and the new reason is additive.What to change: If you sweep many markets, wait for Retry-After on a 429 with reason cold_read_limited, or space uncached requests 10 seconds apart once your burst is spent.Explore keeps a market's 24-hour change while Polymarket's price history runs behind
GET /api/v1/markets/explore now keeps change_pct_24h and no_change_pct_24h for an open market while Polymarket’s minute price history is up to 10 minutes behind. Polymarket sometimes stops recording minute prices for every market at once, for 2 to 14 minutes. In the 24 hours to 18:00 UTC on October 24, 2026, that was 9.6% of the time.Before this change, both fields became null for every open market once the newest recorded minute was more than 2 minutes old.- During such a gap, the change covers the 24 hours to Polymarket’s latest recorded minute, not to the time of your request. The last point of
price_pointsandno_price_pointsis that minute. - A market whose price history stopped before the others, such as a resolved market, still sends
null. - When the history is more than 10 minutes behind, both fields are
null, as before.
null less often.What to change: Nothing. To show how current a change is, read the timestamp of the last point in price_points.A Challenger qualifying match's competition_label ends in ', Qualification'
GET /api/v1/pick-of-the-day now sends sports_context.competition_label for an ATP Challenger qualifying match with , Qualification at the end, for example Seoul, Qualification. Polymarket already labels ATP 250, ATP 500, and WTA qualifying this way, such as Erste Bank Open, Qualification.Before this change, a Challenger qualifying match had the same label as its main draw, for example Seoul. Polymarket marks these matches only in its eventMetadata.tennisFixtureSource field, with the value optic-challenger-qualifying.- A label that already names a qualifying draw is unchanged.
- Main-draw labels are unchanged.
competition_label, treat a label that ends in , Qualification as the qualifying draw of the tournament named before it.A national team's logo is now its official national flag as a same-origin SVG
GET /api/v1/pick-of-the-day now sends a national team’s sports_context team logo as its official national flag: a same-origin path such as /api/sports/team-logos/unl/esp.svg?v=e6ce1922eba61c4a. This covers 1,326 national-team rows across 41 competitions, for men, women, and youth sides.Before this change, those teams carried Polymarket’s raster flag or federation crest URL.- The flag is an SVG at the flag’s own aspect ratio, so draw it contained in a square slot, not cropped.
- Rows that are not exactly one country keep their previous artwork. These include Chinese Taipei, Northern Ireland, overseas territories, and bracket placeholders.
- A URL that a client cached before this change still serves the image it named.
logo against the API origin. Otherwise, resolve it against https://api.0xinsider.com.Team names in Pick of the Day sports_context use plain spaces
GET /api/v1/pick-of-the-day now sends label and full_name on each team in sports_context with ordinary spaces between words. Every Unicode space character, such as the no-break space U+00A0, becomes U+0020.Before this change the names kept the bytes Polymarket sends, and Polymarket sends some team names with a no-break space between words. On October 24, 2026, 2 of 33 AHL teams were sent that way: Cleveland Monsters and Grand Rapids Griffins. A no-break space makes the whole name one word, so a narrow layout broke it inside a word.The market’s own outcome labels and title are unchanged and can still hold the provider’s no-break space.Backward compatible. Only the space characters inside a few team names change.What to change: If you compare a team’s label or full_name with a market outcome label by exact string, treat any whitespace as a plain space on both sides first.Edge Hunter observations read a sport's pre-game holders only while someone asks
GET /api/v1/edge-hunter with view=observations now reads a sport’s pre-game wider_holder holders only while a wider_holder or emerging_pile request named that sport in the last 30 minutes. A request with no category counts for every sport. The default selection and admission=most_held_48h are counted apart, and in-play reads never stop.Before this change, every snapshot read the pre-game holders of every sport, whether or not anyone asked for them.- After 30 minutes with no request for a sport, the first request for it returns
503witherror.reason: read_model_warmingandRetry-After: 45. The retry returns the same rows as before. - A request with no category gets the same
503while any sport is in that state. - While a sport’s holders are not read, its admitted markets count in
coverage.capacity_limited_marketsand not incoverage.emitted_observations. - The rows, fields, ordering, and departures of a sport that someone reads are unchanged.
503 for you, because its Retry-After is under 60 seconds.What to change: Nothing for a client that retries read_model_warming after Retry-After. A client that reads a sport less often than every 30 minutes should expect one 503 before its first answer.The OpenAPI document marks nullable fields the OpenAPI 3.1 way
GET /api/v1/openapi.json now marks every field that can be null the way OpenAPI 3.1 defines: "type": ["string", "null"], or a oneOf with a {"type": "null"} branch. The document already declared "openapi": "3.1.0".Before this change, 370 schemas used the OpenAPI 3.0 keyword "nullable": true, which OpenAPI 3.1 does not have. A 3.1 validator or code generator ignores that keyword, so it read those fields as never null and rejected the null the API sends. One example is the always-null supersedes_pick_id on a Pick of the Day response with no entitled picks.- A nullable
enumnow listsnullas a member, for examplecategoryon Edge Hunter rows andgradeon large-trade webhook payloads. - A nullable object reference is now
"oneOf": [{"$ref": "..."}, {"type": "null"}]. yes_teamandno_teamin the Pick of the Daysports_contextwere declared in a form that generated clients read as nevernull. They are now nullable, as the API has always sent them.- The MCP tools’ output schemas use the same spelling.
- The SDK source in
0xinsider/0xinsidernow typesPickSportsContext.yes_teamandno_teamasPickSportsTeam | null, and the next@0xinsider/sdkrelease carries it. No other SDK type changes. The published 0.31.0 is unchanged.
null changed, and it now matches what the API sends.What to change: If you generate a client from the document, regenerate it and handle null on the fields it now types as nullable. With @0xinsider/sdk, check yes_team and no_team for null before you read them; they can already be null today.The neg-risk P&L correction no longer waits on markets outside sports and esports
On
GET /api/v1/trader/{address}, pnl.correction now publishes once every converted neg-risk market of the wallet that has a sports or esports event is measured. pnl.correction_pending is true only while one of those markets is still being checked.Before this change, every converted market of the wallet had to be measured first, sports or not. A wallet with many converted markets outside sports and esports could stay pending for weeks, with no correction on its sports and esports P&L either.- A converted market with no sports or esports event is no longer measured. An earlier measurement of one still counts in
amountandmarkets_measured. - The same applies to
pnl_correctionon leaderboard and trending wallet entries, and to the SDK’sPnlCorrection. - The fields, their types, and the
neg_risk_conversion_v1basis are unchanged.
pnl.correction_pending set. A wallet-wide amount can leave out part of the gap on markets outside sports and esports.Export snapshot volume, gap, and coverage are null when a day has no volume
On
GET /api/v1/trader/{address}/export, reconciliation.exported_activity_volume is now null when any of the wallet’s daily P&L rows has no volume. provider_activity_volume_gap and activity_volume_coverage are then null too. The export file’s summary.volume_reconciliation and the get_trader_export_snapshot MCP tool follow the same rule.Before this change, the sum skipped those days. Every day from 2026-10-23 on has no volume, so the sum was a subtotal of the earlier days, the gap read too high, and the coverage read too low.- A wallet with any daily P&L row from 2026-10-23 on now reads
nullfor all three fields. - A wallet whose daily P&L stops before 2026-10-23 keeps its volume, and its gap and coverage whenever
provider_lifetime_volumeis present. provider_lifetime_volume,exported_market_cost_basis, and every other field are unchanged.
exported_activity_volume as a number. The field was typed as always present.What to change: Accept null for exported_activity_volume and read it as unknown, not zero. Treat a null gap or coverage the same way.Holder wallet_age_days is whole days, so Pick of the Day revalidation returns 304
wallet_age_days on each holder from GET /api/v1/pick-of-the-day and GET /api/v1/market/{condition_id}/holders is now whole days since the wallet’s first trade, rounded down. A wallet that first traded 3.6 days ago reads 3.Before this change, the value was a fraction of days measured at the moment of your request, such as 250.49197916666665. It changed every second, so the Pick of the Day ETag changed on every request and If-None-Match never returned 304 Not Modified.- The value now changes once a day for each wallet. A Pick of the Day response keeps its
ETaguntil the picks or their holders change. is_new_walletis unchanged. It is stilltruewhen the first trade was under 30 days ago.- The field is still a JSON number, and it is still present only beside the other badge fields.
If-None-Match, you now get 304 responses between changes.Daily P&L entries leave out total_volume from October 23, 2026
On
GET /api/v1/trader/{address}/pnl, entries[].total_volume is left out for every UTC day from 2026-10-23 on. The get_trader_pnl MCP tool returns the same entries.From that day 0xinsider stores only part of a wallet’s fills on markets outside sports and esports, so it no longer knows the wallet’s total cash volume for the day. The field is left out rather than sent as a partial sum.- Days before 2026-10-23 keep their
total_volume. markets_traded,cumulative_profit,daily_change, and every other field are unchanged on all days.stats.total_volumeonGET /api/v1/trader/{address}, the wallet’s full-history volume from Polymarket, is unchanged.
total_volume over a range that reaches 2026-10-23, treat a missing value as unknown, not zero.Leaderboard entries carry the wallet's sports and esports record as in_scope
Each entry on
GET /api/v1/leaderboard now carries in_scope, the wallet’s record on sports and esports markets. It is the same object as pnl.in_scope on GET /api/v1/trader/{address}, as of the leaderboard’s last refresh.Before this change, a leaderboard entry carried only the wallet’s figures for every Polymarket market, so a client that wanted the sports and esports figure the grade ranks had to request each wallet’s profile.in_scopeholdsbasis,realized_pnl,markets,markets_resolved,win_rate,markets_out_of_scope, andas_of.in_scopeis left out until 0xinsider has computed the wallet’s record. A missingin_scopenever means zero.pnl,realized_pnl,pnl_correction, andwin_ratekeep the wallet’s figures for every market.
in_scope.realized_pnl and in_scope.win_rate.The games catalog adds UEFA Europa League and Conference League coverage
GET /api/v1/games now includes UEFA Europa League games as league=uel and UEFA Conference League games as league=uecl, both under sport=Soccer. coverage.leagues lists both keys. Use sport=Soccer&league=uel or sport=Soccer&league=uecl to list them, then GET /api/v1/games/{event_slug} for one game’s linked markets.Before this change, neither competition had its own scope. Their games came through the general Soccer scope, and a game’s league was the provider’s live-score code (col for a Conference League game) or null.GET /api/v1/edge-hunter now reports Conference League rows with market_context.league set to uecl. Before, it was europa-conference-league. A leagues=europa-conference-league selection still matches these rows, because selections normalize to the same key. Europa League rows already read uel.Backward compatible. The league coverage is additive. Request parameters and response fields are unchanged.What to change: If you compare league or market_context.league against col or europa-conference-league, compare against uecl instead.Wallet grades rank realized P&L on sports and esports markets only
grade and score on GET /api/v1/trader/{address}, POST /api/v1/traders/batch, and every other route that returns a wallet’s current grade now rank the wallet’s realized P&L on sports and esports markets. The resolved-market floors for S, A, and B count resolved sports and esports markets, and the win rate inside the grade counts decided sports and esports markets.Before this change, the grade ranked the wallet’s realized P&L on every Polymarket market, and the floors and the win rate counted every market.- The graded figure is the sports and esports share of Polymarket’s realized P&L for the wallet: the P&L of those markets, plus their share of rebates and of the difference between Polymarket’s wallet total and its per-market figures.
pnl.in_scope.realized_pnlonGET /api/v1/trader/{address}is the same figure. pnl.realized,pnl.correction.realized, and the other P&L fields keep Polymarket’s figures for the whole wallet.- Grades change at the first grading pass after the release, which runs about every hour. A wallet with little sports and esports activity can move down to C or lower.
- Historical grades from
GET /api/v1/trader/{address}/grade-atkeep the grade recorded on their date, so a grade from before this change ranked every market.
Export freshness_at and category_data_as_of say when the wallet's positions were last confirmed current
In the wallet dataset export from
POST /api/v1/trader/{address}/export, risk_metrics.*.freshness_at, category_performance.freshness_at and export_metadata.category_data_as_of now state when the wallet’s positions were last confirmed current. That is the older of two times: the last sync that read the wallet’s whole closed-position history, and the last complete read of its open positions.Before this change, these fields gave the time the wallet’s oldest unchanged market row was last written. A settled market is never rewritten, so a wallet that synced today could read months old. On October 22, 2026, 200 wallets synced in the previous 24 hours read a median of 175 days old.- A wallet whose syncs stall still reads old, so the fields still tell you when data is behind.
- Each wallet gets the new time at its next sync that reads its whole closed history. Until then, the fields keep the old time.
- The values the fields describe do not change.
Pick of the Day locked-only responses type supersedes_pick_id as a nullable string
GET /api/v1/pick-of-the-day now declares supersedes_pick_id as a deprecated nullable string on PickOfTheDayNoEntitledPicks, the response a paid caller gets when every published pick needs a higher plan. Every other Pick of the Day shape already declares it this way, and SDK 0.31.0 carries the new type.Before this change, the OpenAPI document declared the field as null only (type: ["null"], enum: [null]). The Go and Rust client generators cannot read that declaration, so those clients have not regenerated since October 12.- The API still sends
nullin this field on every response. - SDK 0.31.0 types the field
string | null. Earlier releases typed itnull. - The
get_pick_of_the_dayMCP output schema declares the same type after the next backend release. - The Go and Rust clients regenerate from the corrected document.
supersedes_pick_id to a variable typed null. Response data is unchanged.What to change: Nothing for most clients. In TypeScript, type the field string | null, or stop reading it and identify a pick by pick_id.API, SDK and MCP descriptions and examples cover sports and esports markets only
The OpenAPI document,
/agents.md, /llms-full.txt, the MCP server, SDK 0.30.0 and MCP package 3.6.2 now describe and give examples for sports and esports markets only. This follows the October 21 changes that limited the API to those markets.Before this change, several descriptions and examples still named categories and markets outside sports and esports: in rejection notes, in response examples and in the search example’s q.- The OpenAPI
info.descriptionstates the scope. A market, event or trade outside sports and esports answers404witherror.code: "not_found"anderror.reason: "market_out_of_scope", and you should not retry it. Acategoryoutside them answers400witherror.paramcategory. - Response examples for trader categories, trader context, sharp-money and smart-money flows, and monthly reports use sports markets. Search markets and the leaderboard examples use sports values, such as
q=lakersandcategory=Basketball. - The MCP tool
explore_marketsdescribescategoryas a sport or esports bucket, and the server instructions state the scope. Both serve after the next backend release. - SDK 0.30.0 adds types already in the API:
MarketOutOfScopeErrorfor the404above,pnl.in_scope(TraderPnlInScope),report.market_scope,product_scopeon trader exports, Edge Hunter’sadmission: "most_held_48h"anddepartures(EdgeHunterObservationDeparture), andcategory_avg_priceonMarketHolderandPickHolder. - The
@0xinsider/mcppackage 3.6.2 carries the sameexplore_marketstext.
MarketOutOfScopeError in SDK 0.30.0 and stop requesting that market.Webhook signatures can carry up to four candidates while 0xinsider rotates its signing key
The
x-0xinsider-signature header on webhook deliveries now carries one more v1=<hex> candidate while 0xinsider rotates the server key that every webhook signing secret is derived from. The extra candidate is signed with the secret you already hold, so your receiver keeps verifying through the rotation.Before this change, the header carried one candidate, or two during a staged rotation of your own secret.- Outside a rotation, nothing changes: one candidate, or two during your staged rotation.
- During our rotation: two candidates, or up to four when your staged rotation overlaps it.
- The first candidate is always the current secret’s.
verifySignaturein the TypeScript client already accepts any matching candidate.
x-0xinsider-signature on commas and accept the request when any candidate matches. During a rotation, rotate your webhook secret to move to the new key; see When 0xinsider rotates its signing key.Wallet trading styles count the wallet's sports and esports markets only
strategy_type on GET /api/v1/leaderboard, and strategy.strategy_type on GET /api/v1/trader/{address} and POST /api/v1/traders/batch with expand=strategy, now describe the wallet’s sports and esports markets only. The leaderboard’s strategy filter selects on the same styles.Before this change, the style counted every market 0xinsider stored for the wallet, in any category.- A wallet with fewer than 20 sports and esports markets is
unclassified, however many other markets it traded. - Both-side shares, fills per market, and category shares are measured over sports and esports markets, so
category_focusedanddiversifiedcompare sports and esports categories with each other. - Measured on October 22, 2026, 94,609 of 285,315 classified wallets change style, 67,219 of them to
unclassified. - Stored styles are rewritten in the background after the release, which takes several hours. Until a wallet’s style is rewritten, it still counts every market.
unclassified as fewer than 20 sports and esports markets or too little usable history.Positions board and wallet reads list sports and esports positions only
GET /api/v1/positions now lists positions on sports and esports markets only, on every read: the board, its min_grade pages, and wallet reads.Before this change, a request without category or condition_id listed open positions on every market 0xinsider tracks, such as politics and crypto. On October 21, 2026, 1,904 of the 2,000 largest open positions on the board were on such markets.- A
walletread returns that wallet’s sports and esports positions only. A wallet that holds no sports or esports position returns an empty list. - A sports market filed under another category is listed when 0xinsider has classified it as sports, by the same rule as the large-trade lists.
- Reads with
categoryorcondition_idare unchanged. They already refuse a category or market outside sports and esports. - Response fields, ordering, and the cursor format are unchanged. The
get_positionsMCP tool reads this route and follows the same rule.
wallet read.What to change: Expect no position on a market outside sports and esports. Positions on other markets are no longer available from this route.Trader exports hold sports and esports trades and markets only
POST /api/v1/trader/{address}/export now writes a file whose trades and markets are sports and esports markets only, the markets the wallet page lists. GET /api/v1/trader/{address}/export counts the same markets.Before this change, the file held every market and trade of the wallet.- The rule applies to the trades in every format (
json,ndjsonandcsv), tomarkets, and tocategory_performance.by_category. - A market is in scope when 0xinsider has classified it as a sports or esports market. A market that is not classified yet is left out.
trader.product_scope_pnlis new: the wallet’s sports and esports realized P&L, the figure the wallet page shows. It is omitted until it has been computed.pnl,summary, the rest oftrader,risk_metrics,quant_metrics,risk_summary, and the duration and hour buckets ofcategory_performancestill cover every market of the wallet.export_metadata.scope_notesays so in the file.- In the status response,
artifact.manifest.generation.product_scopeissports_esports_v1, andartifact.manifest.generation.source_watermarks.trades.coverageissports_esports_rows. - The snapshot adds
product_scope.counts.exported_markets,counts.estimated_trade_rows,counts.estimated_size_mb,reconciliation.exported_market_cost_basis,source_range.latest_trade_atandsource_range.latest_market_activity_atcount sports and esports markets only. - A job’s
total_tradesisnulluntil the file’s rows are known, and then equals the file’s trade rows. Before, it was an estimate set at submit. - A submit no longer returns a
readyfile written before this change. It queues a new job.
total_trades right after submit.What to change: Read artifact.manifest.generation.product_scope to tell a scoped file from an older one, and treat a null total_trades as unknown. A wallet with no sports or esports markets now exports a file with no trade rows.Trader context.md names the position breakdown as covering every market category
GET /api/v1/trader/{address}/context.md now titles its position section ## Position breakdown (synced markets, all Polymarket categories).Before this change, the heading was ## Position breakdown (synced markets). The counts and P&L under it were the same, and they include markets outside sports and esports.- The
position_summarydescription onGET /api/v1/trader/{address}/contextnow says it counts all Polymarket markets. - The
GET /api/v1/trader/{address}/pnldescription and theget_trader_pnlMCP tool now say the daily series covers all Polymarket markets. Polymarket reports this figure for the whole wallet, so it cannot be split per market.
context.md, match the new one, or match on the ## Position breakdown prefix.Edge Hunter wider_holder responses list cards that left before kickoff, and why
GET /api/v1/edge-hunter with view=observations&cohort=wider_holder now returns departures: each market whose card was in an earlier snapshot of the same selection, is not in this one, and has not kicked off. It works for the default selection and for admission=most_held_48h.Before this change, a card that left before kickoff stopped appearing, and the response did not say why.- Each entry has
condition_id,event_slug,category,admitted_by,game_start_time,last_observed_at,departed_atandreason. reasonuses the funnel’s terminal vocabulary.primary_slate_candidatemeans the market moved toview=signals, andsplit_holder_pilemeans its graded holders split.- An entry stays until its kickoff or until the card returns. While it stays, a reason that only says a read did not finish, such as
holder_deadline_unavailable, is replaced by the market’s later outcome; every other field, and any other reason, stays fixed. - The list holds at most 336 entries, newest first. It follows your
categoryand selectors and is part of theETag. - The field is omitted on
in_playandemerging_pile, and on a snapshot that could not establish its departures. - The SDK adds the
EdgeHunterObservationDeparturetype, and theget_edge_hunterMCP output schema adds the field.
departures entry, and treat a missing departures field as unknown.Large-trade, flag and market lists include sports markets filed under another category
GET /api/v1/large-trades, GET /api/v1/large-trades/history, their /api/v1/whale-trades aliases, GET /api/v1/events/feed/since, POST /api/v1/datasets/whale-trades, GET /api/v1/suspicious-trades with its /insider-radar alias, GET /api/v1/markets/explore and GET /api/v1/markets/search now include a sports or esports market that Polymarket files under another category. They use the same scope as the market routes.Before this change, these lists judged a market by its category alone. A market in a sports event but filed under another category, such as a Super Bowl MVP prop filed as Big Game, was left out of the lists, although its market and trade pages served it.- On October 21, 2026, this adds 19 markets and their 102 stored large trades, the newest from July 1, 2026.
- A market that enters or leaves the sports and esports scope reaches the lists within 10 minutes while it is open and for a week after it resolves, and within 160 minutes after that.
- These markets fall outside every sports and esports
categoryvalue, so they show only in a list without acategoryfilter. - A
mode=stablewalk of suspicious trades now also answers400witherror.reason: "cursor_expired"when a market with a flag enters or leaves the scope during the walk. - A
sincepoll does not return the older trades again. Read the list or history to get them.
cursor_expired, as before.Pick of the Day issues entry authorizations for picks released during a slow internal read
GET /api/v1/pick-of-the-day now issues an entry_authorization for a pick released while one of our internal reads is slow, when a recent copy of that data is available.Before this change, a slow internal read at release could publish a pick without entry_authorization, and automated clients skipped it.- Authorizations already issued are unchanged. A pick published without one stays without one.
- A pick can still publish without
entry_authorizationwhen no recent copy is available. policy_versionstays8, and response fields are unchanged.
entry_authorization is missing or expired.Trader reads add the sports and esports P&L and refuse non-sports categories and markets
GET /api/v1/trader/{address} and POST /api/v1/traders/batch now carry pnl.in_scope, the wallet’s sports and esports record. This is the P&L the 0xinsider profile now shows as its headline. Every other pnl field keeps its meaning and still covers all of the wallet’s Polymarket markets.pnl.in_scope holds these fields:realized_pnl: the wallet’s realized P&L on sports and esports markets, in USD, ornullwhen Polymarket publishes no realized figure for the wallet. It splits Polymarket’s realized P&L, with any publishedpnl.correction, by market and shares fees, refunds and rebates out by cost. A wallet that trades only sports keeps the full figure, and a wallet with no sports market gets 0.markets,markets_resolvedandwin_rate(0 to 1, ornull): the wallet’s sports and esports markets.markets_out_of_scope: how many of the wallet’s markets are outside sports and esports.basisnames the split rule, nowsports_esports_split_v1, andas_ofdates the figures.
pnl.in_scope is left out until 0xinsider has computed the wallet’s record. A missing object means the record is not ready yet, not a P&L of zero.Four routes also follow the sports and esports scope. 0xinsider now serves sports and esports markets only.GET /api/v1/trader/{address}/categorieslists sports and esports categories only. Acategoryoutside them, such asCryptoorPolitics, returns400withparam: "category". Before this change it returned200with that category’s record.GET /api/v1/trader/{address}/position-timelineandGET /api/v1/traders/{trader}/position-timelineanswer acondition_idoutside sports and esports with404,error.code: "not_found"anderror.reason: "market_out_of_scope". Before this change they returned the fills.GET /api/v1/positionsanswers the same404for such acondition_id, and the same400for such acategory. Without either filter, the board and wallet reads still list every market for now.
get_trader, batch_get_traders, get_trader_context, get_trader_categories, get_position_timeline, get_position_timeline_by_id and get_positions read these routes and follow the same rules. GET /api/v1/trader/{address}/context.md adds a line for the sports and esports realized P&L.Backward compatible for pnl.in_scope, which is additive. Breaking for clients that ask for a non-sports category or market on the other four routes.What to change: Read pnl.in_scope.realized_pnl for the sports and esports figure. Filter by a sport or esports category, and stop requesting a market that answers market_out_of_scope.Pick of the Day issues entry authorizations for high-priced picks it used to skip
GET /api/v1/pick-of-the-day now issues an entry_authorization for high-priced picks that could not get one before. For those picks, a newly issued max_entry_price can be up to 1 cent higher than before.Before this change, the price ceiling for a high-priced pick was rounded down to the market’s price increment, which could leave it below the lowest ask. Such a pick published without entry_authorization, and automated clients skipped it.- Authorizations already issued keep their recorded
max_entry_priceandexpires_at. A pick published without one stays without one. policy_versionstays8, and response fields are unchanged.- The Pick of the Day reference and the auto-buy guide now explain when
entry_authorizationis missing.
entry_authorization is missing or expired. This change needs no potd-trader upgrade.potd-trader v0.4.4 checks for new picks every minute by default
potd-trader v0.4.4 watch checks for newly released picks every minute when no release time is known, and prints that interval when it starts. Scheduled release times, Retry-After, and proof_pending_picks[].retry_at still set the next check when they are sooner.Before this change, WATCH_IDLE_MINUTES defaulted to 30, so a pick released without a scheduled time could be seen up to 30 minutes late.Backward compatible. A WATCH_IDLE_MINUTES value in your .env still wins, and spending limits and order guards are unchanged.What to change: Upgrade to v0.4.4. If your .env came from an older .env.example and sets WATCH_IDLE_MINUTES=30, set it to 1 or delete the line.Edge Hunter observations offer the most-held 48-hour wider_holder selection
GET /api/v1/edge-hunter with view=observations&cohort=wider_holder accepts a new parameter, admission=most_held_48h. It returns, per sport, up to 8 wider_holder markets that kick off within 48 hours, most graded holders first, then most volume, then soonest kickoff, with at most 4 per event. The selection is made again on every snapshot, so a market with more graded holders takes the place of one with fewer.Before this change, the observations view offered only the default selection: the 8 soonest kickoffs per sport plus up to 8 most-held markets within 24 hours, each kept until kickoff. The most-held 48-hour selection is the one the view used before October 17, 2026.- Every row of an
admission=most_held_48hresponse hasadmitted_by: "most_held_48h", a new enum value, and the response echoesadmissionat the top level. funnel,coverage,degraded, anddegradation_reasonsdescribe that selection.- Any other view or cohort returns
400witherror.param: "admission". Cursors andETagvalues bindadmission.
admission returns exactly what it did before, and no default row carries most_held_48h.What to change: Nothing. To keep a record on the pre-October 17 selection, add admission=most_held_48h to your cohort=wider_holder requests. A strict admitted_by enum check must accept most_held_48h on those responses.Combos serve combos whose every leg is a sports or esports market
GET /api/v1/combos/fills and GET /api/v1/combos/summary now leave out a combo with any leg on a market outside sports and esports. GET /api/v1/combos/{condition_id} answers such a combo 404 with error.code: "not_found" and error.reason: "market_out_of_scope". The MCP tools get_combo_fills, get_combos_summary and get_combo read these routes and follow the same rule. 0xinsider now serves sports and esports markets only.Before this change, a combo with a Politics, Geopolitics or Crypto leg was listed, counted and served. On October 21, 2026, 596 combos had such a leg: 663 of 1,578,764 taker fills, and 424 of the 4,738 combos in the live count.- Page sizes, cursors, offsets and
has_moredescribe the in-scope fills only. Cursors issued before the change stay valid. - The summary’s live count drops by the out-of-scope combos within one five-minute refresh.
- A combo whose every leg is a sports or esports market is unchanged: same fields, envelopes and status codes.
market_out_of_scope.Reports for periods ending on or after October 21, 2026 count sports and esports markets only
GET /api/v1/reports, GET /api/v1/reports/daily, GET /api/v1/reports/weekly, GET /api/v1/reports/monthly and the MCP report tools now build a report whose period ends on or after October 21, 2026 over sports and esports markets only: totals, categories, top_large_trades and grade_distribution leave out every other market. 0xinsider now serves sports and esports markets only.A report whose period ended earlier is a published record and does not change: same numbers, same snapshot.version.Every report body carries a new field, report.market_scope: sports_and_esports for a period ending on or after October 21, 2026, all_markets for an earlier one. On October 20, 2026, 54 of 408 large trades (13.2%) and 10.3% of large-trade volume were on markets outside sports and esports; for September 2026, 1,519 of 13,313 (11.4%).Backward compatible. The new field is additive, and no request changes. A weekly or monthly period that contains October 21, 2026 counts sports and esports only for the whole period, so its totals are lower than a sum of the earlier daily reports inside it.What to change: Read report.market_scope before comparing totals across October 21, 2026.Sharp-money flows and the leaderboard serve sports and esports only
GET /api/v1/markets/sharp-money-flows and its deprecated smart-money-flows alias now rank sports and esports markets only. On both, and on GET /api/v1/leaderboard, a category outside sports and esports answers 400 with error.code: "bad_request" and error.param: "category". GET /api/v1/coverage and its /platforms alias now say that coverage is sports and esports only; their response body is unchanged.Before this change, flows ranked markets in every category, and these routes accepted any category. On October 21, 2026, 84 of the 646 markets in the 7-day S/A/B flows ranking were outside sports and esports: $5.0M of $55.6M in ranked volume.- Use a sport or esports bucket for
category: Basketball, Football, Baseball, Hockey, MMA, Boxing, Soccer, Cricket, Golf, Tennis, Esports, Racing, Table Tennis, Pickleball, and the umbrella Sports. A league value such as NBA still resolves to its bucket; an emptycategorystill means every sport. - A flows cursor taken before this change can answer
cursor_expired, because the ranked set changed. Request the first page again. - Every sports and esports result is unchanged: same fields, envelopes, cursors and status codes.
category values. Expect flows to list sports and esports markets only.Large-trade lists, replay and datasets return trades on sports and esports markets only
GET /api/v1/large-trades (including since polls and sort=market_volume_share), GET /api/v1/large-trades/history, their /api/v1/whale-trades aliases, GET /api/v1/events/feed/since and POST /api/v1/datasets/whale-trades now leave out large trades on markets outside sports and esports. 0xinsider now serves sports and esports markets only.Before this change, these reads returned stored large trades in every category. On October 21, 2026, 10.5% of the previous 24 hours’ large trades and 26.2% of the 943,303 stored ones were on markets outside sports and esports.- On the list and history, a
categoryoutside sports and esports answers400witherror.code: "bad_request"anderror.param: "category", where it answered200. Use a sport or esports bucket: Basketball, Football, Baseball, Hockey, MMA, Boxing, Soccer, Cricket, Golf, Tennis, Esports, Racing, Table Tennis, Pickleball, or the umbrella Sports. - A dataset request whose
condition_idnames an out-of-scope market answers404witherror.code: "not_found"anderror.reason: "market_out_of_scope", and reserves no job. A dataset withoutcondition_idholds in-scope trades only, so its row count can be lower than before for the same window. - Pages,
has_more, cursors and replay positions describe the in-scope trades only. Cursors issued before the change stay valid. - Every sports and esports trade is unchanged: same fields, envelopes and status codes.
category values, and do not expect large trades on other markets from any list, replay or dataset.Large positions and suspicious trades list sports and esports markets only
GET /api/v1/large-positions and GET /api/v1/suspicious-trades, with its deprecated /insider-radar alias, now list positions and flags on sports and esports markets only. GET /api/v1/suspicious-trades/{id} and its /insider-radar/{id} alias answer 404 with error.code: "not_found" and error.reason: "market_out_of_scope" for a flag on a market outside them. 0xinsider now serves sports and esports markets only.From the same release, a trade on a market outside sports and esports is no longer scored, so it gets no new flag and no suspicious_trade_flagged webhook event.Before this change, both lists covered every Polymarket market. On October 21, 2026, 43 of the 51 rows on the first page of large positions, and 554 of the 1,114 stored flags, were on markets outside sports and esports.- On large positions, a
condition_idthat names a market outside sports and esports answers404 not_foundwitherror.reason: "market_out_of_scope", and acategoryvalue outside them answers400witherror.code: "bad_request"anderror.param: "category". An unknown but well-formedcondition_idstill returns an empty list. - Lists keep their cursors, ordering and page sizes; a page is never short because a row was left out.
- Every position and flag on a sports or esports market is unchanged: same fields, envelopes and status codes.
- The
reasonis terminal. It carries noRetry-After, and the answer does not change on a retry.
category values, and treat error.reason: "market_out_of_scope" as final for that market or flag. The @0xinsider/sdk client raises it as MarketOutOfScopeError, a NotFoundError.Market search, explore and batch flow serve sports and esports markets only
GET /api/v1/markets/search and GET /api/v1/markets/explore now return sports and esports markets only, and answer 400 with error.code: "bad_request" and error.param: "category" for a category outside them. POST /api/v1/markets/flow/batch and its /markets/intel/batch alias answer each out-of-scope item with its own market_out_of_scope error. 0xinsider now serves sports and esports markets only.Before this change, search and explore returned markets in every category, and a batch served flow for any market. On October 21, 2026, 30,055 of the 88,490 markets that explore and search could return were outside sports and esports.- Use a sport or esports bucket for
category: Basketball, Football, Baseball, Hockey, MMA, Boxing, Soccer, Cricket, Golf, Tennis, Esports, Racing, Table Tennis, Pickleball, and the umbrella Sports. Matching is case-insensitive; an emptycategorystill means every sport. - In a batch, an out-of-scope item has
status: "error",error.code: "not_found"anderror.reason: "market_out_of_scope". The other items and the200response are unchanged, and the item still counts one batch unit, like any other refused item. - Every sports and esports result is unchanged: same fields, envelopes, cursors and status codes.
category values, and treat a batch item’s error.reason: "market_out_of_scope" as final for that market.Large trades on markets outside sports and esports answer 404 market_out_of_scope, and no new ones are recorded
GET /api/v1/large-trades/{id}, its counterparty executions and makers pages, and their /api/v1/whale-trades aliases now answer 404 with error.code: "not_found" and error.reason: "market_out_of_scope" for a large trade whose market is outside sports and esports. 0xinsider now serves sports and esports markets only.From the same release, a large fill on a market outside sports and esports is no longer recorded as a large trade. It gets no wt_ id, no event on the stream or the event replay feed, and no large-trade webhook event.Before this change, these routes answered 200 for a large trade on any Polymarket market. In the 7 days to October 21, 2026, 356 of 3,373 new large trades were on markets outside sports and esports.- A well-formed id with no stored large trade still answers a plain
404 not_foundwith noreason. - Every large trade on a sports or esports market is unchanged: same fields, envelopes and status codes.
- The
reasonis terminal. It carries noRetry-After, and the answer does not change on a retry. - The large-trade list, history and dataset routes still return stored out-of-scope trades until a later release removes them. That release will get its own entry here.
error.reason: "market_out_of_scope" as final and stop requesting that trade. The @0xinsider/sdk client raises it as MarketOutOfScopeError, a NotFoundError.Market routes answer 404 market_out_of_scope for a market outside sports and esports
The six single-market routes now answer
404 with error.code: "not_found" and the new error.reason: "market_out_of_scope" for a market outside sports and esports: holders, flow, intel, snapshot, candles and context.md. 0xinsider now serves sports and esports markets only.Before this change, these routes answered 200 with data for any Polymarket market, including crypto, politics and other non-sports markets.- A market is in scope when Polymarket marks it as a sports market, or when any market in its Polymarket event is one.
- A condition id with no stored market still answers a plain
404 not_foundwith noreason. - Every in-scope answer is unchanged: same fields, envelopes and status codes.
- The
reasonis terminal. It carries noRetry-After; the answer does not change on a retry or under another URL for the same market.
error.reason: "market_out_of_scope" as final and stop requesting that market. The @0xinsider/sdk client raises it as MarketOutOfScopeError, a NotFoundError, from its next release.Pick of the Day voids a pick whose game is suspended or postponed past 72 hours
A published pick now settles
void when Polymarket reports its game suspended or postponed and the game has not completed 72 hours after the pick’s committed kickoff. The void is final: if the game resumes and its market resolves later, the pick stays void. The archive and the ledger report it as outcome: "void".Before this change, such a pick stayed pending until Polymarket resolved its market. The rules of those markets keep them open until the game is completed, which can be weeks or never. Pick 578, Rayo Vallecano de Madrid vs. Athletic Club on October 10, 2026, was suspended at 0-0 and still read pending ten days later.- The suspension or postponement comes from Polymarket’s own game status, never from a price.
- A void of this kind is treated like any other void: it counts in
void, and it is neither a win nor a loss.stake_usd,return_usd,return_per_100,payout_display, andunit_scoreare omitted, as for every void. resolved_atis the time the pick turned void. It does not move when the market resolves later, because the pick is not re-mapped.- A void from a market that settled 50-50 still follows a later correction of that market.
void was already a value of outcome.What to change: Nothing, unless you settle picks from the market yourself. Then treat a pick the API reports void as final, even if its market later resolves to a winner.