Rate Limits
The previous version of this page described only the enterprise API-key limit.
That was incomplete.
The live platform has multiple rate-limit layers depending on which surface you are using:
- Shared product gateway routes
- Auth and signup abuse controls
- OTP-specific cooldowns
- Public portal anti-abuse limits
- Enterprise API-key limits
Shared Product Gateway
Shared product traffic through the main gateway uses the current default below:
| Surface | Default limit | Scope |
|---|---|---|
/api/* on the shared gateway | 500 requests / minute | Per client IP in production |
This is the default from the shared security config used by the gateway.
Notes:
- Non-production environments can override this with
API_RATE_LIMIT_MAX. - This is separate from auth-specific abuse controls below.
- Hitting this limit commonly returns
429with a retry window from the Fastify rate-limit middleware.
Auth Abuse Controls
Authentication routes have stricter controls than normal API reads.
| Route | Default limit | Scope |
|---|---|---|
POST /auth/register | 3 requests / hour | Per IP |
POST /auth/login | 5 attempts / 15 minutes | Per IP + email |
POST /auth/forgot-password | 3 requests / hour | Per email |
When these controls trigger, the response body includes a retryAfterMs field when applicable.
Example:
{
"success": false,
"error": "Too many login attempts. Please try again later.",
"retryAfterMs": 847000
}
OTP Limits
OTP routes have their own cooldowns and attempt caps:
| Route | Default limit |
|---|---|
POST /auth/otp/request | 1 OTP request per 60 seconds per email |
POST /auth/otp/verify | 5 verification attempts per OTP |
POST /auth/otp/reauth | 1 OTP request per 60 seconds per email |
These are not the same as the gateway-wide limit.
Public Portal
The public portal has a dedicated anti-abuse limiter:
| Surface | Default limit | Scope |
|---|---|---|
| Public portal routes | 30 requests / minute | Per IP in production |
This value can be overridden with PUBLIC_PORTAL_RATE_LIMIT_MAX and PUBLIC_PORTAL_RATE_LIMIT_WINDOW.
Enterprise API
The enterprise API still has its own API-key limit:
| Surface | Default limit | Scope |
|---|---|---|
/api/v1/* | 1,000 requests / hour | Per API key |
This is the limit that the older version of this page described, but it does not represent the whole platform.
Response Format
There is no single universal rate-limit header contract across every route in the platform.
- Shared auth abuse responses often return
retryAfterMsin the JSON body. - Fastify middleware-based limits can also emit standard rate-limit headers depending on the route and middleware layer.
- Clients should handle
429generically and back off instead of assuming one header format everywhere.
When Youโre Rate Limited
If you exceed a limit, the API returns 429 Too Many Requests.
Two common response shapes are currently in use:
Shared auth or abuse-control response:
{
"success": false,
"error": "Too many login attempts. Please try again later.",
"retryAfterMs": 847000
}
Middleware-based response:
{
"success": false,
"error": "Rate limit exceeded, retry in 1 minute"
}
Best Practices
- Cache responses where possible.
- Use pagination with reasonable page sizes.
- Do not brute-force login or OTP flows.
- Treat
429as a normal retry/backoff signal. - Avoid assuming that one routeโs limit equals every other routeโs limit.
Custom Limits
Enterprise tenants on dedicated infrastructure can request custom limits and dedicated abuse-control policies. Contact support@scootsign.com.