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

# Handle throttling and plan around request limits

> Per-environment rate limits, response headers, and retry strategies

Every request to the mintfax API counts against a per-environment rate limit. The limit structure, response headers, 429 response shape, and client backoff strategies are all covered here.

<h2 id="how-limits-are-applied">
  How limits are applied
</h2>

Rate limits are scoped to the API key that authenticates the request. Each API key belongs to an environment, so the limit is effectively per-environment. Sandbox and live environments have independent limits.

mintfax enforces a sliding window measured in requests per minute. Every response includes headers showing where you stand within that window. Your client can read these and pace itself before hitting the ceiling.

<h2 id="response-headers">
  Response headers
</h2>

Three rate-limit headers appear on every API response, regardless of whether the request succeeded.

| Header                  | Type    | Description                                         |
| ----------------------- | ------- | --------------------------------------------------- |
| `X-RateLimit-Limit`     | integer | Maximum requests allowed per minute for this key    |
| `X-RateLimit-Remaining` | integer | Requests remaining in the current one-minute window |
| `X-RateLimit-Reset`     | integer | Seconds until the current window resets             |

When the API rejects a request with HTTP 429, the response also includes a `Retry-After` header. Its value is the number of seconds to wait before sending the next request.

```
HTTP/1.1 429 Too Many Requests
Content-Type: application/json
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 34
Retry-After: 34
```

**Edge cases**

* `X-RateLimit-Remaining` can reach `0` before you see a 429 if multiple requests are in flight simultaneously.
* `X-RateLimit-Reset` counts down from the start of the window. Whether the request succeeded or failed does not affect it.

<h2 id="429-response-body">
  429 response body
</h2>

A rate-limited request returns the standard [error envelope](/docs/errors) with the `rate_limit_exceeded` code.

```json theme={null}
{
  "error": "rate_limit_exceeded",
  "message": "Too many requests. Please slow down and try again.",
  "action": "wait_and_retry",
  "docs": "https://mintfax.com/docs/errors/rate-limit-exceeded"
}
```

The `action` field is `wait_and_retry`. Read the `Retry-After` header and pause for that many seconds before retrying.

**Edge cases**

* `Retry-After` is always in whole seconds, never a date.
* Retrying before `Retry-After` elapses produces another 429 with a fresh `Retry-After` value.

<h2 id="sandbox-and-live-limits">
  Sandbox and live limits
</h2>

Sandbox and live environments enforce separate rate limits. Each environment's API keys count against that environment's own quota. Hitting the limit on a sandbox key does not affect your live environment, and the reverse is also true.

<h2 id="designing-clients">
  Designing clients that respect rate limits
</h2>

### Read the headers before you need them

Check `X-RateLimit-Remaining` on every response. When it drops below a threshold you consider safe (10% of `X-RateLimit-Limit`, for example), slow down proactively instead of waiting for a 429.

### Use exponential backoff on 429

When you receive a 429, wait for the number of seconds in `Retry-After`, then retry. If the retry also comes back 429, double the wait time. Cap the backoff at 60 seconds.

```python theme={null}
import time
import requests

def send_with_backoff(url, headers, data, max_retries=5):
    for attempt in range(max_retries):
        response = requests.post(url, headers=headers, data=data)

        if response.status_code != 429:
            return response

        retry_after = int(response.headers.get("Retry-After", 1))
        wait = retry_after * (2 ** attempt)
        wait = min(wait, 60)
        time.sleep(wait)

    return response
```

### Combine with idempotency keys

When retrying a `POST /fax` request after a 429, use the same [idempotency key](/docs/idempotency) on the retry. If the original request was actually accepted before the 429 reached your client, the retry returns the original response instead of creating a duplicate fax.

### Avoid polling loops

Do not poll `GET /fax/{id}` in a tight loop to check delivery status. Use [webhooks](/docs/webhooks) instead. Webhooks push status updates to your server as they happen, so you do not burn rate-limit quota tracking fax progress.

If you must poll, space requests at least 5 seconds apart and stop once the fax reaches a terminal state (`delivered` or `failed`).

### Agent and LLM callers

If an LLM or agent is calling the API, pass the `X-RateLimit-Remaining` and `Retry-After` values back in the context the agent receives. This lets the agent adjust pacing without guessing. Hard-code the backoff logic in your integration layer so the agent cannot override it and flood requests.

***

*Last updated: 2026-05-09*
