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

# Rate limits

> How many requests your business can send, the headers that tell you where you stand, and what to do with a 429.

Some endpoints limit how many requests your business can send in a rolling window. Each business has its own limit, so other businesses' traffic never counts against yours. Going over the limit returns `429 Too Many Requests`.

## Limits

| Endpoint | Limit |
| - | - |
| `POST /transaction` | 60 requests per 60 seconds |
| `POST /customer/{customerId}/verify` | 100 requests per 24 hours |

Both limits apply in production and in sandbox.

The window is rolling: it counts the requests you sent in the last 60 seconds (or 24 hours), not since a fixed time. Requests rejected with `429` count too.

**Each limit is separate.** Being rate limited on one endpoint does not affect the other, and requests to one do not count against the other.

**Apart from these two, no endpoint has a per-business rate limit.** Reading data, such as listing or fetching transactions, customers, and payment methods, does not count toward these limits.

## Rate limit headers

Responses from these endpoints tell you where you stand against the limit:

| Header | Meaning |
| - | - |
| `X-RateLimit-Limit` | The maximum number of requests allowed in the window. |
| `X-RateLimit-Remaining` | The number of requests left in the current window. |
| `X-RateLimit-Reset` | Seconds until your next request fits in the window. |
| `Retry-After` | Sent with a `429`. Seconds to wait before you retry. |

## Handling a 429

A rate-limited request returns this body:

```json theme={null}
{
  "code": "RATE_LIMIT_ERROR",
  "error": "You can't make this request at the moment. Please try again later",
  "details": {}
}
```

When you receive one:

1. Wait the number of seconds in `Retry-After`, then retry.
2. Retry a transaction with the same `meta.idempotencyKey`, so a retry can never create a second transaction.
3. Don't retry straight away. Rejected requests count toward the limit, so an immediate retry keeps you limited. If you keep getting `429`s, pause and look for a loop in your integration.

## Testing in sandbox

Sandbox enforces the same limits as production, so you can trigger a `429` there and test your handling before you go live. Check that your integration:

* Reads `Retry-After` and waits that long before it retries.
* Retries a transaction with the same `meta.idempotencyKey`.
* Slows down as `X-RateLimit-Remaining` approaches `0`.

To trigger the transaction limit, send more than 60 `POST /transaction` requests within 60 seconds. Rejected requests count toward the limit, so a customer verify test that goes over its limit stays limited until the 24-hour window clears.

A sandbox load test above 60 transaction creates a minute sees `429`s, just as it would in production. Size load tests to the volume you expect in production.

## Staying within the limits

Watch `X-RateLimit-Remaining` and slow down before it reaches `0`.

Reading data does not count toward either limit. These habits don't change your count, but they keep your integration efficient:

* **Let webhooks tell you.** Transaction status changes arrive as [webhooks](/api-reference/endpoint/webhooks/introduction), so you don't need to fetch a transaction again and again to see whether it finished.
* **Reconcile with the list endpoint.** [List transactions](/api-reference/endpoint/transactions/list) with `fromDate` and `toDate` instead of fetching each transaction on its own.

## Higher limits

Need a higher limit? Email [support@afriex.com](mailto:support@afriex.com) and tell us which endpoint it is for, how many requests you expect at your busiest and on an ordinary day, and what you are building.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.