# Rate limits

> 600 requests per minute per key, the headers that show how many are left and how to react to a 429.

| Limit | Value | Window |
|---|---|---|
| Requests per key | 600 | fixed 60 seconds |
| `POST /clips/info` | 10 | fixed 60 seconds |

`POST /clips/info` has its own limit because each call queries the video's source platform.

## Headers

Every response carries the state of the current window, so you can slow down before being cut off:

| Header | Description |
|---|---|
| `X-RateLimit-Limit` | The window ceiling (600) |
| `X-RateLimit-Remaining` | Requests that still fit in this window |
| `X-RateLimit-Reset` | When the window resets, in Unix seconds |

## When you pass the limit

```json title="429 Too Many Requests"
{ "code": "RATE_LIMIT_EXCEEDED" }
```

The `Retry-After` header says how many seconds to wait. Respect it: retrying immediately only burns the next window.

```js
async function call(url, init) {
	const response = await fetch(url, init);
	if (response.status !== 429) return response;
	const seconds = Number(response.headers.get("Retry-After") ?? 1);
	await new Promise((resolve) => setTimeout(resolve, seconds * 1000));
	return call(url, init);
}
```

`503 SERVICE_UNAVAILABLE` also comes with `Retry-After`. Handle it the same way.

## Concurrency limits

Some limits are not about requests, they are about how many jobs run at the same time. They also respond `429`, with a different `code`:

| Code | When | What to do |
|---|---|---|
| `TOO_MANY_PENDING_CLIPS` | Too many clippings in the workspace queue | Wait for one to finish. |
| `BATCH_ALREADY_RUNNING` | A template is already being applied in bulk on the account | Wait for the batch to finish. |
| `TOO_MANY_RUNNING` | Too many AI generations running at the same time | Wait for one to finish. |

### Renders

The plan defines how many renders run at the same time (`max_concurrent`). Those beyond that wait in the queue and show up in `queued_count`. `GET /renders/limits` also shows the maximum resolution, the watermark and for how many hours the MP4 is kept.

```bash
curl https://api.cut.pro/api/v1/renders/limits \
  -H "X-Api-Key: $CUTPRO_API_KEY"
```

```json title="200 OK"
{
  "usage": { "active_count": 2, "queued_count": 1, "total_pending": 3, "max_concurrent": 5 },
  "plan": {
    "video_quality": "1080p",
    "watermark": false,
    "priority_processing": true,
    "max_concurrent_renders": 5,
    "render_expiry_hours": 168
  }
}
```

## Polling

Polling a job every 5 to 10 seconds is the expected pattern. With 600 requests per minute, you can follow 50 jobs at the same time polling every 5 seconds.
