Rate Limiting
Written by Rohman Beny Riyanto
Every request is rate-limited per client IP, not per account or per token - a shared office network or a NAT'd mobile carrier can hit the limit collectively, not just one misbehaving client. Default limit: 100 requests per rolling 1-minute window. Both successful and failed requests count against it (neither is skipped/excluded).
Reading the headers
Every response - not just the one that finally trips the limit - carries three headers so a client can back off before hitting 429:
| Header | Meaning |
|---|---|
X-RateLimit-Limit | The window's total allowance (100 by default). |
X-RateLimit-Remaining | Requests left in the current window. |
X-RateLimit-Reset | When the current window resets. |
A reasonable FE strategy: once X-RateLimit-Remaining drops into single digits, start throttling your own request rate (debounce search-as-you-type calls, batch polling, etc.) instead of waiting to get a 429 back.
When the limit is hit
{
"response_code": "502",
"response_text": "Rate limit exceeded",
"error_details": {
"error": "BUSINESS_ERROR",
"detail": "...",
"path": "/v2/..."
}
}HTTP status 429. There is currently no Retry-After header - use X-RateLimit-Reset from the previous response (the 429 response itself still carries the standard rate-limit headers) to know when the window rolls over, and don't retry before then. Retrying immediately in a tight loop just keeps consuming whatever's left of the next window the moment it opens.
This is a global default, not necessarily every environment's exact number
100 requests/minute is this project's own default - an individual deployment can configure a different value. Always read the live X-RateLimit-Limit header rather than hardcoding 100 in FE code.