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

# Rate limits

> The global request budget, the much stricter per-route throttles on auth and payment routes, and how to read a 429.

There are two layers: a **global budget** that applies to ordinary traffic, and
**per-route throttles** that are far stricter. The per-route throttle is the one that will
surprise you, because it fires during integration testing.

## Global budget

Every response carries the current budget:

```http theme={null}
x-ratelimit-limit: 60
x-ratelimit-remaining: 59
x-ratelimit-reset: 60000
```

| Header | Meaning |
| - | - |
| `x-ratelimit-limit` | Requests allowed in the window. `60` on public GETs. |
| `x-ratelimit-remaining` | Requests left in the current window. |
| `x-ratelimit-reset` | Time until the window resets, **in milliseconds**. |

## Per-route throttles

Auth and money routes carry their own, tighter limits. These are enforced **in addition
to** the global budget — the stricter of the two wins.

| Route | Limit | Window | Extra gate |
| - | - | - | - |
| `POST /merchant/login` | 5 | 15 min | also throttled **per email address** |
| `POST /merchant/register` | 5 | 1 min | CAPTCHA |
| `POST /merchant/admin/login` | 5 | 1 min | — |
| `POST /merchant/forgot-password` | 5 | 15 min | CAPTCHA + per-email |
| `POST /merchant/reset-password` | 5 | 1 min | — |
| `POST /merchant/verify-email` | 10 | 1 min | — |
| `POST /merchant/verify-reset-code` | 10 | 1 min | — |
| `POST /merchant/resend-verification` | 3 | 1 min | CAPTCHA |
| `POST /merchant/refresh` | 20 | 1 min | — |
| `POST /payment/webhook/paymob` | 20 | 1 min | — |
| `POST /payment/webhook/generic` | 10 | 1 min | — |

> [!WARNING]
>
> **The login throttle is per-email as well as per-IP.** Rotating source IPs does not widen
> it — that is deliberate, it defeats credential stuffing across residential proxy pools. In
> practice it means an integration test that loops over login six times will get a `429` on
> the sixth call and stay blocked for the rest of the 15-minute window, for that email
> address, everywhere. Cache the token; do not re-login per request.

## Reading a 429

```http theme={null}
HTTP/2 429
retry-after: 889843
```

```json theme={null}
{ "statusCode": 429, "status": "failed", "data": { "message": "ThrottlerException: Too Many Requests" } }
```

> [!NOTE]
>
> **`Retry-After` is emitted in milliseconds, not seconds.** It is the same unit as
> `x-ratelimit-reset`, not the RFC 9110 delta-seconds a generic HTTP client will assume. The
> value above is \~890 **seconds** (≈15 minutes), not \~890,000 seconds. Divide by 1000 before
> you sleep on it, or you will back off for ten days. Both units are stated here because a
> partner's retry layer will otherwise get this wrong silently.

## Backoff guidance

* Retry on `429` and `503`. Do not retry `400`, `401`, `403` or `404` — they are
  deterministic.
* Use exponential backoff with jitter, seeded from `Retry-After` in milliseconds.
* Never retry a payment-initiating call faster than the PSP's own webhook can arrive; see
  [Idempotency and retries](/guides/payments/idempotency-and-retries.md) for what is and is
  not safe to repeat.

## Quota increases

There is no self-serve quota console. If your integration needs more than the global
budget, talk to your Droplinked counterpart with a request-per-second figure and the routes
involved — the throttles above are per-route, so raising one does not require raising all.


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