<!-- @generated by `npm run docs:gen` from src/content/docs/ — DO NOT EDIT. -->

# Rate limits

The Ask Xverum API enforces a **token-bucket** rate limit per API key.

## Default limits

| Endpoint | Limit | Scope |
| --- | --- | --- |
| `POST /v1/search` | 60 requests/minute | Per API key |
| `GET /v1/profiles/{id}` | 60 requests/minute | Per API key |

The bucket refills continuously at `rpm / 60` tokens per second, so you can burst up to the per-minute cap as long as the average stays within the limit.

Each API key has its own bucket. A custom per-key limit configured in user-management is honoured when present; otherwise the default above applies.

> [!NOTE]
> This rate-limit "token" is a request allowance — distinct from the billing credits drawn from your account balance per result/fetch.

## Quota headers

Every API response (success **or** error) carries the current quota state:

```http
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 57
X-RateLimit-Reset: 1716640000
```

| Header | Meaning |
| --- | --- |
| `X-RateLimit-Limit` | Requests allowed per minute for this key. |
| `X-RateLimit-Remaining` | Requests left in the current window. |
| `X-RateLimit-Reset` | Unix seconds at which the bucket is fully refilled. |

## Hitting the limit

When the limit is exceeded the API returns `429 Too Many Requests` with a `Retry-After` header (always ≥ 1 second) and the structured error envelope:

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

{"error": {"code": "rate_limited", "message": "Rate limit exceeded", "request_id": "9f1c2a7e6b3d4f08"}}
```

## Recommended backoff

For server-to-server integrations, retry the request with an exponentially-growing delay seeded by `Retry-After`. A short jitter (±25%) helps avoid thundering-herd behaviour when several clients recover at once.

```python
import random
import time

def backoff_seconds(retry_after: float, attempt: int) -> float:
    base = max(retry_after, 1) * (2 ** attempt)
    jitter = 1 + random.uniform(-0.25, 0.25)
    return min(base * jitter, 30.0)
```

Give up after a small number of attempts (3–5) and surface the failure to the caller rather than retrying indefinitely.

## Higher quotas

If 60 rpm isn't enough for your use case, contact Xverum support to discuss a higher tier or a per-key override.
