# Rate limits

> A Nodaro API token allows 30 run requests per minute by default, up to 120. See the per-route limits, the two 429 codes, batch sizes and how to back off.

Source: https://nodaro.ai/docs/developers/api/rate-limits

**Rate limits** protect the Nodaro API from bursts of requests. Each personal API token has its own per-minute budget for workflow runs, a few routes have limits of their own, and a request over a limit answers `429 Too Many Requests`. Polling a job or a run never counts against a token's budget, so you can poll every few seconds without running out.

## The per-token limit

Every personal API token has a budget of requests per minute:

- **30 requests per minute by default.** You set the limit when you create the token, in **Rate Limit (requests/min)**, from 1 to 120. Change it later with `rateLimit` on `PATCH /v1/api-tokens/:id`.
- **Only two routes count:** `POST /v1/api/run` and `GET /v1/api/workflows`.
- **Reads do not count.** `GET /v1/api/status/:execId`, `GET /v1/api/result/:execId` and `GET /v1/api/schema` do not use the budget.
- **The budget resets every minute.**

A request over the budget answers:

```json
{ "error": { "code": "rate_limited", "message": "Too many requests. Max 30 per minute." } }
```

To go faster, raise the token's limit to 120. Beyond that, create more tokens, up to 10 per account, and spread your requests across them. See [Authentication](https://nodaro.ai/docs/developers/api/authentication).

## Other limits

| Route | Limit | Answer when over |
| --- | --- | --- |
| `POST /v1/webhooks/:token` ([Webhook Trigger](https://nodaro.ai/docs/nodes/automate/webhook-trigger)) | 10 requests per minute for each trigger | `429` |
| A published app's runs | The app's daily run limit for each user | `429 rate_limit_exceeded` |
| `POST /v1/download-video` | 4 video imports running at once for each account | `429 too_many_downloads` |
| `POST /v1/video-overlay` | 30 requests per minute for each user | `429 rate_limit_exceeded` |
| `POST /v1/freecut-export` | 10 requests per minute | `429 rate_limit_exceeded` |
| `POST /v1/characters/:id/train` | 3 requests per minute for each token | `429 rate_limit_exceeded` |
| `POST /v1/oauth/register` | 10 requests per minute for each IP address | `429 rate_limit_exceeded` |
| `POST /v1/orgs` | A few new organizations per hour for each user | `429 rate_limit_exceeded` |
| `POST /v1/workspaces/join` | 10 attempts per minute for each account and 30 for each IP address | `429 rate_limit_exceeded` |
| `POST /v1/workflows/:id/collaborators` | 20 additions per minute for each account | `429 rate_limit_exceeded` |
| Usage exports as CSV | 10 per minute for each user | `429 rate_limit_exceeded` |
| `POST /v1/orgs/:id/invitations` | 500 invitations a day for each organization | `429 bulk_invite_cap_exceeded` |
| `GET /v1/invitations/by-token/:token`, `GET /v1/shots/:id`, the SSO sign-in exchange | A limit for each IP address | `429 rate_limit_exceeded` |

## Two different 429 codes

- **`rate_limited`** comes only from the per-token budget of the `/v1/api/` routes.
- **`rate_limit_exceeded`** comes from every other limit: the limits for each IP address on a few routes that need no token, the limits for each caller on specific routes, and a published app's daily runs.

Routes with a limit for each caller send a `Retry-After` header. On a route that spends credits, the server answers `503 rate_limit_unavailable` when it cannot check the limit.

Base your retry logic on the `429` status. Use the code only to tell the per-token budget from the other limits.

## Handle limits well

- **Poll every 2 to 5 seconds.** A run changes state in seconds, and faster polling gains nothing.
- **Poll many jobs in one call.** `GET /v1/jobs/status` and `POST /v1/jobs/batch-status` return up to 100 jobs each. See [Jobs](https://nodaro.ai/docs/developers/api/jobs#poll-many-jobs-at-once).
- **Back off exponentially on `429`:** wait 5 seconds, then 10, then 20, before each retry. When `Retry-After` is present, wait at least that long.
- **Treat other `4xx` errors as final.** Fix the request instead of retrying it. See [Errors](https://nodaro.ai/docs/developers/api/errors).

```ts

async function withBackoff<T>(call: () => Promise<T>): Promise<T> {
for (const seconds of [5, 10, 20]) {
try {
return await call()
} catch (err) {
if (!(err instanceof RateLimitedError)) throw err
await new Promise((r) => setTimeout(r, seconds * 1_000))
}
}
return call()
}

const { executionId } = await withBackoff(() => client.workflows.run(workflowId))
```

## Batch and page sizes

| Endpoint | Limit |
| --- | --- |
| `GET /v1/jobs/status?ids=…` | Up to 100 ids |
| `POST /v1/jobs/batch-status` | Up to 100 ids |
| `GET /v1/jobs` | `limit` up to 100 |
| `GET /v1/characters` | `limit` up to 500, 100 by default |
| `GET /v1/objects`, `/v1/creatures`, `/v1/locations`, `/v1/faces` | `limit` up to 500 |
| `GET /v1/credits/transactions` | `limit` from 1 to 50, 20 by default |
| `POST /v1/credits/model-costs` | Up to 50 model ids |
| `GET /v1/community/browse` | `limit` up to 50, 20 by default |
| `GET /v1/orgs/:id/members` | `limit` up to 200, 50 by default |
| `POST /v1/orgs/:id/invitations` | Up to 200 addresses in one call |
| API tokens | 10 for each account |
| OAuth developer apps | 5 registered by hand for each user |

## Frequently asked questions

### What is the rate limit of a Nodaro API token?

30 requests per minute by default, and you can raise it to 120 for each token. The limit counts only workflow runs and workflow lists, POST /v1/api/run and GET /v1/api/workflows.

### Does polling count against my rate limit?

No. Reading a run's status, its result or a workflow's schema does not use the token's budget, and neither do job status reads. Poll every 2 to 5 seconds.

### What should I do when I get a 429 error?

Wait and retry with exponential backoff, for example after 5, 10 and 20 seconds. When the response has a Retry-After header, wait at least that long. Match your retry logic on the 429 status, not on the error code.

### How do I get a higher rate limit?

Raise the token's rate limit up to 120 requests per minute. Beyond that, create more tokens, up to 10 per account, and spread your requests across them.

### Are webhook triggers rate limited?

Yes, separately from API tokens. Each Webhook Trigger accepts 10 requests per minute on its own URL.
