Rate Limits
Rate limits are enforced per API key using Redis sliding-window counters with both per-second (RPS) and per-minute (RPM) buckets.Tiers
| Tier | Requests/sec | Requests/min | Max WS Connections | Max Batch Size |
|---|---|---|---|---|
free | 2 | 120 | 1 | 1 |
pro | 10 | 600 | 3 | 5 |
pro_plus | 30 | 1,800 | 10 | 10 |
enterprise | 100 | 6,000 | 50 | 25 |
The
free tier allows short bursts (up to 2 requests in any one
second) but is also capped at 120 requests in any rolling one-minute
window, so the per-minute bucket is the one you’ll hit first under
sustained load. Use POST /v1/prices/batch and the WebSocket feeds
(which don’t count against the REST limit) to stay well inside it.Rate Limit Response
When you exceed your limit, the API returns HTTP 429 with the Polymarket-shape single-fielderror envelope and a stable
X-Polysim-Code response header:
X-Polysim-Code === "RATE_LIMIT_EXCEEDED" rather than the
body prose, and read the Retry-After header for the exact wait time
in seconds.
Rate Limit Headers (on every response)
Every authenticated response carriesx-ratelimit-* headers so bots
can pre-throttle instead of waiting for an actual 429:
| Header | Type | Description |
|---|---|---|
x-ratelimit-tier | string | Tier of the key making the call — free / pro / pro_plus / enterprise |
x-ratelimit-limit | int | Per-minute cap for the tier |
x-ratelimit-limit-per-second | int | Per-second cap for the tier |
x-ratelimit-remaining | int | Requests remaining in the current rolling-minute window |
x-ratelimit-remaining-per-second | int | Requests remaining in the current rolling-second window |
x-ratelimit-reset | int | Unix epoch seconds when the per-minute window rolls over |
Every header above is also emitted under the PolySim-namespaced
x-polysim-ratelimit-* prefix with identical values (e.g.
x-polysim-ratelimit-remaining). Read whichever your SDK or proxy
keys off — the unprefixed x-ratelimit-* form is canonical.Handling Rate Limits
When the limiter does fire, exponential backoff keyed offRetry-After:
Best Practices
Use Batch Endpoints
POST /v1/orders/batch and POST /v1/prices/batch combine multiple
operations into one request — and a batch call counts as one tick
against your RPS/RPM. It’s bounded by your tier’s Max Batch Size
(see the Tiers table above): free=1 means no batching benefit on
free, so this pays off most on pro (5) / pro_plus (10) /
enterprise (25).Use WebSocket Feeds
Subscribe to
WS /v1/ws/prices instead of polling GET /v1/markets.
WebSocket connections don’t count against your REST rate limit.Cache Market Metadata
Market metadata (slug, question, outcomes) changes infrequently.
Cache it locally and only refresh periodically.
Idempotency Keys
On order placement (
POST /v1/orders, POST /v1/order,
POST /v1/clob/order), send an Idempotency-Key header — a
Stripe-style alias for the body’s client_order_id — so a retried
request can’t double-fill. Reusing a key with a different payload
returns 409 IDEMPOTENCY_KEY_REUSE; reuse it only for the exact same
order you’re retrying.Next Steps
- String Numerics — Why all numbers are strings
- Batch Orders — Reduce request count with batching