Rate limits
The limit
600 requests per minute per credential, in a fixed 60-second window that starts with your first request.
- An API key has its own window. Dashboard sessions share one window per account.
- It is the same for every key type and every plan.
- It is counted per API server, so under load balancing you may get somewhat more before a refusal. Do not design to that.
- A refused request does not count against the window.
Where it applies
| Surface | Limited |
|---|---|
Developer routes — /v1/fx/rates, /v1/webhooks*, /v1/api-keys*, /v1/request-logs*, /v1/usage/*, /v1/transactions*, /v1/contacts*, … | Yes |
| Dashboard routes | Yes |
Money routes — /v1/banking/* | Yes |
GET /v1/public/pay/{handle} | 300 per hour per IP address; its 429 carries no X-RateLimit-* or Retry-After headers |
| Other public routes | No |
Sandbox tools — the faucet, simulate-deposit, simulate-arrival, simulate-completion, the digital-asset approval | Each also has a window of its own: at most 30 requests an hour from one account, a refused request included (429 rate_limited, the message says how many minutes are left). The faucet and the digital-asset tools count against the 600 per minute too — see Sandbox behaviour |
Besides our limit, our banking partner limits us. When it does, you get
429 rate_limited with the message "upstream partner rate-limited the
request" and no Retry-After. Back off and retry. A
payout or conversion refused this way has already been recorded as created,
and a retry with the same Idempotency-Key only returns that record — it is
never sent. Send it again with a new key, as for any other 4xx
(Payouts).
Headers
Every response from a limited surface carries:
| Header | Meaning |
|---|---|
X-RateLimit-Limit | 600 |
X-RateLimit-Remaining | Requests left in the current window |
X-RateLimit-Reset | Unix time, in seconds, when the window resets |
A refusal adds Retry-After in seconds:
HTTP/1.1 429 Too Many Requests
Retry-After: 12
X-RateLimit-Limit: 600
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1792094427
{
"success": false,
"error": "rate_limited",
"message": "too many requests; retry in 12s. The limit is 600 requests per minute."
}
The X-RateLimit-* headers are not exposed to cross-origin browser code; read
them server-side.
Handling 429
- Wait
Retry-Afterseconds if it is present; otherwise back off exponentially with jitter, starting at a second. - Retry with the same
Idempotency-Keywhere the route takes one — our own limit refuses a request before it does anything. (A429withoutRetry-Afteron a money route is our partner's; see above.) - If you hit the limit routinely, spread the work over time and cache
GET /v1/fx/rates(it is reused for a minute on our side anyway). Polling payouts counts too: pace it.
A 429 is not written to request logs — the limit is
checked before the request is logged.