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

# Rate limits

> The per-key, per-IP, write and public-route limits, the request body limit, and how to handle 429 ENSC_RATE_LIMITED.

Requests are rate-limited per API key and per source IP. Exceeding a limit returns `429 ENSC_RATE_LIMITED` with a `Retry-After` header; the response is a plain (unsealed) error envelope.

## The limits

| Limit                                       | Applies to                                                                                           |
| ------------------------------------------- | ---------------------------------------------------------------------------------------------------- |
| 600 requests per minute and 10,000 per hour | per API key                                                                                          |
| 600 requests per minute                     | per source IP, on every route                                                                        |
| 60 requests per minute                      | per API key, on writes to the conversion, account-resolution and transfer routes                     |
| 120 requests per minute                     | per source IP, on the public routes (the key document, the OpenAPI documents and the reference page) |

The per-key default of 600 per minute can be set differently when the key is generated.

## Request size

A request body may be at most 1 MiB. A larger body is refused with `400 ENSC_VALIDATION_FAILED`.

## Handling 429

Back off and retry after the interval in `Retry-After`. The SDK does not retry `429`: it retries only network errors, timeouts and the statuses 500, 502, 503 and 504, so a rate-limited call surfaces as an `EnscError` with code `ENSC_RATE_LIMITED` for your own backoff.

```ts theme={null}
import { isEnscErrorCode } from '@ensc/sdk';

async function withBackoff<T>(fn: () => Promise<T>, attempts = 5): Promise<T> {
  for (let i = 0; ; i++) {
    try {
      return await fn();
    } catch (err) {
      if (!isEnscErrorCode(err, 'ENSC_RATE_LIMITED') || i + 1 >= attempts) throw err;
      await new Promise((r) => setTimeout(r, 1000 * 2 ** i));
    }
  }
}

const c = await withBackoff(() => ensc.conversions.create({ type: 'crypto-issue', chain: 'celo', wallet, pair: 'USDC', amount: '100' }));
```

A retried create is safe: the SDK keeps a stable idempotency key across its own retries, and re-posting a conversion `reference` returns the existing conversion. See [Idempotency](/guides/idempotency).

## Staying under the limits

* Receive outcomes by [webhook](/guides/webhooks) instead of polling `GET /v1/conversions/{reference}`.
* Cache ENSC's public keys from `GET /v1/.well-known/ensc-public-keys.json`, refetching only on an unknown key id. The SDK fetches them once per process.
* If several services share one egress address, remember that the per-IP limit counts all of them together.
