Changelog
API and product changes that affect integrations.
2026-10-21
Realtime fill events carry block_number. Every fill event on wss://ws.polyrank.app now includes the block of
its on-chain log next to tx_hash and log_index, so a client can put fills in chain order with
(block_number, log_index). The change is additive: no field was removed or renamed, and events published before it
do not carry the field. See Realtime → Fill events.
2026-10-20
The leaderboard presets are rebuilt on configurations that were measured as copy lists.
polyrank-defaultandpure-calibrator(Sharp Forecasters) now gate on a top-20% Brier skill score and a top-35% edge over the implied price;copy-lower-risk,copy-consistent,copy-ready-5k,copy-trade-liveandsmart-moneytake the configurations measured for them. Each description states its gates and its measured copy result, labelled where the evidence is thin or weak.- Merged:
profitable-calibrators→pure-calibrator,risk-adjusted-champion→copy-lower-risk,copy-trade-material→copy-trade-live. Retired from the leaderboard:hidden-gems,contrarian-edge,traders-inplay(they now servepolyrank-default). - No slug stops working:
GET /v1/rankings/preset/{slug},GET /v1/public/leaderboard?preset=and the agent preset routes serve the target board for an old slug and say so (preset_redirect/served_preset). The map isGET /v1/public/preset-redirects.
2026-10-05
Founding Trader reopens for launch, and the refund policy is stated in one sentence.
- Founding Trader: the first 250 seats get Pro at $23/mo or $230/yr while the subscription stays active. The
offer is open until 31 October 2026 (23:59 UTC) or until the 250 seats are taken, whichever comes first.
GET /v1/public/foundingcarries the live terms (eligible,seats_total,deadline); the site shows the offer only whileeligibleis true, always with both limits. - Refunds are for billing errors only: a duplicate charge, a charge after cancellation, or an amount that does not match the listed price. Payments are otherwise non-refundable; you can cancel at any time and keep access until the end of the period you paid for. See the Refund & Cancellation Policy.
- The pricing page opens on monthly prices. Annual (two months free) is one click away on the same toggle.
2026-09-28
Split, merge and redemption events are counted once, and 1.91M missing events are back. Some of our metrics read a copy of the position-events table (position splits, merges, conversions and redemptions). The copy was an append-only table fed on every insert, so a re-inserted event (a repair, a replay, a retried batch) was stored again instead of replacing itself. Since 12:03 UTC the copy keeps exactly one row per event:
- 7.23M duplicate rows are gone, across 32 months, almost all of them NegRiskAdapter events. Anything that summed them had counted those events twice.
- 1.91M events it never had are back. 1.88M are CTF splits, merges and redemptions on seven January days (2026-01-02, 05, 07, 09, 11, 13 and 15) that a May history re-sync wrote to the main table before the copy was being fed. The other 31.5k are July 2026 events the copy's feed dropped.
- Who moves: wallets with events on those January days, or with NegRiskAdapter activity, on the surfaces that read the copy. These are the trader and public routes' event-based fields and some period metrics. Headline P&L never read the copy, so it does not change.
- Between 12:03 and 12:20 UTC only, a reader that does not deduplicate saw about 13.8k September 2026 events twice, until the copy's catch-up was merged. The public pulse's "big wins", which sums redemptions over 6 hours, showed 304 wallet-market wins at double their amount ($283k in total) during that window. Since 12:20 the copy holds no duplicate.
2026-09-27
Retired exchange contracts no longer count as market participants. Polymarket's two retired V1 exchange
contracts, the CTF Exchange (0x4bfb41d5b3570defd03c39a9a4d8de6bd8b8982e) and the NegRisk CTF Exchange
(0xc5d563a36ae78145c45a50134d48a1215220f80a), still hold outcome tokens left over from before Polymarket's V3
migration. We had counted them as holders. Since 10:47 UTC they are excluded, like Polymarket's other protocol
contracts. On the 1,579 live markets where they held positions:
volume_weighted_yesin a market's consensus moved by 9.23 points on average; 1,327 markets moved by more than a point, at most 46.9.n_positionersfell by 3,158 in total. The first consensus snapshot after the change is 10:50 UTC.polyrank_consensus_yesdid not move, andtop10_smart_money_yesmoved on 3 markets.GET /v1/market/{id}/holdersno longer lists an exchange contract. Before the change, one was the largest holder of 779 live markets.- Open trader exposure (the coverage census, and the dashboards built on it) fell by $140.2M: the contracts' own inventory.
Neg-risk markets are labelled neg-risk. market_kind now reads negrisk for every market Polymarket's
NegRiskAdapter created. The indexer had labelled most of them binary by their outcome count: 2,967 carried
negrisk before, and 794,479 do now (2026-09-27). The resolution-risk score (/resolution-risk) is versioned
dr-2026-09-26.1. No weight changed, but its +8 "neg-risk multi-outcome" prior now applies to all of them: 643 markets
moved from low to elevated (267 still open), and none moved to high. Other readers of market_kind only
distinguish combo markets, so nothing else moves.
2026-09-20
Combo (parlay) markets are covered. Polymarket's V3 combo markets had no title, no category, no market page and no price anywhere on Polyrank: over the prior 30 days, 312,952 traded combo tokens ($77.3M, 15,266 wallets).
- Every combo now has a market row. Its title names each leg's market and its pick, e.g.
2-pick combo: Kentucky vs. Texas A&M (Texas A&M) · Will Sevilla FC win on 2026-09-19? (Yes). Itsmarket_categoryis the legs' shared category, orMulti-categorywhen the legs span categories. AMulti-categorycombo counts in overall rankings but never on a category board, and never becomes a trader'sbest_category_name. GET /v1/market/{id},GET /v1/public/market/{id}andGET /v1/agent/market/{id}return acomboobject for a combo market (nullotherwise). It holds the legs (market, pick, statusopen/won/lost/partial/unknown, and price) andyes_estimate, the leg-implied chance that every leg hits. Combo pages no longer 404.- An open combo's price is an estimate: the product of its legs' live prices, and exactly 0 once
a leg has lost. Combos have no order book. Positions carry an
is_comboflag so you can label such prices; open combo positions are now valued instead of reading $0. - Combo trades count toward a trader's
markets_traded, and combo traders' category metrics now use the combos' real categories (both from the next nightly board).
Positions in markets with no order book are valued at the last trade. Once a market's order book is gone (a game has ended and awaits settlement, or the market was delisted), an open position in it used to read $0 unrealized until settlement. It now carries the market's last trade price, shown as a stale mark with its real age.
A third-party exchange is no longer counted as Polymarket. Trades from a clone of Polymarket's exchange contract (settling in its own "DeepSage USD") had been indexed as Polymarket trades since 2026-08-31: 105,912 fills from 2,320 wallets that never traded on Polymarket. They are no longer ingested, and those wallets leave rankings and search after the next nightly board.
Categories. Markets with no category from Polymarket are classified by their titles more often (Fed decisions, rate hikes, legal cases, fights and more).
2026-09-19 (evening)
GET /v1/trader/{proxy}/activityno longer fails for large wallets (about 1 in 5 requests failed with a server error, shown as an empty feed).GET /v1/trader/{proxy}/trades: thenext_cursornow also encodes the fill's log index. A page that ended inside a transaction with several of the wallet's fills used to skip the rest of that transaction on the next page. Cursors issued before this change are still accepted.POST /v1/rankings/customno longer fails when a board weightshit_rate_vs_implied_oracle.
2026-09-19
A win is now any profit, and a break-even has its own status. If you read status on
positions or trades, or win_rate_pct, longest_win_streak, longest_loss_streak,
hit_rate_vs_implied or information_coefficient from ranking or trader responses, expect a
one-time shift with the 2026-09-19 nightly board.
- A resolved position counts as won when it finished in profit — any profit, compared at USDC's six decimals. Until now it had to finish more than $0.01 up, so a position that made a fraction of a cent (typically a share bought at 99.9¢ that paid $1.00) counted as not-won.
- A position that finished at exactly $0 is a resolved position that is not a win. On
positions and trades its
statusis the new valueBREAKEVEN(previouslyWONorLOSTby the side that won). Treat any status value you do not recognise as neutral. WON/LOSTbadges follow the same rule: any profit readsWON, any loss readsLOST, whichever outcome won. The old ±$0.01 band inside which the winning side decided the label is gone, so the badge and the win rate still never disagree about a position.- Streaks count every resolved market that finished up or down, however small, and skip only an exact break-even (before: results within $0.01 of zero were skipped).
- Unchanged: which positions count at all (a position under $1 of throughput that moved no more
than a cent is still dust and excluded), and
win_loss_pnl_ratio, whose averages still ignore results within $0.01 of zero. - Positions lists (
/v1/trader/{proxy}/positions,status=closedandstatus=all) now include every exited position the win rate counts: a position appears once it traded at least $1 (buys plus sells) or its P&L is beyond one cent. Before, an exited position had to be more than $0.01 up or down, so sub-cent wins and exact break-evens were counted inwin_rate_pctbut never listed. Expect longer closed lists for wallets with many small positions, and atotalthat grows to match. Withstatus=allthis also lists unresolved positions that were fully exited at about $0 after at least $1 of trading; they readCLOSEDand are not part of the win rate until their market resolves.
Measured on the data of 2026-09-18, the change raises the win rate of 578,183 wallets (median +7 percentage points) and changes a longest streak for 609,994.
2026-09-06
cohort_size changed meaning, and eligible_universe is new. If you read cohort_size
from a ranking response as a population figure, switch to eligible_universe.
cohort_sizeis now the wallets a board actually ranks — the post-gate count, equal tototal_rows. On a selective board that is in the low thousands.eligible_universe(new, optional) is the wallets eligible in the window before the board's own gates — the population, and the same number on every board.
Previously cohort_size carried the second meaning, which made every board report the same
~3.1M and understated how selective each one is. The change landed server-side on 2026-09-03;
this entry and the OpenAPI descriptions are catching the contract up to it.
eligible_universe is optional on purpose: a response served from a cache written by an older
API image will not carry it. Fall back to cohort_size rather than rendering zero.
2026-08-21 (later)
The leaderboard now shows the forecasting number it ranks on. The public board carries a calibration gate — every listed trader is a top-decile forecaster — but the table only ever showed P&L, win rate and volume. A Calibration column now sits between Score and P&L, showing each trader's calibration excess and its percentile.
Calibration excess measures forecasting edge against the market price at entry, not against a coin flip. That distinction is the whole point: raw Brier score rewards buying favourites, because near-certainties usually happen. Measured across entry-price deciles on 532,539 traders, the share clearing a top-quartile bar varies 12.9× on raw Brier and 1.5× on calibration excess. So the board ranks and displays the price-adjusted number, and raw Brier is never used to rank.
Lower is better, and the column says so. A trader at −1.20σ forecast better than
the price implied; a positive value is worse than the price.
Unmeasured is not zero. A trader below the 30-resolved-market minimum shows —
with the reason, or unranked if they have a score but not enough sample to be ranked.
They are never rendered as a zero or as a bottom rank.
Trader pages gain the same score with its explainer, an entry-price distribution (what prices this trader actually buys at, in six bands), and a forecast-vs-money verdict pairing "were they right" against "did they profit" — the two disagree on roughly 10% of positions.
API: GET /v1/public/leaderboard rows now carry calibration_excess_z and
calibration_excess_z_pctile. Both are nullable — null means unmeasured, and
must not be read as zero. No existing field changed.
2026-08-21
Forecasting-skill boards now score against the market price. The eight Brier-gated leaderboards rank on calibration excess — how far a trader's forecasts beat what the price already implied — instead of raw Brier score.
The old score rewarded buying favourites. If you only ever backed near-certainties at 95¢, you scored well: not because you forecast well, but because near-certainties usually happen. We measured the size of that bias by sorting traders into ten buckets by their average entry price and asking how each bucket fared on the gate. A price-fair score is flat across those buckets.
- Money Brier, the outgoing gate: mean gate percentile varied by 30.13 points across entry-price deciles, and the pass rate at a p75 cut varied 6.19× depending purely on what prices you traded (n = 825,974 ranked wallets).
- Calibration excess, the incoming gate: 9.07 points and 1.39× (n = 716,116). A statistic that is exactly fair by construction still shows ~7.4 points of spread, so this is close to the achievable floor.
This changes who appears, substantially. Across the eight boards, listings go from 9,086 to 8,332, and roughly half of currently listed traders are replaced. Most did nothing wrong and their own numbers have not changed — they move because the boards now measure something different.
The traders arriving are not cheap-lottery grinders, which was the obvious risk of a price-fair score. Measured on the same eight boards, seats held by wallets whose mean entry price is under 30¢ fall from 7.00% to 1.19%, and seats held by favourite-farmers (wallets entering more than half of at least 20 resolved positions above 85¢) fall from 21.70% to 14.62%. Both price extremes shrink at once.
Unchanged:
- P&L and trading boards. Realized P&L, win rate, ROI and every money metric are computed exactly as before. Only the forecasting gate moved.
contrarian-edgekeeps its existing gate. On that board specifically the new score performed worse: favourite-farmer share would have risen from 10.0% to 28.0%, because its incumbent gate was actively removing them. A board built on fading the crowd should not fill with people backing favourites, so it was left alone rather than swapped for consistency's sake.category-specialistkeeps its existing gate while a separate sample-size correction is verified.- No API field was added, removed or renamed.
GET /v1/rankingstakes the same parameters and returns the same shape; the membership of the eight affected presets is what changed.
2026-08-18
Position status now follows the money, in both directions. The status
field on GET /v1/trader/{proxy}/positions and
GET /v1/agent/trader/{proxy}/positions answers "did this position make
money" — not "did the side it held win".
Only half of that rule had ever shipped. A position on the winning side that
finished net negative was correctly downgraded to LOST, but the mirror case
was never written: sell a position at a profit before resolution, and if the
side you had already exited went on to lose, the row read LOST next to a
green realized P&L. A real example — 50 YES bought at 25¢ ($12.50), all 50 sold
at 46¢ ($23.00), +$10.50 realized, nothing held at resolution, market resolved
NO — was labelled LOST.
Over the 30 days of resolutions ending 2026-08-18, 668,010 positions held by
75,311 wallets carried a wrong LOST, covering $19.5M of realized profit
(measured against the canonical position engine). The half that already worked
was correcting 287,128 rows over the same window, so the missing half was 2.33×
more common.
What changes for you:
- A resolved position reads
WONwhen it finished more than $0.01 up andLOSTwhen it finished more than $0.01 down, whichever outcome won. Inside that ±$0.01 dust band the winning side still decides the label, so break-even rows do not flip. - That threshold is the same one
win_rate_pctuses, so a position's badge and the wallet's win rate can no longer disagree about the same position. REDEEMABLEis unchanged. It is a state — winnings resolved in your favour and not yet claimed — not a profit claim, so it is never overwritten by P&L.- Voided markets are unchanged:
INVALIDsettles both sides at $0.50, and those rows never readWON/LOSTon side. - Nothing was removed. Which outcome actually won is still on every row as
winner_outcome, andredeemableis stillstatus === "REDEEMABLE".
Not yet changed: status on the per-fill /trades feeds. A single fill has
no position-level P&L under average cost, so those rows still describe the side
they belong to. They will be reconciled with /positions in a follow-up; until
then, treat /positions as the authority on whether a position made money.
2026-08-18 (later)
brier and win_rate_pct can now be null on the agent rankings rail. Affects
POST /v1/agent/rankings/custom, GET /v1/agent/rankings/preset/{slug},
GET /v1/agent/rankings/published/{slug} and GET /v1/agent/leaderboard, and the
row schema published in the x402 Bazaar discovery document.
Previously a wallet with no resolved positions was served brier: 0 and
win_rate_pct: 0. A Brier of 0 is a perfect score, so un-measured wallets sorted
to the top of any "best calibrated" board that did not pass min_resolved — and 0%
was indistinguishable from a genuinely terrible record. Both now return null, which
is what the session-authed rail has always returned.
Action required for typed clients: if you generated types from the discovery
schema, brier and win_rate_pct widen from number to number | null. Treat
null as "not measured" and exclude those wallets rather than defaulting them to 0.
A measured 0 still means exactly what it says and is passed through unchanged.
Ordering is unaffected — it happens in the database, not in this mapping.
Also relabelled, no shape change: the per-market "consensus" is described
throughout as holder average entry — the Brier-weighted average price current
holders paid for YES. It is a cost basis, not a forecast, and measured against
realised outcomes it does not beat the market mid. Field names are unchanged.
flow/cohort is now described as tagged-wallet flow, split by Polyrank
track-record tag rather than by "skill": most tagged wallets qualify on size or on
contrarian profit, not on forecasting.
2026-06-11
Webhooks: production events are live. market.resolved and
signal.smart_money now fire for real — market.resolved within ~2 minutes
of the on-chain resolution, signal.smart_money in real time when a
smart-money-tagged wallet takes a $5,000+ fill. Per-subscription
filter_json filters (condition, trader, signal type, tags, min size) are
honored at emission. See Webhooks for payloads. trader.fill
remains deferred (use the realtime WebSocket for per-fill
streaming). The agent-tier GET /v1/agent/signals/smart-money feed is
populated by the same pipeline.
Four new agent endpoints. The routes announced as "coming soon" are now
live and priced in /x402/info:
GET /v1/agent/trader/{proxy}/playbook— $0.01GET /v1/agent/market/{conditionId}/flow— $0.005POST /v1/agent/rankings/custom— $0.05 (the composite ranking engine, same config shape as the in-app Ranking Builder)GET /v1/agent/rankings/preset/{slug}— $0.01
Trader addresses are now normalized to EIP-55 checksum on every agent route —
lowercase addresses no longer return not_found.
2026-06-10
x402 wire format is now spec-official. The agent tier speaks the official x402 V1 wire format end-to-end:
402bodies are{x402Version: 1, error, accepts}with wire network names (base) and theextraEIP-712 domain — official SDKs (@x402/fetch,x402-axios, Pythonx402) now work out of the box.X-PAYMENTaccepts the official payload; the legacy flat Polyrank encoding ({scheme, network: "base-mainnet", signature, authorization}) still works during a deprecation window. Migrate now — the legacy encoding and thex402: "0.1"body aliases will be removed.- Settlement now happens before the response and returns the
X-PAYMENT-RESPONSEreceipt header with the on-chain tx hash. Failed settlement returns402and never charges you.
Pricing table cleanup. Four announced-but-unimplemented agent routes
(trader playbook, market flow, custom rankings, preset rankings) are
removed from /x402/info and the 402 pricing until their handlers ship.
docs.polyrank.app launched — this site: x402 guide, full generated API reference, MCP, WSS, webhooks, billing.
2026-06-09
- Public API launched: anonymous
/v1/public/*namespace (leaderboard, trader, calibration, market, pulse, founding) +llms.txt. - x402 agent tier live on Base mainnet (5 endpoints).
- MCP server
@polyrank/mcpbuilt — see MCP. Now published to the public npm registry (npx -y @polyrank/mcpworks; latest 0.2.0). - Founding Trader offer: Pro at $23/mo for the first 250 seats.