# Rate Limits

The entire API surface sits behind a **per-IP token-bucket rate limit**. The only exemption is `GET /health`, which lives outside the limiter so uptime monitors polling on a fixed cadence never read as fake downtime.

## The quota

| Parameter | Value |
| --- | --- |
| Scope | per client IP (peer address) |
| Sustained rate | **5 requests/second** (1 token replenished every 200 ms) |
| Burst | **60 requests** |
| Exempt | `GET /health` |

The burst comfortably covers interactive clients — a checkout widget or dashboard fires several requests per screen without tripping the limit — while still capping floods per IP.

## Handling `429`

Over the limit, the API answers `429` (with CORS headers, so a browser client can actually read it). The SDK surfaces this as a `PeltierApiError` with `status: 429` — back off and retry; it is always safe to retry a 429 (the request was never processed). See [Errors & Troubleshooting](/docs/errors.md) for the full retry guidance.

Because the scope is per-IP, callers that funnel through few addresses — server-side integrations, corporate NAT — share one bucket. Server-side code should space bulk calls (e.g. reconciliation sweeps over `GET /v1/payment_sessions`) rather than blasting them in parallel.

## 402 gates: put your own limits upstream

The [HTTP 402 payment gate](/docs/http-402.md) mints a **fresh checkout session for every unauthenticated request** it challenges (`POST /v1/payment_sessions` under your `sk_`). Peltier's per-IP limiter protects its own API, but it cannot see who is hammering *your* gated endpoint — an unauthenticated flood against your route becomes a session-mint flood from **your server's IP**, burning your own quota. Put a rate limit on the gated route **upstream of the gate** (per client IP or API key), so anonymous probing is capped before it reaches the challenge path.
