## Rate Limits & Quotas

Two independent limits govern API usage:

### Technical rate limit (429)

Per-user requests-per-minute cap enforced on every endpoint.
When exceeded, the API returns `429 Too Many Requests`.
Back off and retry after the `Retry-After` header interval.

### Billing quota (402)

Monthly request budget from your plan.
When exhausted, the API returns `402 Payment Required`.
Quota resets on the first day of each calendar month (UTC).

### What counts against the quota

Only **successful** responses (2xx) decrement the monthly quota:

| Response | Monthly quota | Per-minute rate limit |
|---|---|---|
| `2xx` | decremented | counted |
| `304 Not Modified` | **not** decremented | counted |
| `4xx` / `5xx` | **not** decremented | counted |

The per-minute limit counts every request regardless of outcome — it is enforced
before the response is produced.

Statistics endpoints — `/stats/`, `/news/stats/`, `/jobs/stats/` — never
decrement the quota, so you can poll them freely (the per-minute limit still
applies). Requests made through the MCP server are not metered at all.

### Handling limits in code

```python
import time, requests

def call_with_retry(url, headers, max_retries=3):
    for attempt in range(max_retries):
        response = requests.get(url, headers=headers)
        if response.status_code == 429:
            retry_after = int(response.headers.get("Retry-After", 5))
            time.sleep(retry_after)
            continue
        response.raise_for_status()
        return response.json()
    raise RuntimeError("Max retries exceeded")
```

See [Errors](/docs/errors) for the full error-envelope format.
