Skip to main content
Every authenticated session is rate-limited:
WindowLimitScope
1 minute100 requestsper session
1 hour1,000 requestsper session
Read-only endpoints (GETs) count against the same bucket as mutations.

Headers

Every response includes:
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 87
X-RateLimit-Reset: 1717740892
Reset is a Unix timestamp — when the current window expires.

429 response

When you exceed the limit:
HTTP/1.1 429 Too Many Requests
Retry-After: 23
X-RateLimit-Reset: 1717740892
Content-Type: application/json

{
  "error": "rate_limited",
  "message": "Too many requests. Retry after 23 seconds."
}
Retry-After is the recommended back-off in seconds.

Stricter limits

A few endpoints have their own tighter caps:
EndpointLimitWhy
POST /v1/auth/request-code1 per 30 seconds per emailPrevents code-flooding
POST /v1/auth/verify-code5 attempts per codePrevents brute-force guessing
POST /v1/billing/checkout10 per hour per userPrevents fraud-bot accounts
async function callWithBackoff(fn: () => Promise<Response>, maxRetries = 3) {
  for (let i = 0; i <= maxRetries; i++) {
    const res = await fn();
    if (res.status !== 429) return res;
    const wait = parseInt(res.headers.get('Retry-After') ?? '30', 10);
    if (i === maxRetries) return res;
    await new Promise((r) => setTimeout(r, wait * 1000));
  }
  throw new Error('unreachable');
}

Why not higher

The dashboard polls a few endpoints on a timer (/v1/auth/me every 5 min, /v1/billing/balance every 15 sec when on the Billing page). 100/min leaves room for both that polling AND a script doing real work. If your workload genuinely needs more, email business@gpuoutlet.ai — higher-tier accounts get session limits raised to 1,000/min.