Skip to Content
Rate limits

Rate limits

Every /v1 endpoint belongs to a limit tier. When the limit of a tier is full, we reject the request with 429 rate_limited and apply nothing. The tiers are independent of each other: heavy read traffic cannot use up your balance-sync budget.

Tiers and limits

We regenerate the table from the values in our capacity plan at every build. The limits are per minute.

TierEndpointsPer end userPer tenant
balance_sync
POST /v1/balance-sync
POST /v1/balance-sync/batch
None450/min
user_sync
PUT /v1/users/{external_user_id}
None3,000/min
positions
POST /v1/positions
POST /v1/positions/{id}/close
POST /v1/orders
DELETE /v1/orders/{id}
10/min4,500/min
default
every other /v1 route
None600/min
feed_read
GET /v1/markets
GET /v1/markets/{slug}
GET /v1/markets/{slug}/snapshot
GET /v1/markets/{slug}/history
60/min600/min
widget_session
POST /v1/widget/sessions
POST /v1/widget/sessions/refresh
GET /v1/widget/config
POST /v1/widget/error-reports
GET/PUT/DELETE /v1/widget/profile
GET /v1/widget/leaderboard
10/min13,500/min
users_me
GET /v1/users/me
60/min4,500/min
saved_markets
GET /v1/widget/saved-markets
PUT /v1/widget/saved-markets/{market_slug}
DELETE /v1/widget/saved-markets/{market_slug}
20/min5,400/min

Tenant limit and end-user limit

Every tier has a tenant limit. It counts the total traffic of your tenant in that tier. Its purpose is to stop a sudden load from one operator from slowing another operator.

Some tiers also have a limit for each end user. It counts per external_user_id. It stops excessive traffic from one end user. In every tier except feed_read, it does not change the tenant limit: whatever your number of users, the total traffic of your tenant stays within the tenant limit.

The end-user limit applies only to requests that arrive with a widget session token. Requests that you send from your own server with the API key have only the tenant limit. For example, your server requests in the positions and feed_read tiers, and your session-opening request POST /v1/widget/sessions, do not meet the end-user limit.

The feed_read tier counts the two credentials apart. Reads that you send with your API key count against the tenant limit. Reads that arrive with a widget session token count against the end-user limit only, and never against the tenant limit. Many end users of your tenant can read the feed at the same time, each within the end-user limit, and your own server keeps its whole tenant limit.

When you receive a 429

The Retry-After header of the response gives the wait time in seconds. Wait that long, then send the request again. If you retry at once and repeatedly, the limit stays active for longer.

Send write requests again with the same Idempotency-Key and the same body. This retry is safe because a rejected request applies nothing: the request is applied once or not at all. Read requests have no side effect, so you can retry them directly.

Many balance syncs

If you receive 429 in the balance_sync tier, do not send the syncs one by one. Send them in a batch with POST /v1/balance-sync/batch. One batch request counts as a single request against the tier limit. The 429 response in this tier also points you to the batch endpoint.

Syncing users

PUT /v1/users/{external_user_id} has its own tier, user_sync. Syncing users does not use your balance_sync limit, and balance syncs do not use your user_sync limit.

Raising a limit

The values in the table are the default for every tenant. If your traffic regularly exceeds a tenant limit, you can ask for a raise. Open the request as a support ticket from the tenant portal or with POST /v1/support-tickets. In the ticket, write the tier and the traffic that you expect.

A raise applies only to the tenant limit of the balance_sync, positions and default tiers. The end-user limits, widget_session, users_me, saved_markets and feed_read are not raised. A raised limit is part of the agreement with you, and it takes effect with our next deployment.

Last updated on