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

# Limits

> Every numeric limit in the OpenType API: body size, 256k-token decisions, deadlines, question and schema bounds, spend ceilings, lists and quotas.

This page collects every limit the API enforces, the value, and the error you get when you cross it. Use it when you design a question set or a schema, size an input, or plan how much a batch job can send. All of these are checked per request; none of them is a rate.

<Note>
  There is no request-rate limit. OpenType does not count requests per second or per minute, and no response carries a rate-limit header. A `429` is only ever a [period quota](#period-quotas) refusal.
</Note>

## Requests

| Limit             | Value                                        | Applies to                                                      | When exceeded                                            |
| ----------------- | -------------------------------------------- | --------------------------------------------------------------- | -------------------------------------------------------- |
| Body size         | 4 MiB (4,194,304 bytes)                      | `POST /v1/runs`, `POST /v1/router/select`                       | `413 body_too_large`                                     |
| Body size         | 1 MiB (1,048,576 bytes)                      | every other route                                               | a plain-text 413                                         |
| `Idempotency-Key` | 1 to 255 bytes of printable ASCII            | `POST /v1/runs` (required), `POST /v1/router/select` (optional) | `400 invalid_idempotency_key`                            |
| `x-request-id`    | 1 to 128 characters from `A-Z a-z 0-9 . _ -` | every route                                                     | not an error: the server mints its own `req_` id instead |

An `Idempotency-Key` is scoped to your organization and never expires: a key used once always refers to the same run.

## Runs

These apply to every `POST /v1/runs`, decision or verdict.

| Limit                        | Value                                                                        | When exceeded                                                                                                                                                |
| ---------------------------- | ---------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `max_output_tokens`          | required, at least 1                                                         | `400 invalid_body`                                                                                                                                           |
| `deadline_ms`, verdict run   | 1 to 120,000; default 30,000                                                 | not an error: values outside the range are clamped (0 becomes 1, larger values become 120,000). A run that runs out of time answers `504 deadline_exceeded`. |
| `deadline_ms`, decision run  | 1 to 150,000; default 30,000 plus 120,000 per 262,144 input tokens           | clamped the same way, to 150,000 at most. See [Long-context decisions](#long-context-decisions).                                                             |
| `capability_hint`            | at most 7 values, no duplicates                                              | `400 invalid_verdict_schema`                                                                                                                                 |
| Estimated input, verdict run | 64,000 tokens                                                                | `413 input_too_large`                                                                                                                                        |
| Spend per request            | 20,000 micro-USD (\$0.02), or less if your organization sets a lower ceiling | `503 budget_exhausted` when the run's budget cannot cover the call                                                                                           |

The input estimate is `ceil(prompt bytes / 4) + ceil(contract bytes / 4)`, where the prompt is `system` plus `messages` (or the decision `state`) and the contract is your schema or question set. Roughly, 4 bytes of JSON count as one token.

Each run holds its whole spend ceiling as a reservation until it settles, then is charged what it actually cost. With billing on, a run therefore needs up to 20,000 micros of available credit to start, even when it will cost far less.

## Decision runs

| Limit                     | Value                                                                                                                        | When exceeded                    |
| ------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | -------------------------------- |
| Estimated input, Neon 1.1 | 262,144 tokens (256k)                                                                                                        | `413 input_too_large`            |
| Questions per run         | 1 to 64                                                                                                                      | `400 invalid_decision_questions` |
| Alternatives per question | 2 to 20 (`noul` always has 2)                                                                                                | `400 invalid_decision_questions` |
| Question id               | non-empty; no `:`, no line break; unique in the set                                                                          | `400 invalid_decision_questions` |
| Alternative names         | unique within a question                                                                                                     | `400 invalid_decision_questions` |
| `draws`                   | 1 to 8; default 1                                                                                                            | `400 invalid_decision_questions` |
| `think_tokens`            | 0 to 4,096; default 0                                                                                                        | `400 invalid_decision_questions` |
| Question set size         | 32 KiB for `instructions` + `questions` + `draws` + `think_tokens`; `state` is not counted                                   | `400 invalid_decision_questions` |
| `depends_on` and `ask_if` | must name other questions in the set, with no cycle; every `ask_if` list non-empty and naming answers its target can produce | `400 invalid_decision_questions` |
| `question_order`          | exactly the keys of `questions`                                                                                              | `400 invalid_body`               |
| `model`                   | `neon-1.1` or `neon-latest`; optional                                                                                        | `400 unknown_model`              |
| Model calls per run       | exactly 1                                                                                                                    |                                  |

Neon 1.1 reads up to 262,144 tokens of input per decision. Verdict runs keep the 64,000-token ceiling. Keep `state` to the fields the questions need: a smaller input is cheaper and returns sooner.

## Long-context decisions

A decision run can carry up to 262,144 input tokens (256k) in a body of up to 4 MiB. Reading that much takes the model longer, so the deadline of a decision scales with its input:

| Input                 | Default deadline | Typical model time |
| --------------------- | ---------------- | ------------------ |
| a few thousand tokens | about 30 s       | a few seconds      |
| 128k tokens           | about 90 s       | about 40 s         |
| 253k tokens           | about 146 s      | about 110 s        |
| 262,144 tokens        | 150 s            |                    |

The default is `30,000 + 120,000 × input_tokens / 262,144` milliseconds, clamped to 150,000. You can send a shorter `deadline_ms`, or a longer one up to 150,000. Verdict runs keep their own range: default 30,000, at most 120,000.

Set your HTTP client timeout to at least **160 seconds**, above the longest deadline, so the server rather than your client ends a slow run and you receive the `504 deadline_exceeded` with its `request_id`. The official SDKs default to 170 seconds.

A long input is priced like any other, per token: a full 262,144-token read with 16 output tokens costs 11,012 micro-USD, within the 20,000 micro-USD per-run ceiling. See [Models and pricing](/getting-started/models-and-pricing).

## Response timing

`POST /v1/runs` returns a `Server-Timing` header with the time spent in each phase, in milliseconds:

```text theme={"system"}
Server-Timing: admit;dur=3.12, upstream;dur=812.40, gateway;dur=9.85, total;dur=822.25
```

| Phase      | Meaning                                                                    |
| ---------- | -------------------------------------------------------------------------- |
| `admit`    | Authentication, validation, quota and credit checks before the run starts. |
| `upstream` | The model call.                                                            |
| `gateway`  | Everything except `upstream`: the service's own overhead.                  |
| `total`    | The whole request, as the server saw it.                                   |

Compare `total` with your client's own measurement to see how much time the network took. The header is on `200` and `202` responses and on most refusals.

Two properties are not checked at admission: whether each alternative name is a single token for the model, and whether the set fits the model's answer template. A set that fails either is refused later with `503 decision_unavailable`. See [Decision questions](/getting-started/decision-questions).

## Verdict schemas

| Limit             | Value                                                                                                                                              | When exceeded                  |
| ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------ |
| Schema type       | a JSON object                                                                                                                                      | `400 invalid_verdict_schema`   |
| Schema size       | 32 KiB                                                                                                                                             | `400 invalid_verdict_schema`   |
| Nesting depth     | 12                                                                                                                                                 | `400 invalid_verdict_schema`   |
| Nested subschemas | 64                                                                                                                                                 | `400 invalid_verdict_schema`   |
| Properties        | 512                                                                                                                                                | `400 invalid_verdict_schema`   |
| `pattern` length  | 256 characters                                                                                                                                     | `400 invalid_verdict_schema`   |
| `$ref`            | a local pointer starting with `#`, pointing inside the same schema                                                                                 | `400 invalid_verdict_schema`   |
| Refused keywords  | `$id`, `id`, `$anchor`, `$dynamicAnchor`, `$dynamicRef`, `$recursiveAnchor`, `$recursiveRef`, and any unrecognised keyword with a structured value | `400 invalid_verdict_schema`   |
| Model attempts    | 2: one answer plus one repair                                                                                                                      | `503 verdict_schema_violation` |

See [Verdict runs](/guides/verdict-runs).

## Lists and reports

| Limit                          | Value                | When exceeded                                                    |
| ------------------------------ | -------------------- | ---------------------------------------------------------------- |
| `GET /v1/runs` `limit`         | 1 to 100; default 20 | clamped, not refused                                             |
| `GET /v1/runs` `offset`        | 0 or more; default 0 | a non-integer is `400 invalid_body`                              |
| `GET /v1/usage/ledger` `limit` | 1 to 200; default 50 | `0` is `400 invalid_parameter`; larger values are clamped to 200 |
| `GET /v1/usage/daily` window   | at most 92 days      | `400 invalid_parameter`                                          |
| `GET /v1/billing` transactions | the last 50          | fixed                                                            |
| `GET /v1/keys`                 | every key, no paging |                                                                  |

## Billing

| Limit                            | Value                                                     | When exceeded        |
| -------------------------------- | --------------------------------------------------------- | -------------------- |
| Checkout `amount_micros`         | 5,000,000 to 1,000,000,000 ($5 to $1,000), in whole cents | `400 invalid_amount` |
| Auto-recharge `amount_micros`    | same as checkout                                          | `400 invalid_amount` |
| Auto-recharge `threshold_micros` | at most 1,000,000,000 (\$1,000)                           | `400 invalid_amount` |
| Auto-recharge charges            | at most one per organization per clock hour               |                      |

## Period quotas

An organization can have two limits per quota period. The period is the current UTC calendar month. `GET /v1/quota` returns the limits, what the period has consumed, and what remains; a `null` limit means none is set.

| Quota         | What is compared                                                                                            | When exceeded                            |
| ------------- | ----------------------------------------------------------------------------------------------------------- | ---------------------------------------- |
| Period spend  | the run's spend ceiling (up to 20,000 micros), not its actual cost, against the spend remaining this period | `429 organization_spend_quota_exhausted` |
| Period tokens | estimated input tokens plus `max_output_tokens` against the tokens remaining this period                    | `429 organization_token_quota_exhausted` |

Because the spend check uses the ceiling, a run can be refused while the period still has a little room left. Held reservations count against the remaining spend until they settle, so a burst of concurrent runs can hit the quota and then clear as those runs finish.

A refused run stores nothing, so the same `Idempotency-Key` is reusable. A replay of a key that already owns a run is never refused with `429`.

<CodeGroup>
  ```bash cURL theme={"system"}
  curl -sS https://api.opentype.dev/v1/quota \
    -H "Authorization: Bearer $OPENTYPE_API_KEY"
  ```

  ```ts TypeScript theme={"system"}
  const res = await fetch("https://api.opentype.dev/v1/quota", {
    headers: { Authorization: `Bearer ${process.env.OPENTYPE_API_KEY}` }, // needs usage_read
  });
  const quota = await res.json();
  if (!res.ok) throw new Error(`${quota.error.code} (${quota.error.request_id})`);
  console.log("spend left:", quota.remaining_spend_micros ?? "no limit");
  console.log("tokens left:", quota.remaining_tokens ?? "no limit");
  console.log("period ends:", quota.period.end_at);
  ```

  ```python Python theme={"system"}
  import os, requests

  res = requests.get(
      "https://api.opentype.dev/v1/quota",
      headers={"Authorization": f"Bearer {os.environ['OPENTYPE_API_KEY']}"},  # needs usage_read
      timeout=30,
  )
  quota = res.json()
  if not res.ok:
      raise RuntimeError(f"{quota['error']['code']} ({quota['error']['request_id']})")
  print("spend left:", quota["remaining_spend_micros"] if quota["remaining_spend_micros"] is not None else "no limit")
  print("tokens left:", quota["remaining_tokens"] if quota["remaining_tokens"] is not None else "no limit")
  print("period ends:", quota["period"]["end_at"])
  ```
</CodeGroup>

```json theme={"system"}
{
  "organization_id": "org_example",
  "period": {"start_at": "2026-09-01T00:00:00Z", "end_at": "2026-10-01T00:00:00Z"},
  "limits": {
    "period_spend_limit_micros": 2000000,
    "period_token_limit": null,
    "request_spend_ceiling_micros": 20000
  },
  "consumed_tokens": {"input_tokens": 824, "output_tokens": 46, "total_tokens": 870},
  "consumed_spend": {"reserved_micros": 20038, "settled_micros": 38, "unsettled_micros": 20000},
  "remaining_spend_micros": 1979962,
  "remaining_tokens": null
}
```

A quota refusal names the numbers it compared:

```json theme={"system"}
{"error":{"code":"organization_spend_quota_exhausted","message":"the estimated provider spend of 20000 micro-USD exceeds the 1200 micro-USD remaining in this quota period","request_id":"req_7d3f0c1a9b2e4f6a8c0d1e2f3a4b5c6d"}}
```

See [Spend limits and quotas](/guides/spend-limits-and-quotas).

## When the model service is busy

If the model service behind a run limits OpenType's traffic, the run fails with `503 provider_rate_limited`, not `429`. That limit is not on your organization. Retry with exponential backoff and a new `Idempotency-Key`.

## Related

* [Errors](/reference/errors) - what each refusal above means and whether to retry.
* [Spend limits and quotas](/guides/spend-limits-and-quotas) - plan around period quotas.
* [Models and pricing](/getting-started/models-and-pricing) - what Neon 1.1 costs per token.
* [Decision questions](/getting-started/decision-questions) - design a question set inside the bounds.
* [Model Router](/guides/model-router) - selection requests share the 4 MiB body cap.
