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

# Errors & Rate Limits

> The error response format and common error codes by status — plus per-plan rate limits, 429 handling, retry-after, and x-ratelimit headers

The Reinx API uses conventional HTTP status codes and a flat, machine-readable error body.

## Error format

Every API error returns a stable code plus a human-readable message:

```json theme={null}
{ "error": "RATE_LIMITED", "message": "Too many requests.", "retry_after_seconds": 12 }
```

Some errors add route-specific **scalar** fields (like `retry_after_seconds` above) — there is never a nested details object. Branch on the `error` code, not the message text; messages can change.

**Casing convention:** routes authenticated with a session or organization key return `UPPER_SNAKE` codes (`UNAUTHORIZED`, `PLAN_LIMIT_REACHED`). Routes authenticated with an **agent API key** return `lower_snake` codes (`unauthorized`, `agent_disabled`, `scope_denied`).

<Note>
  Request **validation** failures are the one exception to the shape above — they return Fastify's standard `400` body, where the machine code lives in `code`:

  ```json theme={null}
  { "statusCode": 400, "code": "FST_ERR_VALIDATION", "error": "Bad Request", "message": "body/name must NOT have fewer than 1 characters" }
  ```
</Note>

## Common error codes

| Status | Code                                                    | Meaning                                                                                                                                     |
| ------ | ------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| 400    | `FST_ERR_VALIDATION`                                    | Request body/query failed schema validation (see note above)                                                                                |
| 400    | `BAD_CURSOR` / `INVALID_CURSOR`                         | Pagination cursor is malformed or expired — restart from the first page                                                                     |
| 401    | `UNAUTHORIZED`                                          | Missing, invalid, or expired session token                                                                                                  |
| 401    | `unauthorized`                                          | Agent API key is missing, malformed, unknown, or revoked                                                                                    |
| 402    | `INSUFFICIENT_BALANCE`                                  | Not enough treasury balance for the requested operation                                                                                     |
| 403    | `NO_ORG_SELECTED`                                       | Session has no active organization                                                                                                          |
| 403    | `INSUFFICIENT_ROLE` / `OWNER_REQUIRED` / `OUT_OF_SCOPE` | Your role or project/team scope doesn't permit this action                                                                                  |
| 403    | `STEP_UP_REQUIRED`                                      | Sensitive action needs fresh re-verification (passkey/TOTP); re-verify and retry with a fresh token                                         |
| 403    | `KYC_REQUIRED`                                          | Financial operations are locked until verification completes (`kyb_status` field included)                                                  |
| 403    | `PLAN_LIMIT_REACHED`                                    | Plan capacity hit — includes `resource`, `limit`, `current`, `plan_tier`, `upgrade_url`                                                     |
| 403    | `FEATURE_NOT_AVAILABLE`                                 | Feature not on your plan — includes `feature`, `required_tier`, `upgrade_url`                                                               |
| 403    | `agent_disabled`                                        | The agent is paused or archived — its key still authenticates, but actions are blocked                                                      |
| 403    | `scope_denied`                                          | The agent key lacks the required tool scope — includes `required_scope`                                                                     |
| 404    | `ORG_NOT_FOUND` (and similar)                           | The referenced resource doesn't exist or isn't visible to you                                                                               |
| 409    | `IDEMPOTENCY_CONFLICT` / `IDEMPOTENCY_KEY_REUSE`        | An idempotency key was reused with a **different** payload — mint a new key for a new logical request                                       |
| 409    | `REQUEST_IN_PROGRESS`                                   | The same idempotent request is still executing — wait and re-poll rather than resubmitting                                                  |
| 409    | `AGENT_ARCHIVED`                                        | The target agent is archived (terminal state)                                                                                               |
| 429    | `RATE_LIMITED`                                          | Too many requests — includes `retry_after_seconds` and a `retry-after` header                                                               |
| 500    | `INTERNAL`                                              | Something failed on our side — the message is generic by design; retry with backoff, and [contact support](/support/contact) if it persists |

## Rate limits

Limits are applied **per organization** and scale with plan tier:

| Plan       | REST API      | MCP tools     |
| ---------- | ------------- | ------------- |
| Free       | 100 req/min   | 60 req/min    |
| Pro        | 1,000 req/min | 600 req/min   |
| Enterprise | 5,000 req/min | 3,000 req/min |

Some sensitive routes carry additional, tighter per-route caps (for example, withdrawals and agent creation), so you can see a `429` on a specific route while well under your org-wide limit.

Every response carries usage headers:

| Header                  | Meaning                                |
| ----------------------- | -------------------------------------- |
| `x-ratelimit-limit`     | Requests allowed in the current window |
| `x-ratelimit-remaining` | Requests left in the window            |
| `x-ratelimit-reset`     | Seconds until the window resets        |

### Handling 429s

* Wait at least `retry_after_seconds` (or the `retry-after` header) before retrying — don't hammer.
* For write requests, retry with the **same idempotency key**: the retry is deduplicated and will never double-spend. See the [payment workflow](/mcp-tools/payment-workflow) for how idempotency keys behave.
* If you're consistently hitting limits at legitimate volume, [contact support](/support/contact) about your plan's limits.
