# Rate limits

> Per-key per-minute caps. How to read the headers and recover gracefully.

Each API key has a per-minute request budget enforced server-side. The budget scales with plan:

| Plan | Requests / minute |
| --- | --- |
| Free | 30 |
| Indie | 120 |
| Builder | 500 |

When you're over budget the server returns **`429 RATE_LIMITED`** with a `Retry-After` header (seconds).

## Headers

Every response, success or not, carries:

```
X-RateLimit-Limit:     <int>   // total budget
X-RateLimit-Remaining: <int>   // remaining this window
X-RateLimit-Reset:     <unix>  // seconds since epoch when the window resets
```

On a `429` we also include:

```
Retry-After: <seconds>
```

## Recovering

The official retry strategy is **exponential backoff with full jitter**, capped at 60 seconds:

```ts
async function withBackoff<T>(fn: () => Promise<T>, attempts = 5): Promise<T> {
  let lastErr: unknown;
  for (let i = 0; i < attempts; i++) {
    try {
      return await fn();
    } catch (err: any) {
      lastErr = err;
      if (err?.code !== "RATE_LIMITED") throw err;
      const retryAfter = Number(err.retryAfter ?? 1);
      const cap = Math.min(retryAfter, 60);
      const wait = Math.random() * cap * 1000;
      await new Promise((r) => setTimeout(r, wait));
    }
  }
  throw lastErr;
}
```

Future versions of the official SDK will handle this automatically.

Source: https://docs.nordva.dev/api-reference/rate-limits/
