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

# rate_limited

> 429 rate_limit — too many spending POSTs per minute. Reads are never rate-limited.

**HTTP 429 · type `rate_limit`.** Spending POSTs (creates, turns, refreshes,
estimates) are limited per key — 60/minute on a new account. You've exceeded that
rate. Nothing was charged.

Two things are deliberately **not** limited this way:

* **Reads (GET) are not rate-limited at all** — polling is never the thing we
  throttle.
* **Expensive work is limited by concurrency, not rate** — that's the separate
  [`concurrency_cap`](/errors/concurrency_cap).

Spend ceilings are also not rate limits — running out of money is a
[402](/errors/insufficient_credit)/[403](/errors/monthly_cap_exceeded), never a 429.

## The shape

```json theme={null}
{
  "error": {
    "type": "rate_limit",
    "code": "rate_limited",
    "message": "60 spending POSTs per minute per key; retry in 12 seconds.",
    "doc_url": "https://docs.fiveninelabs.com/errors/rate_limited",
    "request_id": "req_7cc31d",
    "retry_after_s": 12
  }
}
```

Headers ride along: `Retry-After`, plus `x-ratelimit-limit`,
`x-ratelimit-remaining`, and `x-ratelimit-reset`.

## How to fix

* Honor `Retry-After` (or `retry_after_s`) with backoff. Retrying a spending POST is
  safe when you send the same `Idempotency-Key` — a replay never bills twice.
* Watch `x-ratelimit-remaining` and pace proactively instead of bouncing off the
  limit.
* If you're burning the bucket on `POST /v1/sessions/estimate` (it's free but sits in
  the spending-POST bucket as its only guard), batch or debounce your quoting.
* Sustained legitimate volume above the default? Ask us to raise the key's limit.

## Reproduce it

Hammer the free estimate endpoint past 60/min on an `fn_test_` key (\$0):

```bash theme={null}
for i in $(seq 1 70); do
  curl -s -o /dev/null -w "%{http_code}\n" \
    https://api.fiveninelabs.com/v1/sessions/estimate \
    -H "Authorization: Bearer $FIVENINE_TEST_KEY" \
    -H "Content-Type: application/json" \
    -d '{"query": "vinyl records"}'
done
# the tail of the output turns from 200 to 429
```
