Skip to content

Rate limits

Each API key has a per-minute request budget enforced server-side. The budget scales with plan:

PlanRequests / minute
Free30
Indie120
Builder500

When you’re over budget the server returns 429 RATE_LIMITED with a Retry-After header (seconds).

Every response — success or not — carries:

X-RateLimit-Limit: <int> // total budget
X-RateLimit-Remaining: <int> // remaining this window
X-RateLimit-Reset: <unix> // seconds since epoch when the window resets

On a 429 we also include:

Retry-After: <seconds>

The official retry strategy is exponential backoff with full jitter, capped at 60 seconds:

async function withBackoff<T>(fn: () => Promise<T>, attempts = 5): Promise<T> {
let lastErr: unknown;
for (let i = 0; i < attempts; i++) {
try {
return await fn();
} catch (err: any) {
lastErr = err;
if (err?.code !== "RATE_LIMITED") throw err;
const retryAfter = Number(err.retryAfter ?? 1);
const cap = Math.min(retryAfter, 60);
const wait = Math.random() * cap * 1000;
await new Promise((r) => setTimeout(r, wait));
}
}
throw lastErr;
}

Future versions of the official SDK will handle this automatically.