Skip to main content
The ER:LC API enforces rate limits to ensure fair access and to protect infrastructure for all users. Understanding how these limits work, and how to respond to them correctly, is essential for building a reliable integration.

Definitions

Throughout this page, the following terms are used:
  • Application — an app (such as a Discord bot or website) that accesses the ER:LC API. Each application is uniquely identified by its global API key, provided in the Authorization header.
  • Server — a private server identified by its server-key, provided via the Server-Key header.

Global rate limit

Requests sent with an API key in the Authorization header are rate limited per API key. Each application is limited to a set number of requests per second, and this limit can vary per application. Requests sent without an Authorization header are unauthenticated and have much lower limits. See Unauthenticated requests. Large applications may be issued higher limits. See Large Applications.

Unauthenticated requests

Unauthenticated access is intended for a server owner calling the API for their own server. Unauthenticated requests are limited per IP address and per server-key at the same time, so spreading one server’s requests across multiple IP addresses does not increase its limit. These requests use the unauthenticated-global (per IP) and unauthenticated-server (per server-key) buckets.
Rotating through IP addresses is not allowed. If you make requests on behalf of multiple servers, you must create a public application. Clients detected rotating IPs or serving multiple servers without authentication will receive 403 responses with error code 2005.

Per-route rate limit

Some routes have tighter limits than the global rate limit because they are more resource-intensive or more prone to abuse. These routes are identified by the X-RateLimit-Bucket response header containing a value other than global. For example, the POST /command route has a limit of 1 request per 5 seconds (subject to change). This is indicated by X-RateLimit-Bucket being set to command.

Rate limit headers

The API attaches the following headers to most standard responses:

What to do when you receive a HTTP 429 response

When you exceed a limit, the API returns HTTP 429 with a Retry-After header (in seconds) and a JSON body containing retry_after. In order to prevent longer API bans, you must stop sending requests immediately and wait the full Retry-After duration before sending any new requests.

Invalid request blocks

If your application continues sending requests after receiving 429 responses, instead of waiting as instructed by Retry-After, it may be placed under an invalid request block. Invalid request blocks last from one minute to a few hours depending on the bucket. While blocked, every request returns a 429 with a message identifying the block and when it lifts.
Applications that persistently fail to respect rate limits will be automatically blocked via Cloudflare. If you encounter a Cloudflare block page, you must contact us by opening an API ticket in the ER:LC Discord server.

Repeated failing requests

If your application keeps sending requests that fail with 400, 401, 403 or 404, it will be temporarily blocked: first from the server it keeps failing on, and, in extreme cases, from the API entirely. While blocked, requests return 429 with code 4001 and the invalid-requests-server or invalid-requests bucket.
Best practice: If you receive a 403 error several times for the same server-key, stop using that key. It has likely been regenerated by the server owner.

Services with shared IPs (including BotGhost) are not supported

The ER:LC API does not support BotGhost or similar shared-hosting services that run many applications under the same IP address, which may causes frequent rate limit collisions that cannot be resolved. For reliable API access, host your application on a dedicated IP.