# Limits are per key, per minute, by class

Writes are limited harder than reads because they cost more to serve, and pipeline runs hardest of all because they cost real money.

## The classes

| Class | Applies to | Limit |
|---|---|---|
| read | every GET | 600 per minute |
| write | POST, PATCH and DELETE on content, taxonomy, keys and webhooks | 120 per minute |
| upload | `POST /media/upload-url` | 60 per minute |
| pipeline | `POST /pipeline/runs` | 10 per minute |

Every operation in the [reference](/docs/api) states its class, so you can work out a budget before you write the loop rather than after it is refused.

## The headers

Every response carries the state of your window, so you can slow down before you are refused rather than after.

on every response:

```
RateLimit-Limit: 600
RateLimit-Remaining: 587
RateLimit-Reset: 1786000860
```

- `RateLimit-Limit` is what your key is permitted in the current window for this endpoint class.
- `RateLimit-Remaining` is what is left in it.
- `RateLimit-Reset` is the Unix second at which the window resets.
- `Retry-After`, in seconds, is added to every 429. Honour it.

## When you are limited

`RATE_LIMIT_EXCEEDED`. Back off and honour `Retry-After`.

Limits are per key, per minute, by endpoint class. Writes are limited harder than reads
because they cost more to serve, and pipeline runs hardest of all because they cost real
money.

| Class | Endpoints | Limit |
|---|---|---|
| read | every GET | 600 per minute |
| write | POST, PATCH and DELETE on content, taxonomy, keys and webhooks | 120 per minute |
| upload | `POST /media/upload-url` | 60 per minute |
| pipeline | `POST /pipeline/runs` | 10 per minute |

Every response carries `RateLimit-Limit`, `RateLimit-Remaining` and `RateLimit-Reset`,
so you can slow down before you are refused rather than after.

> The window slides rather than resetting on a fixed boundary. Aligning a burst to the top of a minute buys you nothing, and a steady rate is always better treated than a spike followed by a wait.

- **Back off exponentially**, starting from `Retry-After`, and add jitter. A fleet of workers that all retry after exactly the same delay recreates the burst that limited them.
- **Batch reads with `limit` and `fields`** rather than fetching one article at a time. One request for 100 projected rows costs one unit; 100 requests cost 100.
- **Do not poll `GET /pipeline/runs` in a tight loop.** Subscribe to `pipeline.run.completed` instead.
- **A 429 is not a spend gate.** If you are looking for the thing that stops runaway cost, that is the 402 family on the [errors page](/docs/errors#the-three-402s).

## Higher limits

Some plans raise the ceiling. It applies automatically to the keys on the Site and needs no change to your code; the first request of a session runs at the standard rate and the elevated rate applies from the next one.

If you are hitting a limit with a legitimate workload, that is worth a conversation rather than a retry loop. Contact [support](https://writavo.com/support).
