Polymarket’s CLOB API uses a layered authentication system that trips up almost every developer on first attempt. The errors are cryptic, the wallet architecture is unusual, and getting even one parameter wrong means silent 401s or misleading error messages.
This guide is the definitive reference for Polymarket API authentication. Whether you’re staring at INVALID_SIGNATURE for the tenth time or trying to figure out why your funder address keeps getting rejected, everything you need to debug is here.
Last verified against Polymarket’s API: March 2026.
TL;DR
Most Polymarket auth errors come from three things: using the wrong signatureType for your wallet, passing your signing address instead of your proxy wallet as the funder, or working with stale credentials after a nonce collision. This guide covers every POLY_* header, all three wallet types and when to use each, a complete error reference table, and a step-by-step debugging checklist that will resolve the vast majority of authentication failures.
The Five POLY_* Headers
Every authenticated (L2) endpoint on the Polymarket CLOB API requires exactly five custom headers. If any one is missing or incorrect, the request fails.
| Header | Contains | Example |
|---|---|---|
| POLY_ADDRESS | Your Polygon signer address (the wallet that signs requests) | 0x1a2B3c4D5e6F7a8B9c0D1e2F3a4B5c6D7e8F9a0b |
| POLY_SIGNATURE | HMAC-SHA256 signature of the request body and timestamp | a1b2c3d4e5f6... (hex-encoded) |
| POLY_TIMESTAMP | Current UNIX timestamp in seconds | 1741564800 |
| POLY_API_KEY | Your derived API key (the apiKey value from credential derivation) | a1b2c3d4-e5f6-7890-abcd-ef1234567890 |
| POLY_PASSPHRASE | Your derived API passphrase (the passphrase value from credential derivation) | randomPassphraseString |
These headers are only required for L2 endpoints — authenticated operations like placing orders, canceling orders, and managing positions. Public endpoints (market data, order books, prices) do not require authentication.
The POLY_SIGNATURE is computed as an HMAC-SHA256 of the request timestamp, method, path, and body using your API secret as the key. The SDK clients handle this computation automatically, so you typically only need to worry about it if you are making raw HTTP requests.
Signature Types Explained
The signatureType parameter tells the API how your wallet is structured and how to verify your signatures. Using the wrong type is the single most common cause of INVALID_SIGNATURE errors.
| Value | Name | Wallet Type | Notes |
|---|---|---|---|
| 0 | EOA | MetaMask, hardware wallets, standard Ethereum wallets | Signs directly with private key. Requires POL for gas. |
| 1 | POLY_PROXY | Magic Link / email login wallets | Custom proxy wallet for Magic Link users only. |
| 2 | GNOSIS_SAFE | Gnosis Safe multisig proxy wallet | Most common type. Used by the majority of Polymarket accounts. |
Type 0 — EOA (MetaMask, Hardware Wallets)
EOA (Externally Owned Account) is a standard Ethereum wallet where your private key directly controls the address. When you sign a message or transaction, the signature comes from the key itself with no proxy layer in between.
With type 0, your signing address and your funder address are the same address. You do not need to pass a separate funder parameter because there is no proxy wallet — the wallet that signs is the wallet that holds your funds.
EOA wallets require POL (the Polygon native token) for gas fees. If you are building a bot with a type 0 wallet, make sure the wallet is funded with both USDC (for trading) and POL (for transaction gas).
Type 1 — POLY_PROXY (Magic Link / Email Login)
POLY_PROXY is a custom proxy wallet type used exclusively by users who signed up for Polymarket via Magic Link (email-based login). These users have a proxy wallet that was created during the Magic Link onboarding flow.
If you logged into Polymarket using an email address rather than connecting a browser wallet, you are a type 1 user. To use the API, you need to export your private key from Magic Link and import it into your bot or script. The signing key and the proxy wallet address are separate — your private key signs requests, but your funds live at the proxy address.
Type 2 — GNOSIS_SAFE (Most Common)
GNOSIS_SAFE is the most common wallet type for Polymarket users. When you connect a wallet (such as MetaMask) to Polymarket.com for the first time, the platform automatically deploys a Gnosis Safe proxy contract that becomes your trading wallet.
With type 2, there are two distinct addresses:
- Signing key address — the private key you export from your wallet (MetaMask, etc.)
- Proxy/funder address — the Gnosis Safe contract address that holds your USDC funds
Your private key authorizes transactions, but the proxy contract is the entity that actually holds and moves funds on the exchange. This separation is why the funder parameter exists and why getting it wrong causes Invalid Funder Address errors.
Funder Address
The funder is the proxy wallet address that holds your trading funds on Polymarket. It is the address displayed on your Polymarket profile at polymarket.com/settings.
When Is It Required?
- Type 0 (EOA): Not required. Your signing address is your funder address.
- Type 1 (POLY_PROXY): Required. Your Magic Link signing key is different from the proxy address that holds funds.
- Type 2 (GNOSIS_SAFE): Required. Your MetaMask signing key is different from the Gnosis Safe proxy address that holds funds.
How to Find It
- Log in to polymarket.com
- Navigate to Settings (polymarket.com/settings)
- The wallet address displayed on your profile page is your proxy/funder address
The Most Common Mistake
Developers frequently pass their MetaMask address (the signing key address) as the funder. This is incorrect for types 1 and 2. The funder must be the proxy wallet address — the one Polymarket displays on your profile — not the address of the private key you are signing with.
If you see Invalid Funder Address, this mismatch is almost certainly the cause.
Error Reference
| Error | Cause | Fix |
|---|---|---|
| INVALID_SIGNATURE | Wrong signatureType for your wallet type, incorrect private key, or malformed key string | Verify your signatureType matches your wallet (0 for EOA, 1 for Magic Link, 2 for Gnosis Safe). Confirm the private key is correct and includes the 0x prefix. |
| NONCE_ALREADY_USED | The nonce provided was previously used to derive API credentials (replay protection) | Re-derive your API credentials with a fresh nonce by calling create_or_derive_api_creds() again. Each derivation requires a unique nonce. |
| Invalid Funder Address | The funder address does not match the proxy wallet registered to your signing key | Use the address displayed at polymarket.com/settings. Do not use your MetaMask/signing key address. |
| 401 Unauthorized | API credentials are expired, revoked, or were never properly initialized | Re-derive credentials using create_or_derive_api_creds() and re-initialize your client with the new apiKey, apiSecret, and passphrase. |
| Clock drift (intermittent 401) | The POLY_TIMESTAMP header is too far from the server’s current time | Sync your system clock. You can check the server’s time with GET /server-time on the CLOB API and compare. |
Debugging Ambiguous Errors
Some errors are more ambiguous than they appear:
- INVALID_SIGNATURE with a correct key — Almost always means the
signatureTypeis wrong. Try type 2 first (it covers the majority of accounts). - Intermittent 401s that work on retry — Usually clock drift. Even a few seconds of timestamp skew can cause sporadic failures.
- 401 immediately after credential derivation — The client was not re-initialized with the new credentials. Make sure you pass the derived
apiKey,apiSecret, andpassphraseback into the client constructor.
Deriving API Credentials
Before you can make authenticated requests, you must derive your API credentials. This is a one-time operation (per nonce) that produces an apiKey, apiSecret, and passphrase. These three values, along with your private key and funder address, are everything you need.
Python (py_clob_client)
from py_clob_client.client import ClobClient
from py_clob_client.clob_types import ApiCreds
client = ClobClient(
host="https://clob.polymarket.com",
chain_id=137,
key="YOUR_PRIVATE_KEY",
signature_type=2, # GNOSIS_SAFE for most users
funder="YOUR_PROXY_WALLET_ADDRESS"
)
# Derive or create API credentials
creds = client.create_or_derive_api_creds()
print(f"API Key: {creds.api_key}")
print(f"Secret: {creds.api_secret}")
print(f"Passphrase: {creds.api_passphrase}")
# Re-initialize client with derived credentials
client = ClobClient(
host="https://clob.polymarket.com",
chain_id=137,
key="YOUR_PRIVATE_KEY",
signature_type=2,
funder="YOUR_PROXY_WALLET_ADDRESS",
creds=ApiCreds(
api_key=creds.api_key,
api_secret=creds.api_secret,
api_passphrase=creds.api_passphrase
)
)
Important: You must re-initialize the ClobClient with the derived credentials. The first client instance (without creds) can only derive credentials — it cannot make authenticated trading requests until the credentials are passed in.
TypeScript (@polymarket/clob-client)
import { ClobClient } from "@polymarket/clob-client";
import { ethers } from "ethers";
const wallet = new ethers.Wallet("YOUR_PRIVATE_KEY");
const client = new ClobClient(
"https://clob.polymarket.com",
137,
wallet,
undefined, // creds - will be derived
2, // signatureType: GNOSIS_SAFE
"YOUR_PROXY_WALLET_ADDRESS" // funder
);
// Derive API credentials
const creds = await client.createOrDeriveApiKey();
console.log("API Key:", creds.apiKey);
console.log("Secret:", creds.secret);
console.log("Passphrase:", creds.passphrase);
After deriving credentials in TypeScript, create a new ClobClient instance and pass the credentials object as the fourth constructor argument to make authenticated requests.
Storing Credentials
Once derived, you should store the apiKey, apiSecret, and passphrase securely (environment variables, a secrets manager, or an encrypted config file). You do not need to re-derive them on every run — only when they expire, are revoked, or you encounter persistent INVALID_SIGNATURE errors that re-derivation resolves.
Proxy Wallet Architecture
Understanding Polymarket’s proxy wallet system is essential for debugging authentication issues. Here is how the architecture works:
Automatic deployment. Proxy wallets are deployed automatically the first time a user logs into Polymarket.com. If you have never logged into the web interface, your proxy wallet does not exist yet, and API authentication will fail. You must log in at least once before using the API.
The relationship chain:
Private Key → Signing Address → Proxy/Funder Address
(you hold) (derived from key) (deployed by Polymarket)
By wallet type:
- EOA (type 0): Signing address = funder address. One address does everything. No proxy contract involved.
- POLY_PROXY (type 1): Signing key is your exported Magic Link key. The proxy address is a separate contract deployed during Magic Link onboarding.
- GNOSIS_SAFE (type 2): Signing key is your MetaMask/wallet private key. The proxy address is a Gnosis Safe contract deployed by Polymarket on your first login.
Key takeaway: For types 1 and 2, there is always a separation between the key that signs and the address that holds funds. The signing key authorizes actions; the proxy address is where USDC balances and positions actually live. When the API asks for a funder, it wants the proxy address — not your signing key address.
Finding your proxy address: Go to polymarket.com/settings. The address shown there is your proxy/funder address.
Debugging Checklist
When authentication fails, work through this checklist in order:
- Verify your wallet type and use the correct
signatureType(0 for EOA, 1 for Magic Link, 2 for Gnosis Safe). If unsure, try type 2 first — it is the most common. - For types 1 and 2, confirm your funder address matches polymarket.com/settings. Do not use your MetaMask address or signing key address as the funder.
- Check that your private key is correctly formatted with the
0xprefix. Some wallet exports omit the prefix, which causes silent failures. - Verify your system clock is synced. Timestamp drift causes intermittent 401 errors that appear random. Compare your local time against
GET /server-timeon the CLOB API. - Re-derive API credentials if you get persistent
INVALID_SIGNATUREerrors. Callcreate_or_derive_api_creds()and update your stored credentials. - Ensure you have logged into polymarket.com at least once. The proxy wallet must be deployed before the API will accept your credentials. There is no way to deploy it programmatically.
- If using a new nonce, make sure it has not been used before. Nonce reuse triggers
NONCE_ALREADY_USED. Each credential derivation consumes a unique nonce.
Polymarket US Authentication
Polymarket US uses a completely different authentication system than the Global API covered in this guide. The US platform uses Ed25519 signatures instead of the EIP-712/HMAC system described above. The header names, credential derivation flow, and signing process are all different.
If you are building for the US market or need to support both platforms, see the Polymarket US vs. Global API Guide for a complete comparison of the two authentication systems.
Frequently Asked Questions
What are the five POLY headers required for Polymarket API authentication?
The five L2 headers are: POLY_ADDRESS (your Polygon signer address), POLY_SIGNATURE (HMAC signature of the request), POLY_TIMESTAMP (current UNIX timestamp), POLY_API_KEY (your derived API key), and POLY_PASSPHRASE (your derived passphrase). All five are required for every authenticated trading endpoint on the CLOB API. Public endpoints like market data and order book queries do not require these headers.
What does INVALID_SIGNATURE mean in the Polymarket API?
INVALID_SIGNATURE means the API could not verify your request signature. The three most common causes are: using the wrong signatureType for your wallet (for example, passing type 0 when you should be using type 2), using an incorrect or improperly formatted private key, or having corrupted credentials that need to be re-derived. Start by verifying your signatureType — EOA wallets use type 0, Magic Link wallets use type 1, and Gnosis Safe proxy wallets (the most common) use type 2.
What is the funder address in Polymarket API?
The funder is the proxy wallet address that holds your trading funds. It is the wallet address displayed on your Polymarket.com profile at polymarket.com/settings. For proxy wallet types (1 and 2), the funder address is different from your signing key address. A common mistake is passing your MetaMask address as the funder — this will fail because the API expects the proxy wallet address, not the signing key address.
How do I fix NONCE_ALREADY_USED error on Polymarket?
NONCE_ALREADY_USED means the nonce you provided was previously used to create an API key. Nonces are consumed during credential derivation as a replay protection mechanism. To fix this, generate a new nonce and re-derive your API credentials by calling create_or_derive_api_creds() again. The SDK handles nonce generation automatically, so simply calling the derivation function again should resolve it.
What is the difference between signatureType 0, 1, and 2?
Type 0 (EOA) is for standard Ethereum wallets like MetaMask where your private key directly controls the address — the signing address and funder address are the same. Type 1 (POLY_PROXY) is for Magic Link email login users who have a custom proxy wallet created during the email-based onboarding flow. Type 2 (GNOSIS_SAFE) is for Gnosis Safe multisig proxy wallets and is the most common type — this is what gets deployed automatically when you connect a wallet to Polymarket.com for the first time.
See Also
- Polymarket API: The Complete Developer Guide — Full API reference
- Polymarket US vs. Global API — Dual-stack auth comparison
- py_clob_client Reference — Python SDK method reference
- Polymarket TypeScript SDK Reference — TypeScript SDK reference
- Polymarket Rate Limits Guide — Rate limit numbers and retry strategies
- Prediction Market API Reference — Cross-platform API comparison
- Security Best Practices — Protecting API keys
This guide is maintained by AgentBets.ai. Found an error or API change we missed? Let us know on Twitter.
Not financial advice. Built for builders.
