Rate limits
Request budgets, not credit budgets. Enforced per API key. The numbers come from the same table the route reads.
01Limits by plan
| Plan | Per minute | Per day |
|---|---|---|
| Free | 100 | 5,000 |
| Starter, Plus, Pro, Business | 1000 | 50,000 |
| Enterprise | 10000 | Unlimited |
02Headers
| Header | Meaning |
|---|---|
| X-RateLimit-Limit | Per-minute ceiling |
| X-RateLimit-Remaining | Left this minute |
| X-RateLimit-Reset | UTC epoch seconds |
| X-RateLimit-Daily-Limit | Daily ceiling, omitted when unlimited |
| X-RateLimit-Daily-Remaining | Daily left, omitted when unlimited |
| X-Request-Id | Quote this |
| Retry-After | On 429 only, seconds |
Headers
HTTP/1.1 200 OK
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 958
X-RateLimit-Reset: 1738368060
X-RateLimit-Daily-Limit: 50000
X-RateLimit-Daily-Remaining: 49958
X-Request-Id: req_abc123def45603Handling 429
Sleep Retry-After seconds, then retry the same request.
429Response
{
"success": false,
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Too many requests. Please slow down."
},
"meta": {
"request_id": "req_abc123",
"timestamp": "2026-02-01T12:00:00Z"
}
}async function withRetry(url, options) {
const res = await fetch(url, options);
if (res.status === 429) {
const wait = Number(res.headers.get('Retry-After') || 60);
await new Promise((r) => setTimeout(r, wait * 1000));
return withRetry(url, options);
}
return res;
}04Check remaining
curl https://www.brainpercent.app/api/v1/user/usage \
-H "Authorization: Bearer bp_your_key"