The Frontline Public API rate-limits requests per account to protect platform stability and ensure fair use across customers.
| Scope | Limit | Window |
|---|---|---|
| Per account | 1,000 requests | 60 seconds |
The window is a fixed 60-second bucket that resets on the first request of each window. Requests issued by any key under the same account count toward the same bucket.
Unauthenticated requests (no valid API key) are rate-limited per IP at the same threshold.
Every successful response includes:
| Header | Meaning |
|---|---|
X-RateLimit-Limit | Total requests allowed per window. Currently 1000. |
X-RateLimit-Remaining | Requests remaining in the current window. Drops to 0 at limit. |
Use these to back off proactively instead of waiting for a 429.
A request beyond the limit returns:
HTTP/1.1 429 Too Many Requests
Content-Type: application/json{
"ok": false,
"error": {
"code": "internal_error",
"message": "Rate limit exceeded. Please try again later."
}
}Wait until the next 60-second window and retry.
A minimal retry loop with exponential backoff:
async function callWithRetry(url, init, attempt = 0) {
const res = await fetch(url, init);
if (res.status !== 429 || attempt >= 5) return res;
const delayMs = 1000 * 2 ** attempt; // 1s, 2s, 4s, 8s, 16s
await new Promise((r) => setTimeout(r, delayMs));
return callWithRetry(url, init, attempt + 1);
}import time, requests
def call_with_retry(url, headers, attempt=0):
res = requests.get(url, headers=headers)
if res.status_code != 429 or attempt >= 5:
return res
time.sleep(2 ** attempt)
return call_with_retry(url, headers, attempt + 1)- Cache reference data (
/ai-models,/billing) instead of polling. - Batch listing calls with the highest
pageSizeyou can tolerate (default20, raise it within reason). - Run scheduled syncs off-peak.
- If you need a higher limit for a legitimate integration, reach out to support.