Plan Limits
Per-plan request and token limits, response headers, and how to handle 429s.
Limits keep the platform fair and stable for everyone. Every plan has a monthly allowance. Your client should expect 429 responses and retry sensibly.
Plans
| Plan | Price | Requests / month | Tokens / month | Seats |
|---|---|---|---|---|
| Free | $0 | 100 | 200K | 1 |
| Starter | $15/mo | 1,000 | 1.5M | 1 |
| Pro | $49/mo | 8,000 | 12M | 1 |
| Team | $149/mo | 40,000 | 60M | 5 |
| Enterprise | Custom | Custom | Custom | Unlimited |
Start right away with 100 requests and 200K tokens a month. All 60+ models are available on every paid plan. Free, Starter and Pro are individual plans; Team and Enterprise are separate plans for team workspaces, not an upgrade from Pro.
Two kinds of limit
| Limit | Applies to | What you get |
|---|---|---|
| Monthly quota (table above) | You, or the team owner's plan | 429 with code: rate_limit_exceeded and no Retry-After. It resets at the start of next month. |
| Short bursts | Your client IP (not your plan) | POST /v1/ai/*: 20 requests/minute. Everything else: 100/minute. 429 with a Retry-After header. |
If the 429 has code: rate_limit_exceeded and no Retry-After, you're out of monthly quota. Retrying won't help: back off for a long time or upgrade. A loop that only waits for Retry-After will spin.
Headers you can read
Burst-limited responses carry the standard headers:
HTTP/1.1 200 OK
RateLimit-Limit: 100
RateLimit-Remaining: 95
RateLimit-Reset: 42 # seconds until the window resets
Retry-After: 42 # only on a 429Successful chat requests also tell you where you stand on your monthly quota:
X-Monthly-Requests-Used: 1240
X-Requests-Limit: 8000
X-Requests-Remaining: 6760
X-Monthly-Tokens-Used: 402113
X-Tokens-Limit: 12000000Retry the right way
This honours Retry-After for bursts and uses capped exponential backoff with jitter otherwise:
async function makeRequestWithRetry(url, options, maxRetries = 4) {
for (let attempt = 0; attempt <= maxRetries; attempt++) {
const response = await fetch(url, options);
if (response.status !== 429 && response.status < 500) return response;
if (attempt === maxRetries) return response; // give up — let the caller see it
const retryAfter = Number(response.headers.get('Retry-After'));
const waitMs = Number.isFinite(retryAfter) && retryAfter > 0
? retryAfter * 1000 // burst: server told us
: Math.min(2 ** attempt * 1000, 30000) + Math.random() * 1000; // quota / 5xx: backoff + jitter
await new Promise(r => setTimeout(r, waitMs));
}
}
const response = await makeRequestWithRetry('https://api.tarqaai.com/api/v1/chat/completions', {
method: 'POST',
headers: { 'Authorization': 'Bearer YOUR_API_KEY', 'Content-Type': 'application/json' },
body: JSON.stringify({
model: 'gemini-2.5-flash',
messages: [{ role: 'user', content: 'Hello!' }],
}),
});Tips
- Watch the
X-Requests-Remainingheader and slow down before you hit zero. - Cache responses you'll ask for again.
- Batch work where you can.
- Need more? Contact support about higher limits.