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

# Rate Limits

> Request limits, response headers, and how to handle 429s.

ReconLayer applies a request-rate limit to protect the API and your organization's workloads from runaway clients.

## Default limit

<Note>
  **300 requests per minute**, per organization.
</Note>

The limit is keyed by your resolved `organizationId` — every credential (API key or Clerk session) belonging to the same organization shares the same 300-requests-per-minute budget. Requests that don't resolve to an organization (which should not normally happen for authenticated `/v1/*` routes) are keyed by IP address instead.

Both the request ceiling and the time window are configurable per deployment via environment variables:

| Env var             | Default    | Meaning                                                |
| ------------------- | ---------- | ------------------------------------------------------ |
| `RATE_LIMIT_MAX`    | `300`      | Maximum requests allowed per window, per organization. |
| `RATE_LIMIT_WINDOW` | `1 minute` | The rolling time window the limit applies over.        |

If you're operating a high-volume integration and need a higher limit, contact ReconLayer support — limits are configured at the deployment level.

## Public paths are not rate-limited

`/health`, `/openapi.json`, `/openapi.yaml`, `/docs` (and `/docs/*`), and `/webhooks/*` are exempt from rate limiting — the same allow-list used for [public, unauthenticated routes](/api-reference/authentication).

## Response headers

Every response from a rate-limited route carries headers describing your current budget:

| Header                  | Meaning                                                        |
| ----------------------- | -------------------------------------------------------------- |
| `x-ratelimit-limit`     | The configured maximum requests per window (`RATE_LIMIT_MAX`). |
| `x-ratelimit-remaining` | Requests remaining in the current window.                      |
| `x-ratelimit-reset`     | Seconds until the current window resets.                       |

```http theme={null}
HTTP/1.1 200 OK
x-ratelimit-limit: 300
x-ratelimit-remaining: 287
x-ratelimit-reset: 42
```

## Exceeding the limit — `429`

Once your organization exceeds `RATE_LIMIT_MAX` requests within `RATE_LIMIT_WINDOW`, ReconLayer responds with `429 Too Many Requests` and adds a `retry-after` header (in seconds) indicating when the window resets:

```http theme={null}
HTTP/1.1 429 Too Many Requests
x-ratelimit-limit: 300
x-ratelimit-remaining: 0
x-ratelimit-reset: 38
retry-after: 38
```

```json 429 Too Many Requests theme={null}
{
  "statusCode": 429,
  "error": "Too Many Requests",
  "message": "Rate limit exceeded, retry in 1 minute"
}
```

## Handling `429`s

<Steps>
  <Step title="Read retry-after">
    Use the `retry-after` header (seconds) to decide how long to wait before your next request — don't guess or use a fixed backoff that ignores it.
  </Step>

  <Step title="Back off and retry">
    For idempotent writes, retry with the **same `Idempotency-Key` and request body** after the indicated delay — see [Idempotency](/api-reference/idempotency).
  </Step>

  <Step title="Spread bursty workloads">
    If you're paginating through a large list (e.g. an export or bulk reconciliation sweep), add a small delay between pages rather than firing requests as fast as possible. See [Pagination](/api-reference/pagination).
  </Step>

  <Step title="Watch x-ratelimit-remaining proactively">
    Slow down before you hit `0` rather than reacting only to `429`s — this avoids latency spikes from forced retries.
  </Step>
</Steps>

## Example: backoff loop

```bash theme={null}
until response=$(curl -s -w "%{http_code}" -o /tmp/body \
    "https://api.reconlayer.com/v1/payment-intents?limit=25&offset=0" \
    -H "Authorization: Bearer $RECONLAYER_API_KEY" \
    -D /tmp/headers); do
  sleep 1
done

if [ "$response" = "429" ]; then
  retry_after=$(grep -i '^retry-after:' /tmp/headers | awk '{print $2}' | tr -d '\r')
  echo "Rate limited, retrying in ${retry_after}s"
  sleep "$retry_after"
fi
```

## Next steps

* [Errors](/api-reference/errors) — the full error catalog, including other `4xx`/`5xx` statuses.
* [Idempotency](/api-reference/idempotency) — safely retrying write requests after a `429` or `5xx`.
* [Authentication](/api-reference/authentication) — how the organization that rate limits are keyed on is resolved.
