Guide

Polymarket V2 migration: what changed and what it means for your data

Polymarket moved production trading to CLOB V2 on April 28, 2026: new collateral, a new order struct, fees collected from takers at match time, and every order book rebuilt from scratch. This guide separates what actually changed for order-book data and backtests from what stayed the same, and walks through the migration a Python data pipeline needs.

What this guide covers

  • CLOB V2 went live on April 28, 2026 — V1 SDKs and V1-signed orders stopped working
  • Order books were cleared at the cutover: resting orders canceled, balances and positions carried over
  • Collateral moved from USDC.e to pUSD, an ERC-20 redeemable 1:1 for native USDC
  • V2 fees are taker-only and set at match time; V1's embedded feeRateBps is gone from signed orders

What V2 changed at the platform level

Polymarket switched production trading to the CLOB V2 engine on April 28, 2026, after roughly an hour of trading suspension. The upgrade replaced the exchange contracts behind the order book, migrated settlement collateral to a new token, and changed how orders are signed and fees are collected. It is the largest single change to the platform's trading stack since the central limit order book launched.

At the cutover, matching was stopped, all resting limit orders were canceled, and every order book was rebuilt from scratch. Account balances and open positions carried over automatically at the snapshot block, and conditional token IDs did not change. Programmatic traders running pre-V2 clients were effectively locked out of production with HTTP 503 cancel-only responses until their code was migrated.

The collateral change was invisible in the web app but is mandatory for API operators. Web-interface traders had their USDC.e balances auto-converted to pUSD, Polymarket's new ERC-20 token (six decimals, redeemable 1:1 for native USDC). API traders must wrap USDC.e into pUSD themselves before placing V2 orders and approve the new exchange contracts before they can trade.

Polymarket CLOB V1 vs V2
LayerV1 (before April 28, 2026)V2 (production since April 28, 2026)
CollateralUSDC.e, the bridged USDC tokenpUSD, a USDC-backed ERC-20 on Polygon
Python SDKpy-clob-clientpy-clob-client-v2
TypeScript SDK@polymarket/clob-client@polymarket/clob-client-v2
Order structnonce, expiration, taker, feeRateBpstimestamp (ms), metadata, builder
EIP-712 exchange domainversion “1”version “2”
Feesembedded in the signed orderoperator-set at match time, takers only
Feesmaker and taker both paidmakers pay zero

What V2 means for order-book data and backtests

For data consumers the notable result is how little changed underneath. Order-book prices are still quoted 0–1, the snapshot shape (price levels with sizes, best bid first and best ask first) is unchanged, and conditional token IDs were stable across the cutover. PolyOrderbooks archives span the migration, so a market that traded before and after April 28 reads as one continuous sequence of 1-second L2 snapshots.

What changed is friction, not liquidity. V2 removed the nonce and balance validation paths that caused failed fills, but it did not change market depth. Spreads, order-book depth and slippage behavior are structurally the same after the upgrade: if a book was thin before, it is thin after. A migration explainer that blamed V2 for new slippage, or promised V2 fixed it, would be describing something that did not happen.

The one place backtests genuinely break is the fee model. V1 embedded a maker/taker fee in the signed order; V2 collects platform fees from takers only, at match time. A strategy replayed across the cutover should apply V1 fee semantics before April 28, 2026 and V2's taker-only cost after it — otherwise the backtest reports P&L that no actual fill on either side of the boundary could have produced.

Because the quoted prices in archived order books did not change, no re-mapping of condition IDs, token IDs or price scales is needed. The adjustment is purely about cost modeling. That makes the V2 boundary a metadata concern for your pipeline, not a data-format concern.

Migrating a Python trading or data pipeline

The mechanical part is small: replace V1 imports with their v2 equivalents, switch to the options-object constructor (chain, not chainId), drop nonce and feeRateBps from order construction, add a millisecond timestamp for order uniqueness, and move builder attribution into the signed order instead of the old HMAC headers.

Collateral handling is the part most bots miss. Before placing any V2 order you must wrap USDC.e into pUSD through the collateral onramp and approve the V2 exchange contracts — including the negative-risk exchange if you trade event markets. Several reported cutover failures were bots attaching the V1 collateral address to a V2 signature. Test with a minimum-sized order before resuming production volume.

Data pipelines that only read order books need none of this. If you consume historical snapshots from an archive rather than placing orders, the only V2-related change is knowing where the fee-regime boundary sits so cost modeling in backtests stays honest.

from datetime import datetime, timezone

import requests

# The V2 cutover was April 28, 2026, UTC. Use the date in code,
# not a hard-coded epoch, so your pipeline stays readable.
V2_CUTOVER = int(datetime(2026, 4, 28, tzinfo=timezone.utc).timestamp())

BASE = "https://api.polyorderbooks.com/v1"
HEADERS = {"X-API-Key": "your-key"}

slug = "btc-updown-5m-1787486400"
r = requests.get(
    f"{BASE}/markets/{slug}/books",
    headers=HEADERS,
    params={"start_ts": 1787486400, "end_ts": 1787486700, "resolution": "1s"},
)
r.raise_for_status()

# Tag each snapshot with the fee regime active at that moment.
for snap in r.json():
    regime = "v2" if snap["timestamp"] >= V2_CUTOVER else "v1"
    best_bid = snap["bids"][0]["price"] if snap["bids"] else None
    print(f"t={snap['timestamp']} regime={regime} bid={best_bid}")

The V2 fee model under the hood

V2 fees are protocol-set per market and charged to takers at match time; makers never pay. The documented model scales the fee with p × (1 − p) of the order price rather than a flat embedded rate, so the same order size can cost differently on a 0.90 contract than on a 0.50 one.

Do not hard-code fee parameters. Poll getClobMarketInfo(conditionId) at runtime for the per-market fee, tick size and minimum order size; the values change over a market's life. This guide deliberately quotes no platform-wide fee number, because there is no stable one to quote — measure it from the endpoint for the market you actually trade, and re-measure before every campaign.

Code examples

from datetime import datetime, timezone

import requests

# The V2 cutover was April 28, 2026, UTC. Use the date in code,
# not a hard-coded epoch, so your pipeline stays readable.
V2_CUTOVER = int(datetime(2026, 4, 28, tzinfo=timezone.utc).timestamp())

BASE = "https://api.polyorderbooks.com/v1"
HEADERS = {"X-API-Key": "your-key"}

slug = "btc-updown-5m-1787486400"
r = requests.get(
    f"{BASE}/markets/{slug}/books",
    headers=HEADERS,
    params={"start_ts": 1787486400, "end_ts": 1787486700, "resolution": "1s"},
)
r.raise_for_status()

# Tag each snapshot with the fee regime active at that moment.
for snap in r.json():
    regime = "v2" if snap["timestamp"] >= V2_CUTOVER else "v1"
    best_bid = snap["bids"][0]["price"] if snap["bids"] else None
    print(f"t={snap['timestamp']} regime={regime} bid={best_bid}")

Free tier

The Starter plan is free, includes order books, prices, and metrics at 1-second resolution, with 3 days of history, 60 requests/min, 1,000/day, 1 free AI backtest, and 3 strategy backtests. No credit card required.

Paid data windows from $19/mo extend history to 30–120 days at higher throughput. Backtest AI add-on is +$19/mo or standalone at $29/mo.

FAQ

Was Polymarket V2 a breaking change for order books?

Yes, at the cutover: matching stopped, all resting limit orders were canceled, and every order book was rebuilt. Account balances and open positions carried over automatically, and conditional token IDs did not change.

Does my historical order-book dataset break across the V2 cutover?

No. Prices stay quoted 0-1, the L2 snapshot shape is unchanged, and archives read as one continuous series. The only adjustment is fee modeling: apply V1 fee semantics before April 28, 2026 and V2 taker-only fees after it.

Do I need py-clob-client-v2 or @polymarket/clob-client-v2 to trade?

Yes. V1 packages and V1-signed orders are no longer accepted on production; pre-V2 clients received HTTP 503 cancel-only responses. The constructor also changed to an options object with chain instead of chainId.

Is collateral still USDC on Polymarket?

You still deposit and withdraw USDC, but settle on-chain in pUSD, Polymarket's ERC-20 redeemable 1:1 for native USDC. API traders must wrap USDC.e into pUSD before placing V2 orders and approve the V2 exchange contracts.

Did Polymarket V2 reduce slippage?

No. V2 fixed nonce- and balance-related failed fills, but it did not change order-book depth. Spreads and slippage are structurally the same after the upgrade.