Rate limits
Each brand can make 200 requests per minute. How to see how many are left, and how to retry.
The limits
- A brand can make 200 requests per minute. All keys of the brand share this count.
- The count starts again at 0 at the start of each minute, in UTC.
- A brand can run at most 4 reports at the same time.
- Separately, each IP address can send at most 20 requests per second, with short bursts of up to 100.
See how many requests are left
Every response has 3 headers with the brand's count:
X-RateLimit-Limit: 200
X-RateLimit-Remaining: 143
X-RateLimit-Reset: 17X-RateLimit-Remaining is the number of requests left this minute. X-RateLimit-Reset is the number of seconds until the count starts again.
When you go over the limit
The 201st request in a minute gets status 429 with the error code rate_limited. The response has a Retry-After header with the number of seconds to wait. It is the same number as X-RateLimit-Reset:
{
"error": {
"code": "rate_limited",
"message": "This brand made more than 200 requests this minute. Retry after 12 seconds.",
"param": null
}
}If a brand starts a 5th report while 4 of its reports are still running, the 5th gets status 429 with the error code too_many_concurrent_reports. Wait a moment and send it again.
Retry a failed request
- After a
429, wait the number of seconds inRetry-After, then send the request again. - After a
500or a503, wait and retry, and wait twice as long after each failure. - Do not send any other failed request again without changing it. It gets the same error.
This Python function follows these rules:
import os
import time
import requests
API = "https://api.lumirank.ai/v1"
HEADERS = {"Authorization": f"Bearer {os.environ['LUMIRANK_API_KEY']}"}
def get(path, params=None):
for attempt in range(5):
resp = requests.get(f"{API}{path}", headers=HEADERS, params=params, timeout=60)
if resp.status_code == 429:
time.sleep(int(resp.headers.get("Retry-After", "1")))
continue
if resp.status_code in (500, 503):
time.sleep(2 ** attempt)
continue
resp.raise_for_status()
return resp.json()
raise RuntimeError(f"{path} still failing after 5 tries")
print(get("/brand")["name"])In a long export, check X-RateLimit-Remaining and pause when it gets low, so you stay under the limit.