There are no published per-plan quotas to request an increase against. If a well-behaved integration is hitting limits, that usually points to a traffic pattern worth fixing (see Build a well-behaved client) rather than a quota to raise.
How limits are applied
Limits are enforced independently per service and are evaluated globally across that service’s instances — you can’t escape a limit by landing on a different server. A request is identified by a combination of:- Your IP address — every request counts against a per-IP limit.
- Your access token — the full
Authorizationheader. The token limit applies on top of the IP limit, not instead of it. The IP limit is checked first, so every request from one IP shares that IP’s budget whatever token it carries. Requests with no auth header skip the token limiter. - The endpoint path — on some public surfaces, specific paths have their own limits.
429 Too Many Requests.
Traffic limits by surface
These are sustained per-second limits. When exceeded, the key is blocked for a short cooldown before requests are accepted again.The GraphQL API endpoint is the one most integrations call for deposits, purchases, transfers, and reveals — plan around 20 requests per second there. The mobile/app gateway’s per-IP, per-token, and per-endpoint limits are configured per environment and aren’t published as fixed numbers; treat them as protective and back off on
429.Query cost limits
The GraphQL API scores every query before it runs. A query over any of these limits is rejected without running, no matter how slowly you send requests.How cost is counted
Each field you select costs 1 point. A field with its own selection set costs 1 point plus 5 times the cost of everything inside it, and a query costs the sum of its top-level fields. Each level of nesting multiplies what’s below it by 5:7,000. In practice you reach the cost limit before the depth limit.
- Page size doesn’t change the cost. Asking for 1 row or 20 costs the same, because cost comes from the fields you select, not the rows returned.
__typenamecosts the same as any other field. Clients that add it to every selection set, as Apollo Client does by default, raise the cost of deep queries.- Fragments add levels. An inline fragment (
... on Type { }) counts as one level of nesting and a named fragment spread counts as two, so the same fields cost 5 or 25 times more inside a fragment. Write the fields out in place in large queries. - Every operation in the document is checked, including ones
operationNamedoesn’t select. One operation over the limit rejects the whole request.
When a query is rejected
The response is HTTP400 with the reason in the errors array:
Syntax Error even though the query is valid GraphQL, and the found value is your query’s cost. Alias and directive limits return the same shape with their own message, for example Syntax Error: Aliases limit of 15 exceeded, found 16. A query over the depth limit is always over the cost limit too, so it gets both errors, cost first. A request over the token limit returns HTTP 500 with the same code, and a batched request returns HTTP 400 with the code BAD_REQUEST and the message Operation batching disabled.
Nothing runs when a query is rejected, so no mutation is applied, and sending the same query again returns the same error.
Authentication & security
Sign-in, PIN, and two-factor (2FA) flows are protected separately from general API traffic. Repeated failed attempts — logins, PIN checks, or 2FA verification — and excessive 2FA or SMS requests trigger temporary lockouts that clear on their own after a cooldown. Successful authentication resets these counters.When you exceed a limit
Rate limits and query cost limits fail in different ways, so check the status before you retry:
Every rate-limited response uses status
429 Too Many Requests. The body and headers vary by surface:
Retry-After(integer seconds) is returned on the authentication IP limiter and the PIN/2FA flows. It is not guaranteed on the general GraphQL/web traffic limiters.- There are currently no
X-RateLimit-Limit,X-RateLimit-Remaining, orX-RateLimit-Resetheaders — don’t build logic that depends on them.
Build a well-behaved client
1
Treat 429 as retryable
Honor
Retry-After when it’s present. When it isn’t, back off exponentially starting around 1 second (1s → 2s → 4s…) rather than retrying immediately.2
Keep sustained rates modest
Don’t parallel-blast a surface from a single IP or token. For the GraphQL API, stay comfortably under 20 requests/second and smooth out bursts.
3
Keep queries small
Select only the fields you use, keep nesting shallow, and write fields out in place instead of using fragments in large queries. If a query hits the cost limit, split it into smaller queries instead of retrying it.
4
Don't auto-retry auth failures
Repeated login, PIN, or 2FA failures cause temporary lockouts. Show the user a “try again later” message instead of retrying automatically.
5
Budget per IP, not per token
Every request from one IP counts against the same limit, however many tokens you use. If several workers, services, or customer accounts send traffic through one NAT gateway or proxy, pace them together so their combined rate stays under the limit.
Retry-After isn’t guaranteed everywhere, pair your retry logic with idempotency keys so a retried mutation never double-processes a purchase or transfer. For the full error catalog, see Errors.