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

# Rate Limits

> Request limits and how to handle throttling

# Rate Limits

Every API-key-authenticated request returns rate-limit headers so your
integration can throttle proactively.

## Headers

Every API-key-authenticated response (including the `429` rejection) carries:

| Header                  | Description                                     |
| ----------------------- | ----------------------------------------------- |
| `X-RateLimit-Limit`     | Requests allowed per window                     |
| `X-RateLimit-Remaining` | Requests left in the current window             |
| `X-RateLimit-Reset`     | Unix timestamp (seconds) when the window resets |
| `X-RateLimit-Window`    | Window duration (e.g., `60s`)                   |
| `X-RateLimit-Policy`    | IETF-style policy string                        |

Read `X-RateLimit-Remaining` on each response and slow down as it approaches
`0` to avoid `429`s entirely. Session/JWT-authenticated requests use separate
role-based limits and do **not** receive these headers.

## Defaults

| Key Type    | Default Limit | Max Configurable |
| ----------- | ------------- | ---------------- |
| `nex_live_` | 60 req/min    | 6,000 req/min    |
| `nex_test_` | 60 req/min    | 6,000 req/min    |
| `nex_pat_`  | 60 req/min    | 600 req/min      |

Configure per-key limits when creating or updating keys via the API Keys
dashboard or `POST /api/api-keys`.

## Handling 429 Responses

When rate-limited, the API returns `429` with a `Retry-After` header (seconds)
plus the full `X-RateLimit-*` set, and this body:

```json theme={null}
{
  "error": {
    "message": "Rate limit exceeded for this API key",
    "code": "API_KEY_RATE_LIMITED",
    "suggestion": "This API key is limited to 60 requests/minute. Wait until the window resets (see the X-RateLimit-Reset header, a Unix timestamp) before retrying, or batch multiple operations into fewer requests.",
    "retryable": true
  }
}
```

Prefer honoring `Retry-After` / `X-RateLimit-Reset` when present; otherwise fall
back to exponential backoff with jitter:

Use exponential backoff with jitter:

```typescript theme={null}
async function withRetry(fn: () => Promise<Response>, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    const res = await fn();
    if (res.status !== 429) return res;
    const delay = Math.min(1000 * 2 ** i + Math.random() * 1000, 30000);
    await new Promise(r => setTimeout(r, delay));
  }
  throw new Error('Rate limited after retries');
}
```
