Your API Key
Polymarket issues each partner an API key during onboarding:- Key ID: the public half, sent on every request.
- Secret: a base64url-encoded string, shared once through a secure channel. Decode it to bytes before using it as the HMAC key.
Sign a Request
Sign every request exceptGET /v1/time:
1
Create the Request Timestamp
First, create a new Unix timestamp in seconds for each request. It must be
within 30 seconds of server time, in either direction. See
Keep Your Clock in Sync.
2
Create the Request Signature
Next, concatenate the timestamp, the uppercase HTTP method, the request
path, and the exact serialized body you send, with no separators. Then sign
the result with your API key’s secret, decoded from base64url:Where:
request_pathis the URL path only. The query string is not signed.bodyis the exact bytes sent. For aGET, it is empty. Serialize the body once and reuse that string for both the signature and the request, to avoid mismatches from key ordering or whitespace.rfq_signatureis base64url-encoded with padding (RFC 4648 §5). It is not hex and not standard base64.
Test vector
Test vector
Use these inputs to check your implementation:
3
Send an Authenticated Request
Finally, send the key ID, the timestamp, and the signature as headers. This
request validates the terms of a trade:Every authenticated request uses the same three headers:
Keep Your Clock in Sync
RFQ-Timestamp must be within 30 seconds of server time, in either direction.
Keep your clock NTP-synced. If your requests start failing with 401, compare
your clock with the server’s: GET /v1/time needs no authentication.
timestamp is the server time in Unix seconds, in the same format as
RFQ-Timestamp.
Authenticate the WebSocket
The trade status stream is authenticated once, on the upgrade request. Sign it like anyGET, with an empty body, and send the same three headers on the
handshake:
Authentication Errors
A request that fails authentication returns401 with code
authentication_failed. Missing headers, a timestamp that isn’t whole Unix
seconds, and a timestamp outside the 30-second window each have their own
message. An unknown or revoked key ID and a signature mismatch share one
generic message, for security.