Skip to main content

Rate Limits

The API enforces rate limits per tenant to ensure fair usage and platform stability. Limits vary by tenant tier and endpoint group.

Limits by Tier

TierGeneral (15 min)Auth (15 min)Transfers (15 min)
starter1005050
pro500100200
enterprise2,0005001,000
note

Sandbox environments use 10x the production limits to facilitate testing. See Sandbox Testing.

Response Headers

Every response includes rate limit headers:

HeaderDescriptionExample
RateLimit-LimitMaximum requests per window100
RateLimit-RemainingRequests remaining in current window87
RateLimit-ResetUnix timestamp when the window resets1740009600
HTTP/1.1 200 OK
RateLimit-Limit: 100
RateLimit-Remaining: 87
RateLimit-Reset: 1740009600

Rate Limit Exceeded

When you exceed the limit, the API returns:

HTTP/1.1 429 Too Many Requests
Retry-After: 120
{
"success": false,
"error": "Too many requests",
"code": "RATE_LIMIT_EXCEEDED"
}

The Retry-After header tells you how many seconds to wait before retrying.

Authentication Rate Limits

Login endpoints have stricter limits to prevent brute-force attacks:

EndpointLimit (15 min)Notes
POST /api/v1/auth/login50Successful requests don't count
POST /api/v1/auth/refresh100
POST /api/v1/registration/forgot-password10Per email address
POST /api/v1/registration/reset-password10Per token

Successful login requests are not counted against the rate limit — only failed attempts count.

Handling Rate Limits

Check Headers Before Retrying

async function apiCall(url, options) {
const res = await fetch(url, options);

const remaining = parseInt(res.headers.get("RateLimit-Remaining"));
const resetAt = parseInt(res.headers.get("RateLimit-Reset"));

if (res.status === 429) {
const retryAfter = parseInt(res.headers.get("Retry-After")) || 60;
await new Promise((r) => setTimeout(r, retryAfter * 1000));
return apiCall(url, options); // Retry once
}

// Log when approaching limit
if (remaining < 10) {
console.warn(`Rate limit low: ${remaining} remaining, resets at ${new Date(resetAt * 1000)}`);
}

return res;
}

Strategies

  • Monitor RateLimit-Remaining — Back off when approaching zero.
  • Use exponential backoff — On 429 responses, wait the Retry-After duration before retrying.
  • Batch operations — Use bulk endpoints (e.g. POST /api/v1/bulk-transfers) instead of multiple individual calls.
  • Cache responses — Cache list responses (accounts, beneficiaries, billers) to reduce API calls.
  • Upgrade your tier — If you consistently hit limits, contact support to upgrade.

Request Counting

  • Each API call counts as one request regardless of response status (except where noted).
  • Websocket connections are not rate-limited.
  • Public endpoints (/api/v1/theme, /api/v1/fx-rates, /health) have separate, higher limits.

Next Steps