Rate Limits
AI92 rate-limits per account using a 1-second fixed window: your limit is expressed in requests per second (RPS), and the counter resets every second. The limit is determined by your tier — and if you hold both a credit pack tier and a hybrid subscription, you get the higher of the two.
Your limit
effective RPS = max(pack tier RPS, subscription tier RPS)
Pack tiers
| Tier | RPS |
|---|---|
STARTER | 10 |
GROWTH | 10 |
PROFESSIONAL | 25 |
BUSINESS | 25 |
ENTERPRISE | 50 |
SCALE | 50 |
Hybrid subscription tiers
| Subscription | RPS |
|---|---|
pro_sub | 25 |
business_sub | 50 |
enterprise_sub | 100 |
Example. A GROWTH account (10 RPS) on a business_sub subscription (50 RPS) gets an effective limit of 50 RPS — max(10, 50). Subscriptions never lower your limit.
You can read your current effective limit from the X-RateLimit-Limit header on any response, or compute it from GET /v1/account (tier + subscription_tier).
Rate-limit headers
Every /v1 response includes:
| Header | Meaning |
|---|---|
X-RateLimit-Limit | Your RPS limit for this window |
X-RateLimit-Remaining | Requests left in the current 1-second window |
X-RateLimit-Reset | Unix timestamp (seconds) when the window resets |
X-RateLimit-Limit: 25
X-RateLimit-Remaining: 22
X-RateLimit-Reset: 1718971801When you exceed the limit
A request over the limit returns 429 Too Many Requests with a Retry-After header:
HTTP/1.1 429 Too Many Requests
Retry-After: 1
X-RateLimit-Limit: 25
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1718971801{
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Rate limit of 25 requests/second exceeded for your tier. Retry after 1 second or upgrade your plan.",
"status": 429,
"documentation_url": "https://ai92.ai/docs/rate-limits"
}
}Because the window is one second, Retry-After is 1: wait a second and try again.
Handling 429s: backoff guidance
- Respect
Retry-After. If present, wait at least that many seconds before retrying. - Exponential backoff with jitter for repeated 429s:
0.5s, 1s, 2s, 4s…plus a small random jitter to avoid thundering-herd retries from a fleet of workers. - Cap concurrency, not just retries. The cleanest fix is to throttle outbound concurrency client-side so you rarely hit the limit. A simple token bucket sized to your
X-RateLimit-Limitkeeps you under it. - Only retry idempotent operations automatically. For writes (sends, reveals), pair retries with an
X-AI92-Idempotency-Keyso a retried call can't double-charge. See Idempotency.
A minimal Python retry wrapper:
import time, random, httpx
def call_with_backoff(method, url, *, max_retries=5, **kwargs):
delay = 0.5
for attempt in range(max_retries + 1):
r = httpx.request(method, url, **kwargs)
if r.status_code != 429:
return r
wait = float(r.headers.get("Retry-After", delay))
time.sleep(wait + random.uniform(0, 0.25))
delay *= 2
r.raise_for_status()
return rasync function callWithBackoff(input, init = {}, maxRetries = 5) {
let delay = 500;
for (let attempt = 0; attempt <= maxRetries; attempt++) {
const res = await fetch(input, init);
if (res.status !== 429) return res;
const retryAfter = Number(res.headers.get("Retry-After")) * 1000 || delay;
await new Promise((r) => setTimeout(r, retryAfter + Math.random() * 250));
delay *= 2;
}
throw new Error("Rate limited after max retries");
}Need more throughput?
Move to a higher pack tier or add a hybrid subscription — your effective limit jumps immediately on the next window. See Credits & Billing. For sustained high volume, enterprise_sub lifts you to 100 RPS; talk to us if you need more.
Note: the limiter is fail-open — if AI92's limiter backend is briefly unavailable, requests are allowed through rather than blocked. Don't rely on the limiter as your only backpressure; cap concurrency on your side too.