> ## Documentation Index
> Fetch the complete documentation index at: https://docs.pureframe.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Rate Limits

> Per-key request limits and how to handle 429s.

Rate limits are applied per API key. Exceeding a limit returns `429 Too Many Requests`.

| Endpoint group                                                                | Limit                 |
| ----------------------------------------------------------------------------- | --------------------- |
| `POST /v1/search`                                                             | 30 requests / minute  |
| `POST /v1/upload`                                                             | 10 requests / minute  |
| `GET /v1/jobs/*`                                                              | 60 requests / minute  |
| `GET /v1/videos/{video_id}/moment`                                            | 60 requests / minute  |
| `GET /v1/videos`, `GET /v1/videos/{video_id}`, `DELETE /v1/videos/{video_id}` | 30 requests / minute  |
| Collections (read)                                                            | 100 requests / minute |
| Collections (write)                                                           | 30 requests / minute  |
| Agent tools                                                                   | 30 requests / minute  |

These are throughput protections against abuse of a single key, not a signal about system capacity — see [Performance](/production/performance).

## Handling 429s

Retry with exponential backoff. The response includes a `Retry-After` header (in seconds) when the limit is time-based.

```python theme={null}
import time, httpx

def search_with_retry(client, payload, max_retries=3):
    for attempt in range(max_retries):
        resp = client.post("/v1/search", data=payload)
        if resp.status_code == 429:
            wait = int(resp.headers.get("Retry-After", 2 ** attempt))
            time.sleep(wait)
            continue
        resp.raise_for_status()
        return resp.json()
```
