Polymarket API Auth: Sign Requests Step-by-Step
This guide shows you how to authenticate and sign Polymarket API requests using API keys and EIP-712 signatures. You’ll learn the exact steps to generate credentials, construct the required headers, and sign your requests so the Polymarket API accepts them. This is essential for placing orders, reading private account data, or using the CLOB (central limit order book) endpoints.
What You’ll Need
- A Polymarket account (you can create one at polymarket.com)
- A wallet that supports EIP-712 signatures (e.g., MetaMask, WalletConnect, or a custom signer)
- Access to the Polymarket CLOB API documentation (docs.polymarket.com)
- A tool to make HTTP requests (like Postman, cURL, or a scripting language such as Python or Node.js)
- Your API secret and API key (generated via the Polymarket UI or API)
Step-by-Step
- Generate your API credentials. Log in to Polymarket, go to your account settings, and find the API section. Click “Generate API Key” to create an API key and API secret. Store these securely—you’ll need them for every request. The secret is shown only once, so copy it immediately.
- Understand the required headers. For authenticated requests, you must include three headers:
POLY-ADDRESS(your wallet address),POLY-SIGNATURE(a signed timestamp), andPOLY-TIMESTAMP(the current Unix timestamp in seconds). The signature is an EIP-712 signed message that proves you own the wallet. - Construct the signing message. The message to sign is a JSON object with the following fields:
timestamp(the same Unix timestamp you’ll send in the header),action(e.g., “create-order” or “cancel-order”), andpayload(the request body as a JSON string). The exact structure is defined in the Polymarket docs under “Authentication”. - Sign the message with EIP-712. Use your wallet’s signer to produce a signature. In ethers.js, you can use
signTypedDatawith the domain and types specified in the docs. The domain typically includes the name “Polymarket CTF” and a chain ID of 137 (Polygon). The signature is a hex string starting with0x. - Build the request headers. Set the three headers as follows:
POLY-ADDRESSto your wallet address (lowercase),POLY-SIGNATUREto the signature from step 4, andPOLY-TIMESTAMPto the timestamp you used in the signing message. Ensure the timestamp matches exactly—any mismatch will cause a 401 error. - Send your request. Make the HTTP request to the desired endpoint (e.g.,
POST /ordersfor placing an order). Include the headers and any required body parameters. For GET requests, the payload is usually an empty string or the query parameters as a JSON string, depending on the endpoint. - Verify the response. If successful, you’ll receive a 200 response with the expected data. If you get a 401 or 403, check your timestamp, signature, and address—common issues are listed below.
Common Mistakes
- Timestamp mismatch: Using a different timestamp in the signature vs. the header. Always use the exact same value.
- Incorrect address case: Polymarket expects the address in lowercase. Using a checksummed address (with uppercase letters) will cause authentication to fail.
- Wrong chain ID: The EIP-712 domain must include chain ID 137 (Polygon Mainnet). Using 1 (Ethereum) or 80001 (Mumbai) will produce an invalid signature.
- Forgetting the payload: For POST requests, the payload must be the exact JSON string of the request body. If you omit it or use a different formatting (e.g., extra spaces), the signature won’t match.
- Using the wrong endpoint: Some endpoints require a different action string in the signature. Always check the docs for the specific endpoint you’re calling.
Tips
- Use a library: Libraries like ethers.js or viem simplify EIP-712 signing. Avoid hand-rolling the signature logic.
- Test with a small order first: Before placing a large order, test with a tiny amount to ensure your authentication works.
- Keep your secret safe: Never expose your API secret in client-side code or share it. Use environment variables.
- Check the docs for examples: Polymarket provides Python and JavaScript examples—use them as a reference.
- Use a timestamp from your server: If you’re building a bot, generate the timestamp from your server clock, not the client, to avoid drift.
Troubleshooting
If you receive a 401 Unauthorized error, the most likely cause is a signature mismatch. Here’s what to check:
- Timestamp drift: Ensure your system clock is accurate. A difference of more than a few seconds will cause rejection.
- Signature format: The signature must be a hex string with
0xprefix. Some libraries return a signature object—convert it to a string. - Payload serialization: For POST requests, the payload must be the exact JSON string of the body. Use
JSON.stringify(body)and ensure no extra whitespace. - Action string: Verify that the action in the signing message matches the endpoint. For example,
create-orderfor POST /orders,cancel-orderfor DELETE /orders. - Address mismatch: Confirm that the address in the header matches the one you generated the API key with.
- Check the docs: If all else fails, review the official authentication section—it may have been updated.
Frequently Asked Questions
Do I need to sign every request?
Yes, every authenticated request must include a valid signature. The signature is tied to the timestamp and payload, so it changes with each request.
Can I use the same signature for multiple requests?
No, each request requires a fresh timestamp and signature. Reusing an old signature will result in a 401 error.
What is the difference between API key and API secret?
The API key is a public identifier for your account, while the API secret is used to derive the signature. The secret is sensitive and should never be shared.
Does the API work on testnet?
Yes, Polymarket provides a testnet environment. You’ll need to generate separate API keys for testnet and use the testnet chain ID (80001) in the signing domain.
Can I use WalletConnect to sign?
Yes, any wallet that supports EIP-712 can sign the message. WalletConnect v2 works, but you may need to handle the session manually.
What if my signature is valid but I get a 403 error?
A 403 usually means your API key lacks permission for the endpoint. Check that you’ve enabled the necessary permissions when generating the key, or regenerate the key with full access.
Related
Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.