2026-04-25 — Pricing section retired: candles deduplicated, “Market Card” introduced
The “Pricing” sidebar section has been removed. It contained two endpoints:GET /v1/stats/{token_id}— kept, renamed to Market Card, moved further down the sidebar (just above “System”). This one is genuinely useful: a single call returns the condition_id, outcomes, neg-risk flag, end date, current orderbook liquidity, 24h OHLCV summary, and last price. Saves you from chaining 3–4 calls when you just need a market overview tile.GET /v1/candles/{token_id}— removed from documentation. It was an in-memory rolling buffer with no historical depth, no pagination, no VWAP, and no buy/sell split. UseGET /v2/onchain/candles/{token_id}instead — same OHLCV plus VWAP, volume in shares, trade count, full history, and pagination. The endpoint itself still responds on the API for backward compatibility.
2026-04-25 — Wallet endpoints reorganized: V1 wallet endpoints removed from documentation
The “Wallets” and “Onchain” sidebar sections have been merged into a single section called Wallets / Positions / Onchain. All wallet, position, and trade endpoints now live in one place — the V2 onchain endpoints. What changed in the docs: The seven legacy V1 wallet/market endpoints have been removed from the documentation sidebar. They were inferior duplicates of the V2 onchain equivalents — three of them returned empty or error responses, and the rest lacked PnL, average-price, current-price, and market-status fields that the V2 versions provide directly from chain data.
Important — backward compatibility preserved:
The V1 endpoints still respond on the API. We have not turned them off. If you have integrations hitting the legacy paths, they continue to work exactly as before — we just stopped surfacing them in the documentation because the V2 onchain replacements are strictly better. You should migrate, but you don’t have to migrate today.
Why V2 onchain is better:
V1 wallet endpoints returned mostly social-flavored fields (bio, profile picture, pseudonym). V2 onchain endpoints return rich trading-relevant fields:
avg_price, realized_pnl, unrealized_pnl, current_price, total_bought, market_status, order_hash, fee, maker_amount, taker_amount, condition_id, and more. Same data your equity curve, leaderboard, and PnL endpoints already use.
2026-04-25 — Equity Curve endpoint: faster default + four new query parameters
The/v2/trader/{wallet}/equity endpoint is faster, more flexible, and more accurate.
Default is now realized-only. The curve is built from completed P&L by default — the locked-in result of every closed position, partial sell, and resolution. Same query, same numbers, every time. Whales return in 1–2 seconds (was 8+).
If you want mark-to-market on currently-open positions (the old behavior), pass include_unrealized=1. That path is still supported, just opt-in now because it adds latency and makes responses non-deterministic as live prices move.
Four new optional query parameters:
All four compose. Example — fast realized-only curve over the wallet’s last 50 markets in early April:
markets_count (distinct outcome groups in the curve), applied_filters (echoes what was applied, useful for debugging), and partial (true if the request hit the 10-second server-side cap).
Coverage fix. Wallets with more than 500 lifetime trades previously had positions whose first-trade timestamp wasn’t found, causing those positions to be incorrectly stamped at “now” on the curve. The endpoint now walks all relevant trade history and falls back to sibling-token and redemption timestamps for positions acquired through USDC splits. Curves are dramatically more accurate for active traders.
Full reference: /api-reference/enriched/equity-curve.
2026-04-24 — Fee Escrow V2 live on Polygon (pUSD collateral, V2 CLOB)
We’ve deployed a V2 variant of the Fee Escrow contract so platforms building on the V2 CLOB can charge fees in pUSD (V2’s native collateral) instead of USDC.e. Both V1 and V2 are live and fully supported — there is no migration. If you’re already running V1, nothing changes. FeeEscrow V2 (new):
FeeEscrow V1 (unchanged):
The contracts have byte-identical calldata, identical function signatures, and identical semantics. The only functional differences are the collateral token and the domain name / version. The
FeeAuth typed-data struct is unchanged.
Opting into V2 today:
The cosigner accepts an escrow_contract field in fee_auth. Absent or set to the V1 address = V1 (default). Set to the V2 address = V2. Sign the FeeAuth against the V2 domain when using V2.
exchangeVersion to V2 in your TraderConfig and the SDK automatically signs FeeAuth against the V2 domain, reads nonces from the V2 contract, approves pUSD against the V2 FeeEscrow during ensureReady(), and tells the cosigner to route to the V2 operator. Install:
exchangeVersion (or set it to V1) and everything keeps working exactly as before.
Validation: 8/8 end-to-end fork tests pass against the deployed V2 contract, exercising pullFee + distribute (30/70 treasury/affiliate split) + refund + 72-hour claimRefund + every revert path (expired deadline, wrong nonce, tampered signature). The test impersonates a real on-chain pUSD whale to fund the payer. Contract bytecode is a strict 2-change diff from V1 (collateral address + domain strings).
Full guide: /guides/fee-escrow.
2026-04-21 (late) — Unrealized P&L and market status on positions
The/v2/onchain/positions and /v2/wallets/{address}/positions/onchain endpoints now return unrealized P&L, the current market price, and a status flag per position — so you don’t have to fetch prices separately or special-case resolved markets in client code.
New per-position fields:
unrealized_pnl— paper P&L on the held size at the current price. For resolved markets, uses the settlement price (1.0 for winners, 0.0 for losers). For live markets, uses the current market price. Returns 0 whensize = 0.current_price— the price used to computeunrealized_pnl.nullwhensize = 0or no price is available.market_status— one oflive,resolved-win,resolved-loss, orclosed. Lets you tell apart a live-tradable holding from a resolved-but-never-redeemed position without looking up the market separately.
/v2/wallets/{address}/positions/onchain:
total_unrealized_pnltotal_pnl—total_realized_pnl + total_unrealized_pnl. This is the number that matches the “Profit” value shown on a Polymarket profile page.
2026-04-21 (late) — Gasless Safe wrap/unwrap via the Polymarket relayer
Patch release.wrapToPolyUsd / unwrapFromPolyUsd (and their Python/Rust equivalents) now route through the Polymarket relayer automatically when called on a Safe or Proxy wallet — the flow ensureReady already uses. Previously these helpers sent the transaction directly from the EOA, which failed for Safe wallets because the funds live in the Safe, not on the EOA, and the EOA has no MATIC for gas.
Install:
- TS: wrap
0xde6c02c3..., unwrap0x006cd3dd... - Python: wrap
0x7de53811..., unwrap0xccf9cf32... - Rust: wrap
0xd80af0f4..., unwrap0xd21d6ad6...
status: 0x1, funded by third-party relayer EOAs — your EOA only signs the Safe execTransaction EIP-712 payload.
Requirements for Safe wrap/unwrap: pass builderCredentials in TraderConfig. The SDK uses your Polymarket builder HMAC key to authenticate the relayer submit. Mint one at polymarket.com/settings?tab=builder.
Tip — avoid stale-cache order rejection after wrap: after wrapToPolyUsd(), the V2 CLOB’s cached balance view is stale for a few seconds. If you place an order immediately, the CLOB can return a cryptic "error parsing fee rate bps" instead of the actual “balance not yet visible”. Call await trader.refreshBalanceAllowance() before the order, or wait ~3 seconds. This is why we don’t auto-refresh in wrap — not every wrap is followed by an immediate order.
Also in this patch:
- Rust: fixed
encode_unwrapselector (was0x39f47693, correct value is0x8cc7104f). All Rust V2 unwraps prior to 0.12.1 hit the wrong contract function and reverted on-chain. - Rust:
get_polyusd_balance()/get_usdce_balance()now read the funder address (Safe) instead of the EOA. Previously they always returned 0 for Safe-wallet users. - Python:
relayer.pymodule added with a minimal Python port of@polymarket/builder-relayer-client. Implements EIP-712 Safe tx hashing, EIP-191 personal_sign viaeth_account, builder HMAC headers, and/submit+/transactionpolling.
2026-04-21 — SDK V2 order flow hardening (all three SDKs)
End-to-end V2 order placement verified live onclob-v2.polymarket.com across all three SDKs. Matched fills tagged with your builder code now appear in the V2 CLOB’s /builder/trades attribution feed.
Install:
- V2 approvals now include the V1
NegRiskAdapterin the spender list. The V2 CLOB’s balance-allowance check monitors this address alongside the two V2 exchanges — orders without this approval were rejected with"not enough balance / allowance". - New methods:
refreshBalanceAllowance()/getBalanceAllowance(). The V2 CLOB maintains a cached balance-allowance view per API key;ensureReady()now auto-refreshes it after setting V2 approvals so the first order after onboarding goes through. - Amount math hardened against float-precision edge cases. Raw-units now derived via string-based decimal conversion instead of
Math.trunc(x * 1e6)(TS) /(x * 1_000_000.0) as u64(Rust), which could truncate toN-1for prices that round-trip badly through float. - V2 order body now matches
@polymarket/clob-client-v2exactly — addstaker,postOnly,deferExecfields to the POST payload. checkBalance()is V2-aware — reads pUSD on V2, USDC.e on V1. Previously always read USDC.e.- Market neg-risk detection fix (TS). The old check treated every market as neg-risk (truthiness of the response object rather than its
neg_riskfield), which signed orders against the wrong exchange on standard markets.
trader.order(...) signature is unchanged; if you’re on V2 and your orders were going through before, they still will. If you had a custom ensureReady-equivalent flow, you may now drop the manual /balance-allowance/update call — ensureReady() handles it on fresh V2 approvals.
The full V2 wire format, required approvals, fee math, and common failure modes are documented in each SDK at src/trading/V2_ORDER_FLOW.md (TS, Rust) / polynode/trading/V2_ORDER_FLOW.md (Python).
End-to-end verification (from each public registry, fresh sandbox, real V2 orders against clob-v2.polymarket.com):
Each sandbox pulled from the public registry, imported the SDK, placed a real V2 GTC BUY with builder attribution, confirmed
status: "live" from the V2 CLOB, then cancelled. No local source overrides, no pre-compiled artifacts — same install path a new user follows.
Docs fix also shipped today: the V2 section of /sdks/trading now inlines ensureReady / ensure_ready so a V2-first reader who pastes only that block hits a copy-paste runnable flow. Previously the snippet silently assumed the reader had already gone through the Quick Start section.
2026-04-20 — CLOB v2 API launched
New paid REST namespace/clobv2/* exposing every Polymarket CLOB v2 fill, position, builder, and neg-risk event.
11 endpoints, all enriched with market metadata (question, slug, outcome, image, condition_id) inline:
GET /clobv2/trades— global fills, filterable by wallet/builder/market/time/sizeGET /clobv2/positions— every open/closed v2 positionGET /clobv2/candles/{token_id}— OHLCV at 1m/5m/15m/1h/4h/1d with VWAP + buy/sell splitGET /clobv2/wallets/{address}/trades— per-wallet fill history withsideGET /clobv2/markets/{token_id}/{trades,volume,orderbook}— per-outcome aggregatesGET /clobv2/builders— v2 builder leaderboard (v2-exclusive)GET /clobv2/neg-risk/events{,/{parent_id}/children}— multi-outcome event drilldownGET /clobv2/volume/hourly— platform-wide hourly volume buckets
count, pagination.{limit,offset,has_more}, and rate-limit headers. Paid tier required; free-tier keys receive 402. See the overview for auth + numeric-precision conventions.
/v2/onchain/* enrichment restored
Trades / wallet-trades / market-trades / market-volume / candles on the legacy /v2/onchain/* endpoints now carry market, market_slug, outcome, image, and condition_id inline again. These fields had been quietly lost during a backend refactor.
2026-04-19 — Expanded orderbook wire format + Rust SDK 0.11.0
The orderbook WebSocket now delivers PM’s full per-level payload so you can maintain a tick-accurate local book without REST polling. Verified at 100% best-bid / 100% best-ask across 50 concurrent markets. What’s new in theprice_change message
Every entry in the assets array now includes four extra fields:
size— the absolute size at that level after the change."0"means the level was removed.side—"BUY"(affects bids) or"SELL"(affects asks)best_bid,best_ask— best bid/ask on the asset after the change
{asset_id, price} are unaffected — the new fields are additive. Multiple distinct levels on the same asset may now appear in one batch; repeat hits on the same (asset_id, price, side) within the 250ms coalesce window still merge to last-write-wins.
See the orderbook message reference for the full field list.
Rust SDK 0.11.0
PriceChangeAssetnow carriessize,side,best_bid,best_ask- New
LocalOrderbook::apply_price_change(&PriceChange)— apply incremental updates directly to your local book OrderbookEngineautomatically appliesprice_changeevents to its shared state so everyEngineViewstays tick-accurateOrderbookUpdate::LastTradePrice(BookTrade)— executed-trade events now deserialize cleanly (previously dropped)
OrderbookUpdate will need to handle the new LastTradePrice variant — add a _ => {} arm or match it explicitly.
2026-04-19 — V2-ready SDKs released (Rust 0.9.0, TypeScript 0.8.0, Python 0.8.0)
All three polynode trading SDKs are now wire-compatible with the Polymarket V2 exchange ahead of the April 28, 2026 cutover. Upgrade before then. V1 orders submitted after cutover will be rejected withorder_version_mismatch.
What changed (all three SDKs):
- V2 CLOB POST body now includes
"expiration": "0"to match@polymarket/clob-client-v2’s wire format OrderParamsnow exposes abuilderfield (bytes32). Pass your builder code on each order to attribute trades on-chain. Defaults to zero (no attribution). Mint your V2 builder code at polymarket.com/settings?tab=builder- All V2 order placement paths live-verified against
clob-v2.polymarket.com
OrderParams added a required struct field. If you construct OrderParams { ... } explicitly without ..Default::default(), add builder: None to your literal. No code change required if you use struct update syntax.
See the V2 Migration Guide for the full cutover checklist, the single-line switch, and a troubleshooting reference for common V2 errors.
2026-04-18 — Rust SDK 0.8.1: batch orderbook API
New: batch + all-tracked queries
Every per-token orderbook method onOrderbookEngine and EngineView now has a batch and an all-tracked variant. One read lock, one round-trip, results returned as a HashMap<String, T> keyed by token ID.
New: detect inactive markets
Each tracked token now records when its local copy was last touched. Use it to find markets that have stopped moving.New: direct state access
engine.state() returns the underlying Arc<RwLock<LocalOrderbook>> so callers can hold the lock and walk the full state themselves — useful for snapshotting all tokens at one consistent moment or building custom views.
Install
engine.midpoint(id), engine.book(id), etc.) are unchanged. This release is purely additive.
2026-04-17 — Unrealized P&L + redemption fix
New: unrealized_pnl field on positions
Every position returned by /v2/onchain/positions now includes an unrealized_pnl field showing the paper profit or loss on remaining open shares.
- Resolved markets: uses the final settlement price (0 for losers)
- Active markets: uses the current market price, refreshed every 15 minutes
Fixed: realized P&L for redeemed positions
Positions that were closed via onchain payout redemption (rather than selling on the orderbook) now correctly reflect their realized P&L. Previously, these showedrealized_pnl: 0 even when the position had a gain or loss.

