Changelog
API and product changes that affect integrations.
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.