Rate limits
Each API token may make 1000 requests per hour.
The limit exists to protect the database behind the metadata endpoints. It does not apply to translation bundle downloads, which are static CDN files and are not part of this API — so the request you make most often is not the one being counted.
The window is fixed, not rolling
Quota is counted in a fixed one-hour window. When the window ends, the full allowance returns at once; it does not trickle back request by request. A client that spends its 1000 requests in the first two minutes waits out the remaining fifty-eight.
X-Localeo-RateLimit-Reset tells you how long that wait is.
Headers
Responses carry your current state — including error responses, which is how you
can tell that a 401 has been spending quota:
| Header | Meaning |
|---|---|
X-Localeo-RateLimit-Limit | Requests allowed per window. Normally 1000. |
X-Localeo-RateLimit-Remaining | Requests left in the current window. |
X-Localeo-RateLimit-Reset | Seconds until the window resets and the allowance returns. |
HTTP/1.1 200 OKX-Localeo-RateLimit-Limit: 1000X-Localeo-RateLimit-Remaining: 987X-Localeo-RateLimit-Reset: 2384When you exceed it
A 429 carries Retry-After only — the X-Localeo-RateLimit-* headers are
not repeated on it, because Retry-After already tells you everything you need:
HTTP/1.1 429 Too Many RequestsContent-Type: application/jsonRetry-After: 3590{ "error": "rate limit exceeded" }Two behaviours worth designing around
Rejected requests still cost quota
The limiter runs before authentication, so a 401 consumes an allowance exactly as a 200 does. This is the failure mode that surprises people: a service with a stale token retries hard, burns 1000 requests against 401, and then starts reporting 429 — so the symptom points at rate limiting when the cause is a bad credential.
If you see 429s you cannot account for, read X-Localeo-RateLimit-Remaining on your successful responses and check your token before asking for a higher limit.
Cached responses do not cost quota
The opposite also holds, and works in your favour. The response cache sits in front of the limiter, so a request that hits the cache is served without being counted. Polling the same URL repeatedly is far cheaper than the raw request count suggests — see Caching.
Backing off
A reasonable client:
- Reads
X-Localeo-RateLimit-Remainingand slows down as it approaches zero, rather than waiting to be rejected. - On
429, sleeps forRetry-Afterseconds and retries once. - Treats a second
429as a real error and surfaces it, rather than looping.
If 1000/hour is not enough
It usually is, because the high-frequency operation — fetching a bundle — is not rate limited at all. If you are approaching the limit, the cause is often one of:
- Polling for new releases too aggressively. The
latestCDN path lets you fetch the newest bundle with no API call at all. See Releases & bundles. - Fetching metadata per user or per request instead of once per deploy.
- A retry loop against
401, as above.
If none of those apply, get in touch — the limit is configurable per deployment.