# Rate limits

The Frontline Public API rate-limits requests **per account** to protect platform stability and ensure fair use across customers.

## Current quota

| 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.

## Response headers

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`.

## When you hit the limit

A request beyond the limit returns:


```http
HTTP/1.1 429 Too Many Requests
Content-Type: application/json
```


```json
{
    "ok": false,
    "error": {
        "code": "internal_error",
        "message": "Rate limit exceeded. Please try again later."
    }
}
```

Wait until the next 60-second window and retry.

## Handling 429 in client code

A minimal retry loop with exponential backoff:


```js
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);
}
```


```python
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)
```

## Best practices

- Cache reference data (`/ai-models`, `/billing`) instead of polling.
- Batch listing calls with the highest `pageSize` you can tolerate (default `20`, raise it within reason).
- Run scheduled syncs off-peak.
- If you need a higher limit for a legitimate integration, reach out to support.