This guide is for builders who still have a bot on py-clob-client-v2 / @polymarket/clob-client-v2 (or older V1 packages) and need the current recommended client path. Polymarket docs now point to the unified SDK (polymarket-client / @polymarket/client). The April 28, 2026 CLOB V2 protocol cutover is still the historical backdrop — this page keeps that context — but the actionable install and method map today is the unified cutover.

For agent builders: automate package uninstall → install, credential resume, and limit / post-only / paced batch placement behind a secure client. What you should not automate is shipping the owner private key into an agent runtime, inventing fee or tick values the SDK no longer asks for, or treating a superseded create_and_post_order call site as current.

Official sources: SDK Migration, Python SDK, Place Orders. Order-placement deep dive (GTC/GTD, FAK/FOK, batches, responses): polymarket-client place_limit_order — slug still says py-clob-client-create-order; that is intentional and unchanged. Auth debugging: Polymarket Auth Troubleshooting. Post-cutover V2 SDK error table (still useful for leftover V2 imports): py-clob-client-v2 Errors.

Last verified against Polymarket unified SDK docs + PyPI polymarket-client==0.9.0: September 2026.

Update (September 2026): Uninstall py-clob-client-v2 (and related builder packages); install polymarket-client (0.9.0 on PyPI as of 2026-09-04, Python >=3.11). Trading clients are AsyncSecureClient / SecureClient. Order methods: place_limit_order, create_limit_order, place_market_order, create_market_order, post_order, post_orders. TypeScript twin: uninstall @polymarket/clob-client-v2 (+ builder packages) → install @polymarket/client + viem; use createSecureClient / placeLimitOrder.

Old py-clob-client-v2Current polymarket-client
create_and_post_orderplace_limit_order
create_ordercreate_limit_order
create_and_post_market_orderplace_market_order
create_market_ordercreate_market_order (still exists)
post_orderpost_order
ClobClient + set_api_creds / two-step create_or_derive_api_keyAsyncSecureClient.create / SecureClient.create
OrderArgs / Side enumkeyword args; side="BUY" / "SELL" strings in official Python examples
PartialCreateOrderOptions(tick_size, neg_risk)resolved automatically by SDK

Two migrations, one bot

Treat these as stacked, not interchangeable:

  1. CLOB V2 protocol cutover (April 28, 2026) — Exchange contracts, EIP-712 Exchange domain version "2", pUSD collateral, redesigned order struct, resting orders wiped. V1 packages cannot sign valid V2 orders. Covered below as prior migration context.
  2. Unified SDK cutover (current recommended path) — one client covers CLOB + Gamma + Data + wallet/relayer flows that previously required separate CLOB, relayer, and builder-signing packages. Official migration doc: Migrate from previous SDKs.

If you never left V1, you still need both. If you already run on py-clob-client-v2 against production CLOB V2, you mainly need the unified package swap and method renames.


Current path: py-clob-client-v2polymarket-client (Python)

Install

pip uninstall -y py-clob-client-v2 py-builder-relayer-client py-builder-signing-sdk
pip install polymarket-client
uv remove py-clob-client-v2 py-builder-relayer-client py-builder-signing-sdk
uv add polymarket-client
poetry remove py-clob-client-v2 py-builder-relayer-client py-builder-signing-sdk
poetry add polymarket-client

Requires Python >=3.11. Interfaces:

InterfacePublic dataTrading and account
AsyncAsyncPublicClientAsyncSecureClient
SyncPublicClientSecureClient

Client construction

Previous V2 pattern (two-step ClobClient + create_or_derive_api_key):

# Historical — py-clob-client-v2
from py_clob_client_v2 import ClobClient

l1 = ClobClient(host="https://clob.polymarket.com", chain_id=137, key="<pk>")
creds = l1.create_or_derive_api_key()
client = ClobClient(
    host="https://clob.polymarket.com",
    chain_id=137,
    key="<pk>",
    creds=creds,
    signature_type=3,
    funder="<deposit-wallet>",
)

Unified pattern — create derives or creates CLOB credentials, resolves the account wallet, and configures signing:

import os

from polymarket import AsyncSecureClient

async with await AsyncSecureClient.create(
    private_key=os.environ["POLYMARKET_PRIVATE_KEY"],
) as client:
    ...

Omit wallet for the default Deposit Wallet flow. Pass wallet=... when reconnecting an existing account wallet. Sync twin: SecureClient.create(...).

Resume with stored credentials (same API key) when you already persisted them:

resumed = await AsyncSecureClient.create(
    private_key=os.environ["POLYMARKET_PRIVATE_KEY"],
    wallet=os.environ["POLYMARKET_WALLET_ADDRESS"],
    credentials=credentials,
)

Revoke the current API key with end_authentication() (returns a public client). Builder / Relayer API keys for gasless wallet actions move onto api_key= (BuilderApiKey / RelayerApiKey) at create time — see the official migration page for local vs remote builder signing.

Orders (limit, market, sign-then-post, batch)

One-step limit (omit expiration for GTC; Unix seconds for GTD):

response = await client.place_limit_order(
    token_id=yes_token_id,
    side="BUY",
    price="0.52",
    size="10",
)

Two-step sign then submit:

signed = await client.create_limit_order(
    token_id=yes_token_id,
    side="BUY",
    price="0.52",
    size="10",
)
response = await client.post_order(signed)

Market (FAK/FOK); user_usdc_balance becomes max_spend:

response = await client.place_market_order(
    token_id=yes_token_id,
    side="BUY",
    amount=10,
    max_spend=10,
    order_type="FOK",
)

Batch signed orders with post_orders([...]) (order type / post-only live on each signed order). Official Place Orders docs allow 1–15 signed orders per batch call.

Tick size, neg-risk routing, fees, and signing details are resolved by the SDK when you place — you do not pass PartialCreateOrderOptions anymore. For inspection after get_market:

tick_size = market.trading.minimum_tick_size
neg_risk = market.state.neg_risk

Builder attribution: pass builder_code= on place_limit_order (32-byte hex from Settings → Builders). Full GTC/GTD rules, post-only, estimate_market_price, response statuses, and settlement wait: place_limit_order guide.

Market data and account reads (rename highlights)

Previous (py-clob-client-v2)Unified (polymarket-client)
get_market("CONDITION_ID")await client.get_market(slug="MARKET_SLUG") (also id / URL forms in docs)
get_markets() page dictclient.list_markets(...) async paginator → .first_page()
get_tick_size / get_neg_risk / get_fee_rate_bpsread market.trading.minimum_tick_size, market.state.neg_risk, market.trading.fee_schedule
get_order_book(token_id)await client.get_order_book(token_id="...")
calculate_market_price(...)await client.estimate_market_price(...)
get_open_orders(...)client.list_open_orders(...) paginator
get_trades / get_trades_paginatedclient.list_account_trades(...)
get_balance_allowance(BalanceAllowanceParams(...))await client.get_balance_allowance(asset_type="COLLATERAL")
Separate relayer execute for split/merge/redeemsplit_position / merge_positions / redeem_positions on the secure client

Public-only bots can use AsyncPublicClient() without a private key. The unified clients also cover Gamma / Data flows that many bots previously called with raw requests.


Prior migration: CLOB V1 → CLOB V2 (April 28, 2026)

Still accurate as protocol history. Use this if you are auditing why an old bot broke, or if you are reading May 2026 field notes. Prefer the unified SDK section above for new edits.

What changed on the wire (and what did not)

Polymarket shipped, in one coordinated release: new on-chain Exchange contracts (CTF Exchange V2 + Neg Risk CTF Exchange V2), a rewritten CLOB matching backend, EIP-712 Exchange domain version "1""2", collateral pUSD (replacing USDC.e), a redesigned order struct, builder attribution on the order, and language-specific V2 SDK packages. Old V1 packages cannot sign valid V2 orders; resting orders were wiped at cutover.

What did not change then (and still holds): host URL clob.polymarket.com, Gamma (gamma-api.polymarket.com), Data API (data-api.polymarket.com), WebSocket hosts, and the L1/L2 API-key model (ClobAuthDomain stays at version "1" — you do not need to regenerate API key/secret/passphrase solely for the protocol bump). Read-only public CLOB paths (/book, /price, /midpoint, /spread) continued to work.

V1 → V2 package / import map (historical)

AreaV1V2 (py-clob-client-v2)
Installpip install py-clob-clientpip install py-clob-client-v2
Clientfrom py_clob_client.client import ClobClientfrom py_clob_client_v2 import ClobClient
Order typesOrderArgs, MarketOrderArgs, OrderType from clob_typessame names from py_clob_client_v2 + PartialCreateOrderOptions
SideBUY / SELL constantsSide.BUY / Side.SELL
Creds helpercreate_or_derive_api_creds()create_or_derive_api_key()

Order-struct field changes (still on the wire)

FieldV1V2+
fee_rate_bpsUser-settable; signed into the orderRemoved from the signed struct. Fees set by the protocol at match time.
nonceUser-settable uniquenessRemoved. Replaced by timestamp (ms).
takerUser-settableRemoved.
timestamp / metadata / buildern/aAdded (builder set via builder code).

Raw signers still need Exchange domain version "2" and V2 verifying contracts — see Contracts. Canonical addresses documented for standard / Neg Risk exchanges include 0xE111180000d2663C0091e4f400237545B87B996B and 0xe2222d279d744050d28e00520010520000310F59.

Signature types (wallet still matters)

ValueNameNotes
0EOADefault if omitted on older clients.
1POLY_PROXYMagic Link / Google login proxy wallets.
2GNOSIS_SAFEExisting Safe-based browser wallet flow.
3POLY_1271Deposit wallets / EIP-1271 path emphasized for new API users after V2.

Unified AsyncSecureClient.create resolves wallet + signing for you when you omit wallet (Deposit Wallet flow) or pass an existing wallet=. Details: POLY_1271 & Smart-Contract Wallets, Wallets and Authentication.

Collateral: pUSD

Trading collateral is pUSD, not USDC.e. UI users get a wrap path on first use; API-only wallets that never wrapped still need to move collateral into pUSD before allowance checks pass. See What Is pUSD? and Polymarket USD.

Builder attribution

Order attribution uses a public builder code on the signed order (not the old per-request HMAC POLY_BUILDER_* header set for attribution). Builder API keys remain relevant for gasless / relayer authorization on the unified client (BuilderApiKey / remote signing helpers) — that is separate from per-order builder_code.

Cutover day (historical)

Pre-cutover test host: https://clob-v2.polymarket.com, parallel with production V1. At ~11:00 UTC on April 28, 2026, V2 took over clob.polymarket.com, V1 stopped accepting orders, and resting orders were wiped (about an hour of downtime in contemporary reports). Production today is the standard CLOB host. Do not point new integrations at the old clob-v2 hostname.

Some V2-era clients exposed get_pre_migration_orders() for read-only reconciliation of wiped pre-cutover orders. Treat that as a historical audit helper, not a live trading API.


TypeScript: previous CLOB client-v2 to unified client

Official migration removes the previous CLOB client-v2, builder-relayer, and builder-signing packages, then adds the unified client package plus viem (see official SDK Migration for exact install commands per package manager).

Packages involved: @polymarket/clob-client-v2, @polymarket/builder-relayer-client, @polymarket/builder-signing-sdk@polymarket/client.

PreviousUnified
new ClobClient({ host, chain, ... }) read-onlycreatePublicClient()
Two-step createOrDeriveApiKey + secured ClobClientawait createSecureClient({ wallet, signer })
createAndPostOrderplaceLimitOrder
createOrder + postOrdercreateLimitOrder + postOrder
createAndPostMarketOrderplaceMarketOrder
postOrders([{ order, orderType }, ...])postOrders([signed, ...])

createSecureClient derives credentials and configures signing. Omit wallet for Deposit Wallet. Signer adapters include Viem (privateKey from @polymarket/client/viem), Privy, and Ethers v5. The earlier V2 ethers to viem rewrite on the old client-v2 package is superseded for new work — see ethers to viem migration only if you are still on that stack.


Rust: unified SDK in progress

Official docs: a unified Rust SDK is in progress. Until it ships, use polymarket_client_sdk_v2 0.7.0 (enable the clob feature for auth/trading). Deposit Wallet trading uses funder + SignatureType::Poly1271. Deploying deposit wallets / submitting wallet batches is not in that crate — use Direct API workflows for those. See SDK Migration — Rust and Polymarket Rust SDK Reference.


Before / after: minimal Python place path

On py-clob-client-v2 (superseded client)

from py_clob_client_v2 import (
    ClobClient, OrderArgs, OrderType, PartialCreateOrderOptions, Side,
)

l1 = ClobClient(host="https://clob.polymarket.com", chain_id=137, key=os.environ["PK"])
creds = l1.create_or_derive_api_key()
client = ClobClient(
    host="https://clob.polymarket.com", chain_id=137, key=os.environ["PK"],
    creds=creds, signature_type=3, funder=os.environ["FUNDER"],
)

resp = client.create_and_post_order(
    order_args=OrderArgs(token_id=token_id, price=0.52, size=10.0, side=Side.BUY),
    options=PartialCreateOrderOptions(tick_size="0.01"),
    order_type=OrderType.GTC,
)

On polymarket-client (current)

import asyncio
import os

from polymarket import AsyncSecureClient


async def main() -> None:
    async with await AsyncSecureClient.create(
        private_key=os.environ["POLYMARKET_PRIVATE_KEY"],
    ) as client:
        market = await client.get_market(slug="MARKET_SLUG")
        yes_token_id = market.outcomes.yes.token_id
        if yes_token_id is None:
            raise RuntimeError("YES token ID missing")

        response = await client.place_limit_order(
            token_id=yes_token_id,
            side="BUY",
            price="0.52",
            size="10",
        )
        if not response.ok:
            raise RuntimeError(f"{response.code}: {response.message}")
        print(response.order_id, response.status)


asyncio.run(main())

Things you can keep as-is

  • Host https://clob.polymarket.com — unchanged through both cutovers.
  • Gamma / Data API hosts — still valid; unified SDK can replace many direct calls with typed helpers.
  • WebSocket hosts — still documented under Polymarket realtime feeds; Python unified realtime is via async subscribe() (async clients only).
  • Existing CLOB API credentials — can be resumed into AsyncSecureClient.create(..., credentials=...) when the signer/wallet match; you are not forced to mint a new key solely because the package name changed.
  • Order lifetime vocabulary — GTC, GTD, FOK, FAK, post-only (post-only is not combined with FOK/FAK).
  • pUSD as collateral — still required for trading inventory.

Common gotchas (unified + leftover V2)

  • Still importing py_clob_client_v2 after installing polymarket-client. Overlapping mental models, wrong methods. Remove the old packages and fix imports to from polymarket import ....
  • Calling create_and_post_order / PartialCreateOrderOptions on the new client. Those are V2-era names. Use place_limit_order and let the SDK resolve tick / neg-risk.
  • Assuming Python chain_id renamed. On the old V2 client it did not (TS chainIdchain did). Unified Python create helpers do not ask you to pass host/chain for production defaults.
  • Leaving USDC.e unwrapped. Allowance failures until collateral is pUSD.
  • Owner key in the agent container. Prefer scoped session keys for Deposit Wallet trading when your threat model needs a non-owner signer (Session Keys).
  • Blind FOK on thin books / ignoring rate limits. Same operational failure modes as before; see rate limits and the create-order sibling.
  • Leftover V2 error messages (order_version_mismatch, dict-vs-attribute order books, removed get_balance / get_positions). Symptom table: py-clob-client-v2 Errors.

Agent compatibility

Safer automation

  • Scripted removal of py-clob-client-v2 (+ builder packages) and install of polymarket-client / the unified TypeScript client in CI or bootstrap
  • AsyncSecureClient.create / SecureClient.create with credentials resumed from a secret store (not committed)
  • Limit ladders, post_only=True, and post_orders batches within the documented 1–15 size
  • estimate_market_price plus max_price / min_price / max_spend before market orders
  • Scoped session keys for Deposit Wallet trading when you can keep the owner key off the bot host

Unsafe / account-burning patterns

  • Shipping the owner private key into an agent runtime, chat tool, or CI log
  • Hammering order endpoints past rate limits
  • Blind FOK into thin books
  • Treating delayed acceptance as a confirmed fill
  • Hard-coding fee bps or tick sizes the unified place APIs no longer take from you

Changelog

DateChange
May 25, 2026Initial publication as V1→V2 playbook (py-clob-client-v2, @polymarket/clob-client-v2, polymarket_client_sdk_v2).
September 7, 2026Targeted refresh: primary path is unified SDK (polymarket-client 0.9.0 / @polymarket/client); V1→V2 cutover retained as prior context; method rename table aligned with create-order sibling; agent compatibility section added.

Official Resources

AgentBets Guides

Where This Fits in the Agent Betting Stack

This guide is maintenance work at Layer 3 (Trading) of the Agent Betting Stack. After April 28, 2026 a V1 adapter cannot place; after the unified SDK push, a V2-only package is the wrong long-term dependency. Layer 4 strategies only matter if the execution adapter can still sign and post.

Greenfield bots: start at the Trading Bot Quickstart and the place_limit_order reference rather than replaying the full V1→V2 field list.


This guide is maintained by AgentBets.ai. Found an error or an SDK change we missed? Let us know on Twitter.

Not financial advice. Built for builders.