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

# Rate limits

> How limits are signalled, and how quota differs from rate.

Request-rate and in-flight concurrency limits apply globally, per IP, per organization, and per credential. Read the headers rather than assuming numbers.

## Headers

| Header | Meaning |
| - | - |
| `X-RateLimit-Limit` | The size of the controlling request-rate bucket. |
| `X-RateLimit-Remaining` | Requests immediately available in that bucket. |
| `X-RateLimit-Reset` | UTC Unix epoch seconds, rounded up, when the bucket is fully replenished. |
| `Retry-After` | On over-limit responses, seconds until the next request is permitted, when the limiter can compute it. |

The bucket described is whichever scope has the fewest requests left. The headers cover request rate only, not in-flight concurrency, plan usage, prepaid balance, or upstream limits.

## A 429

```http theme={"theme":{"light":"github-light","dark":"github-dark"}}
HTTP/1.1 429 Too Many Requests
Retry-After: 12
X-RateLimit-Limit: 120
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1788000000
Content-Type: application/json; charset=utf-8

{"error":{"message":"rate limited","code":"rate_limited"}}
```

An in-flight concurrency rejection is also `429 rate_limited`, with no fixed window: retry after one of your own requests completes.

## Quota

`insufficient_quota` also returns `429` but is a funding decision: prepaid balance, plan allowance, or the Free daily allowance is exhausted. Retrying does not clear it.

## Notes

* Limits are checked before a stream commits, so an over-limit streaming request returns a normal JSON error.
* If the limiter backend is unavailable, inference and MCP routes fail closed with `503 unavailable`.
* Honor `Retry-After`; otherwise back off exponentially with jitter. See [Backoff](/api/api-reference/errors-and-rate-limits/backoff). Bound your own concurrency. Never retry `insufficient_quota` in a loop.

## Related

* [Retry behavior](/api/api-reference/errors-and-rate-limits/retry-behavior)
* [Status mapping](/api/api-reference/errors-and-rate-limits/status-mapping)
* [Error codes](/api/api-reference/errors-and-rate-limits/error-codes)

## Inspect current capacity

`GET /api/v1/rate-limits` returns snapshots for the authenticated caller without consuming capacity in the groups being inspected. Use an organization API key or an OAuth bearer with `cli:inference`. No admin-key permission is required. Anonymous callers and MCP tokens are not supported.

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
curl https://app.trynito.ai/api/v1/rate-limits \
  -H "Authorization: Bearer $NITO_API_KEY"
```

Do not send query parameters, including model or scope selectors. The gateway derives scopes from your credential and connection. An optional `X-Org-ID` must match your credential's organization.

Illustrative response; the numbers are not fixed plan limits:

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "enabled": true,
  "data": [
    {"group":"inference_generate","coverage":"aggregate_request_limits","allowed":true,"limit":60,"remaining":58,"reset_at":1790000000,"retry_after":0},
    {"group":"inference_count","coverage":"request_limits","allowed":true,"limit":120,"remaining":120,"reset_at":1790000000,"retry_after":0},
    {"group":"model_list","coverage":"request_limits","allowed":true,"limit":120,"remaining":119,"reset_at":1790000000,"retry_after":0}
  ]
}
```

| Field | Meaning |
| - | - |
| `enabled` | Whether rate-limit enforcement is configured and enabled. |
| `group` | Generation, token counting, or model listing. |
| `coverage` | `aggregate_request_limits` for generation; `request_limits` for counting and model listing. |
| `allowed` | Whether the inspected request windows currently allow another request. |
| `limit` | Capacity of the controlling request bucket. |
| `remaining` | Available requests before the next request. |
| `reset_at` | Unix timestamp in seconds, rounded up, when the controlling bucket fully replenishes. |
| `retry_after` | Seconds until another request fits, rounded up; zero when allowed. |

`limit`, `remaining`, and `reset_at` are `null` when no applicable request bucket exists, including when enforcement is disabled. Zero remaining on a finite bucket means exhausted. If enforcement is disabled, `enabled` is `false`; rows allow requests and have zero `retry_after`.

The generation row excludes model-, stream-, and command-specific policies. Snapshots also exclude concurrency, MCP limits, other HTTP groups, billing/spend caps, and Free-plan quotas. They neither reserve capacity nor guarantee admission; concurrent requests can change capacity immediately, and the buckets are not read atomically.

## Polling and failures

Polling uses a separate management request quota. Response `X-RateLimit-*` headers describe that polling request, not the inspected groups; the JSON body describes the inspected capacity. Ordinary enforcement headers report capacity after the request, whereas snapshot `remaining` is before the next request.

* An exhausted inspected group returns HTTP `200` with `allowed: false` and a `retry_after` value.
* Exhausting the polling quota returns HTTP `429`; honor `Retry-After` when supplied.
* Limiter backend failure returns `503`, not unlimited capacity or a partial snapshot.
* Unsupported query parameters return `400`; authentication/organization failures use `401` or `403`.

Responses use `Cache-Control: no-store`. See the [endpoint schema](/api/api-reference/endpoints/rate-limits/get).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.