API · Troubleshooting
Most Polymarket API errors have a one-line cause and a one-line fix — but the answers are scattered across GitHub issues. This page collects the errors developers actually hit on CLOB V2 / pUSD, with the cause, a minimal reproduction, and the fix in Python and Rust. Paste your error below to jump straight to it.
py-clob-client (latest 0.34.6) and
@polymarket/clob-client are archived / superseded and produce orders the
V2 exchange rejects. Move to py-clob-client-v2 (Python), @polymarket/clob-client-v2
(Node) or the official Rust client polymarket_client_sdk_v2. New projects can use the unified
beta SDKs (polymarket-client / @polymarket/client).order_version_mismatch
Cause. You signed a V1-shaped order (old EIP-712 Exchange domain
version "1", legacy fields) and posted it to the V2 exchange (domain
version "2"). On 28 April 2026 the order struct changed: nonce,
feeRateBps, taker and expiration were removed from the signed struct
and timestamp, metadata and builder were added. Almost always this
means you are still importing the V1 client.
Fix. Switch to the V2 SDK — it builds and signs the V2 struct for you.
pip install py-clob-client-v2 # V1 py-clob-client (0.34.x) is archived
from py_clob_client_v2 import ClobClient
client.create_and_post_order(order_args) # signs the V2 struct, domain "2"
// Cargo.toml: polymarket_client_sdk_v2 = "0.5" (official, repo rs-clob-client-v2)
use polymarket_client_sdk_v2::ClobClient;
Related: invalid signature, migrate v1 → v2.
not enough balance / allowance
Cause. Under V2 your funding wallet must approve the V2 exchange contracts to move your collateral and outcome tokens — and your collateral must be pUSD, not USDC.e. A buy needs a pUSD allowance; a sell needs a CTF (ERC-1155) approval. Missing either returns this error.
Fix. (1) Wrap USDC.e → pUSD, then (2) approve pUSD and the conditional tokens to the three V2 contracts:
- CTF Exchange (V2) —
0xE111180000d2663C0091e4f400237545B87B996B - Neg Risk CTF Exchange —
0xe2222d279d744050d28e00520010520000310F59 - Neg Risk Adapter —
0xd91E80cF2E7be2e162c6513ceD06f1dD0dA35296
0xC011a7E12a19f7B1f670d46F03B03f3342E82DFB ·
Conditional Tokens (CTF): 0x4D97DCd97eC945f40cF65F87097ACe5EA0476045Website users are auto-wrapped after a one-time approval; API-only traders call
CollateralOnramp.wrap() (0x93070a847efEf7F70739046A929D47a521F5B8ee) themselves.
maker address not allowed, please use the deposit wallet flow
Cause. You're signing with a POLY_1271 deposit wallet (signature type 3).
As of June 2026 the Python (py-clob-client-v2) and TypeScript (@polymarket/clob-client-v2)
clients have an open bug: L1 auth binds the API key to your EOA instead of the deposit wallet,
so the exchange rejects the order.
Fix. For deposit-wallet (type 3) trading today, use the official Rust client, which wraps the EIP-1271 signature correctly:
// Rust — authentication_builder().funder(deposit_wallet).signature_type(SignatureType::Poly1271)
Workaround without Rust: sign up via email/Magic, export the Magic wallet key and use
signature_type = POLY_PROXY (type 2) — it works but doesn't scale to many bots.
This is a moving bug — re-check Polymarket issues #70 (Python) and #65 (TS) for a fix.
the order signer address has to be the address of the API KEY
Cause. The wallet that signed the order doesn't match the wallet your API key was derived
for, or you didn't pass the right funder/signature type. Common with proxy and Gnosis-Safe
wallets when the signing key differs from the fund-holding address.
Fix. Derive the API key for the same wallet you sign with, and pass both the private
key and the funder address with the correct signature_type (1 = email/Magic proxy,
2 = Gnosis Safe, 3 = deposit wallet).
invalid signature
Cause. Usually one of: (a) signing the wrong EIP-712 domain — the V2 Exchange domain version
is "2" (the L1 ClobAuth domain stays "1"); (b) clock drift > ~60s between your
machine and the server; (c) a V1 client (see order_version_mismatch).
Fix. Use the V2 SDK so the domain/struct are correct, and sync your clock (NTP).
401 / invalid api key / PolyApiException
Cause. Missing or wrong L2 credentials (API key/secret/passphrase), or you never created them. Reading market data is keyless — this only affects authenticated calls (orders, your positions).
Fix. Create or derive your API credentials, then pass all three on authenticated requests:
# client.create_or_derive_api_key() -> api_key, api_secret, api_passphrase
INVALID_ORDER_MIN_TICK_SIZE
Cause. Your price isn't a multiple of the market's tick size (often 0.01, sometimes 0.001).
Fix. Fetch the market's tick size (GET /tick-size) and round your price to it
before signing.
FOK_ORDER_NOT_FILLED
Cause. A Fill-Or-Kill order couldn't be filled completely at your price against current resting liquidity, so it was killed (this is FOK working as intended, not a failure).
Fix. Read the book first and size to available depth, widen your price, or use GTC/FAK instead of FOK.
invalid amounts (decimals)
Cause. Amounts must respect decimal precision — maker amount to 2 decimals, taker amount to 4 decimals. Extra precision is rejected.
Fix. Round/quantize before signing; let the V2 SDK compute amounts from price × size.
Size lower than the minimum: 5
Cause. Orders below the minimum share size (5) are rejected.
Fix. Increase order size to ≥ 5 shares.
429 / throttled
Cause. You exceeded a sliding-window rate limit. V2 limits are high (CLOB ~9,000 / 10s;
/book,/price 1,500 / 10s; Gamma 4,000 / 10s; Data 1,000 / 10s) and over-limit
requests are throttled/queued, not hard-rejected — but a client-side limiter is still wise.
Fix. Add a token-bucket limiter and exponential backoff on 429.
Next: Authentication & wallets · CLOB API reference · API quickstart.

