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

# Rate limits & retries

> Request limits per product, what a 429 looks like, and how to implement correct backoff.

## Marketing API (`cloudapi.mailercloud.com`)

Requests are rate-limited per client IP using a sliding one-second window of **50 requests per second** (higher limits can be arranged for specific IPs — contact support).

When the limit is exceeded the API responds:

```http theme={null}
HTTP/1.1 429 Too Many Requests
```

```json theme={null}
{ "message": "Too Many Requests" }
```

<Warning>
  The API does not currently send `X-RateLimit-*` or `Retry-After` headers. Clients — especially AI agents doing batch work — should treat any `429` as a signal to back off exponentially rather than expecting a server-provided retry time.
</Warning>

## Email API (`email-api.mailercloud.com`)

Transactional sending is governed by your account's sending quota and throttling rules rather than a fixed per-second number. Two internal status codes signal limits (see [Errors](/errors)):

| Code   | Meaning                        | Action                          |
| ------ | ------------------------------ | ------------------------------- |
| `9001` | Throttling error               | Retry with backoff              |
| `9002` | Message sending quota exceeded | Do not retry — raise your quota |

## Email Verifier API (`verify.mailercloud.com`)

Requests are rate-limited; a `503 service busy, please retry` response also indicates transient capacity pressure — retry with backoff.

## Recommended retry strategy

Retry `429`, `5xx`, and throttling responses with exponential backoff and jitter; do not retry validation (`400`) or auth (`401`/`403`) errors.

```javascript theme={null}
async function withBackoff(fn, maxRetries = 5) {
  for (let attempt = 0; ; attempt++) {
    const res = await fn();
    if (res.status !== 429 && res.status < 500) return res;
    if (attempt >= maxRetries) return res;
    const delay = Math.min(30000, 1000 * 2 ** attempt) + Math.random() * 500;
    await new Promise((r) => setTimeout(r, delay));
  }
}
```

For sustained batch work (e.g. contact syncs), keep total request rate below the limit by pacing requests rather than relying on retries.
