# Rate Limiting

ZevPay enforces rate limits to ensure fair usage and protect the API from abuse. All REST API endpoints are subject to rate limiting.

## Limits

| Scope | Limit | Window |
|-------|-------|--------|
| **Global** (per API key) | 100 requests | 1 minute |
| **Session initialization** (`POST /v1/checkout/session/initialize`) | 30 requests | 1 minute |

Rate limits are applied per API key. Test and live keys have separate counters.

::: info
These limits are generous for normal usage. If your integration requires higher limits, contact us at support@zevpay.ng.
:::

## Rate limit response

When you exceed the rate limit, the API responds with HTTP `429 Too Many Requests`:

```json
{
  "success": false,
  "error": {
    "code": "HTTP_ERROR",
    "message": "ThrottlerException: Too Many Requests"
  },
  "correlationId": "-"
}
```

## Handling rate limits

Implement exponential backoff when you receive a `429` response:

::: code-group

```js [Node.js]
async function fetchWithRetry(url, options, maxRetries = 3) {
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
    const response = await fetch(url, options);

    if (response.status !== 429) return response;

    // Exponential backoff: 1s, 2s, 4s
    const delay = Math.pow(2, attempt) * 1000;
    await new Promise(resolve => setTimeout(resolve, delay));
  }

  throw new Error('Rate limit exceeded after retries');
}
```

```python [Python]
import time
import requests

def fetch_with_retry(url, **kwargs):
    max_retries = 3
    for attempt in range(max_retries + 1):
        response = requests.request(**kwargs, url=url)

        if response.status_code != 429:
            return response

        # Exponential backoff: 1s, 2s, 4s
        delay = (2 ** attempt)
        time.sleep(delay)

    raise Exception("Rate limit exceeded after retries")
```

:::

## Best practices

- **Batch operations** where possible instead of making many individual requests
- **Cache responses** to avoid redundant API calls (e.g., cache bank list, verify results)
- **Spread requests** evenly over time rather than sending bursts
- **Use webhooks** instead of polling for payment status — see [Webhooks](/webhooks/overview)

## Request body size

All REST API endpoints enforce a **1 MB** maximum request body size. Requests exceeding this limit will be rejected with a `413 Payload Too Large` response.

This limit is more than sufficient for all API operations. If you're sending metadata with your requests, keep it concise.
