Use cases
API rate limiting (60/min prod, 1000/min sandbox, client backoff)
Per-tenant limits, quota headers, client exponential backoff
Scell.io applies a per-tenant rate limit: 60 req/min in production (sk_live_*), 1000 req/min in sandbox (sk_test_*) to ease load testing. Response headers `X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset` (epoch) let the client adjust. On exceedance: HTTP 429 + `Retry-After` header (seconds). Recommended client pattern: exponential backoff with jitter (1s, 2s, 4s, 8s, 16s) over max 5 attempts. For needs > 60/min, contact support for a custom quota (enterprise and SSII).
Key facts
- Production: 60 req/min/tenant
- Sandbox: 1000 req/min/tenant
- `X-RateLimit-*` headers on all responses
- HTTP 429 + `Retry-After` on exceedance
- Exponential backoff + jitter recommended client-side
- Custom quota available for enterprises and SSIIs
Code example
async function callWithBackoff<T>(fn: () => Promise<T>, maxAttempts = 5): Promise<T> {
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
try {
return await fn();
} catch (err: any) {
if (err.status !== 429 || attempt === maxAttempts) throw err;
const retryAfter = Number(err.headers?.['retry-after'] ?? 0);
const backoff = retryAfter > 0 ? retryAfter * 1000 : Math.min(1000 * 2 ** (attempt - 1), 16_000);
const jitter = Math.random() * 250;
await new Promise((r) => setTimeout(r, backoff + jitter));
}
}
throw new Error('unreachable');
}
const invoice = await callWithBackoff(() => scell.invoices.create(payload));