Skip to main content

Rate Limits

To protect system stability and ensure fair usage, the API enforces rate limits.

Rate Limit Tiers

The API implements two tiers of rate limiting:

Per-Token Limits

Each Bearer token is limited to 30 requests per minute. This ensures individual tokens cannot overwhelm the system.

Per-Account Limits

All tokens associated with your account share a combined limit of 60 requests per minute. This prevents excessive usage across multiple tokens.

Rate Limit Response

When you exceed a rate limit, the API returns a 429 Too Many Requests response with a Retry-After header indicating how many seconds to wait before retrying.

Example:

HTTP/1.1 429 Too Many Requests
Retry-After: 60
Content-Type: application/json

The response body includes additional information about which limit was exceeded:

{
"error": "Rate limit exceeded",
"limitType": "jti", // "jti" for per-token, "sub" for per-account
"limit": 30 // The limit that was exceeded
}

The limitType field indicates which limit you've hit:

  • "jti": Per-token limit exceeded
  • "sub": Per-account limit exceeded

Handling Rate Limits

When you receive a 429 response:

  1. Check the Retry-After header - This tells you exactly how long to wait
  2. Implement exponential backoff - If retrying multiple times
  3. Add jitter - Randomise retry delays slightly if making parallel requests

Example Implementation

async function fetchWithRetry(url, options, maxRetries = 5) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
const response = await fetch(url, options);

if (response.status !== 429) {
return response;
}

// Parse retry delay from header
const retryAfter = response.headers.get('Retry-After');
let delaySeconds = retryAfter ? parseInt(retryAfter) : Math.pow(2, attempt);

// Add jitter (±10% randomisation)
const jitter = delaySeconds * 0.1 * (Math.random() * 2 - 1);
delaySeconds = Math.max(1, delaySeconds + jitter);

console.log(`Rate limited. Waiting ${delaySeconds} seconds before retry ${attempt + 1}/${maxRetries}`);
await new Promise(resolve => setTimeout(resolve, delaySeconds * 1000));
}

throw new Error(`Failed after ${maxRetries} retries`);
}

Need Higher Limits?

If you're routinely hitting rate limits, please contact Scoffable to discuss your requirements. We can help optimise your integration or adjust limits if needed.