Skip to content

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:

HeaderMeaning
X-Localeo-RateLimit-LimitRequests allowed per window. Normally 1000.
X-Localeo-RateLimit-RemainingRequests left in the current window.
X-Localeo-RateLimit-ResetSeconds until the window resets and the allowance returns.
HTTP/1.1 200 OK
X-Localeo-RateLimit-Limit: 1000
X-Localeo-RateLimit-Remaining: 987
X-Localeo-RateLimit-Reset: 2384

When 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 Requests
Content-Type: application/json
Retry-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:

  1. Reads X-Localeo-RateLimit-Remaining and slows down as it approaches zero, rather than waiting to be rejected.
  2. On 429, sleeps for Retry-After seconds and retries once.
  3. Treats a second 429 as 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 latest CDN 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.