> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.cloudraker.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.cloudraker.com/_mcp/server.

# Errors

Errors come back as JSON with a `snake_case` code and a matching HTTP status:

```json
{ "error": "invalid_status" }
```

Some errors carry extra detail alongside the code (for example a list of offending field keys). Always branch on the HTTP status first, then on the `error` code.

## Status codes

| Status | Meaning                                                                                                                  |
| ------ | ------------------------------------------------------------------------------------------------------------------------ |
| `401`  | Unauthenticated — missing, malformed, or invalid token                                                                   |
| `403`  | Authenticated but lacks a **write** permission, or not an admin                                                          |
| `404`  | Not found — **also used as a leak-guard** for a missing `space:read` grant (hides existence rather than returning `403`) |
| `409`  | State conflict (for example, reprocessing a non-failed file, or deleting a definition that still has objects)            |
| `410`  | Expired but still within a grace window (see the [Process API](/developers/process-api))                                 |
| `413`  | Payload too large (relayed from file storage)                                                                            |
| `422`  | Invalid body — an unknown or archived field, or a `$`-injection attempt                                                  |
| `429`  | Too many requests — the organization's [rate limit](/developers/rate-limits) is exhausted; wait for `Retry-After`        |
| `503`  | A downstream dependency is unavailable, or auth validation hit a transient auth-service outage                           |

The `404`-as-leak-guard convention matters: a `404` on a space-scoped resource can mean "doesn't exist" **or** "you can't see it." The API deliberately doesn't distinguish the two, so you can't probe for the existence of resources you lack access to.

## Common error codes

| Code                | Typical status | Meaning                                                                            |
| ------------------- | -------------- | ---------------------------------------------------------------------------------- |
| `unauthorized`      | 401            | Missing or malformed `Authorization` header                                        |
| `invalid_token`     | 401            | Token failed validation                                                            |
| `auth_unavailable`  | 503            | Transient auth-service outage during key validation — retry; **not** a revoked key |
| `org not found`     | 404            | Token has no associated organization                                               |
| `invalid_request`   | 400            | Malformed request (for example, combining `view` with `filter`/`sort`)             |
| `invalid_status`    | 400            | Unknown `status` value in a query filter                                           |
| `view_not_found`    | 404            | Unknown or wrong-scope saved view                                                  |
| `objects_exist`     | 409            | Deleting an object definition that still has live objects                          |
| `payload_too_large` | 413            | Body exceeded the size limit                                                       |
| `not_found`         | 404            | Unknown id (or hard-wiped resource)                                                |
| `expired`           | 410            | Purged resource, still in its grace window                                         |
| `upstream_error`    | 5xx            | A downstream worker returned an error                                              |

## Errors on capability endpoints

The [capability endpoints](/capabilities/extract) (`/v1/…`) use a richer envelope. The legacy `{ "error": … }` shape above is unchanged on every other route.

```json
{
  "code": "invalid_request",
  "message": "file: provide exactly one of `file` or `files`",
  "retryable": false,
  "requestId": "req_01KYCZWG1M7V8HM95NBV63PET2",
  "docUrl": "https://docs.cloudraker.com/developers/errors#invalid_request"
}
```

| Field       | What it is                                                                                           |
| ----------- | ---------------------------------------------------------------------------------------------------- |
| `code`      | Stable machine-readable code — branch on this.                                                       |
| `message`   | Human-readable, and where a field is at fault it is prefixed with that field's path. Never parse it. |
| `retryable` | Whether repeating the identical request could succeed.                                               |
| `requestId` | Also returned as the `x-request-id` response header. Quote it in support requests.                   |
| `docUrl`    | Present when a specific rule was broken — links to the rule.                                         |

### invalid\_request

`400`. The body or query is malformed: a missing field, a bad type, or a mutually exclusive pair sent together (`file` **and** `files`, `schema` **and** `action`, `spaceId` **and** `space` on [keep](/developers/runs#keep-a-run)). It also covers a parameter that doesn't apply to the input — `style` on a PDF, `mode` on audio — and a saved [sign action](/capabilities/sign) passed as another verb's `action`. `message` names the offending field. Fix the call; retrying identically will fail identically.

A slow run is never an error. When the synchronous cap is reached the call returns `202` with the run handle, and a run waiting on a human returns `202` with `needs_input` — both are successes with a body to poll.

### invalid\_schema

`400`. The `schema` you sent to extract breaks the [extraction schema dialect](/capabilities/extract/schema). `docUrl` points at the exact rule and `message` at the exact node.

### not\_found

`404`. No such run, file, template, action, webhook endpoint, or produced output. Also returned when a sub-route addresses a step the run doesn't have — `GET /v1/runs/plr_…/envelope` on a pipeline with no `sign` step. Right after a synchronous run returns, `GET /v1/runs/:id/output/:name` can `404` for a moment while the produced file is registered; re-fetch the run and use `output.file.url`.

### Other capability codes

| Code                             | Status | Meaning                                                                                                                                                                             |
| -------------------------------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `unauthorized` / `invalid_token` | 401    | Missing, malformed, or invalid bearer token.                                                                                                                                        |
| `rate_limited`                   | 429    | The organization's [rate limit](/developers/rate-limits) is exhausted. Nothing was started; wait for the `Retry-After` seconds and retry.                                           |
| `run_expired`                    | 410    | The run passed its `ttl` and was purged. Terminal; the result is gone. After the grace window this becomes `404`.                                                                   |
| `upstream_error`                 | 4xx    | Fallback code when a downstream stage rejects the request and has no more specific code. Fix the call; `retryable` is `false`.                                                      |
| `action_unknown`                 | 4xx    | The `action` you referenced doesn't exist in your organization, by id or by slug.                                                                                                   |
| `file_ineligible`                | 4xx    | The document couldn't be used as an input — wrong type, or it never finished parsing.                                                                                               |
| `file_not_ready`                 | 409    | The file exists but hasn't finished uploading or parsing yet. Poll `GET /v1/files/:id` until `ready`.                                                                               |
| `output_not_ready`               | 409    | A run's output file is registered but its bytes are still settling. Retryable — wait a moment and re-request `output.file.url` or `/v1/runs/:id/output/:name`. It is never a `404`. |
| `file_fetch_failed`              | 422    | The `url` you sent couldn't be fetched at registration time — unreachable host, non-2xx response, or an empty body.                                                                 |
| `file_unreadable`                | 502    | The source was reached but its bytes couldn't be read.                                                                                                                              |
| `file_upload_failed`             | 502    | The fetched bytes couldn't be stored. Most often the source served no `Content-Length` — see [Files](/developers/files#register-by-url).                                            |
| `already_kept`                   | 409    | The run was already kept into a different space. A run belongs to one space.                                                                                                        |
| `pipeline_running`               | 409    | You tried to keep a run that hasn't finished. Wait for a terminal status.                                                                                                           |
| `webhook_endpoint_not_found`     | 422    | `webhook: {id}` references an endpoint that doesn't exist.                                                                                                                          |
| `webhook_endpoint_disabled`      | 422    | The referenced endpoint is paused. Re-enable it with `PATCH /v1/webhooks/:id`, or send `webhook: {url}`.                                                                            |
| `ambiguous_capability`           | 4xx    | A saved `redact` action didn't say whether it targets documents or audio. Send `mimeType` when creating it.                                                                         |
| `run_too_large`                  | 4xx    | The request exceeds the dispatch size budget. Send fewer files, or a smaller schema.                                                                                                |
| `schema_too_large`               | 4xx    | The inline `schema` is over the 64 KB limit. See [size limit](/capabilities/extract/schema#size-limit).                                                                             |
| `internal_error`                 | 5xx    | Something failed on our side. `retryable` is `true` — back off and retry.                                                                                                           |

New codes can be added over time; branch on the ones you handle and treat anything unknown as a plain failure of its HTTP status class.

## Retrying

* **`503 auth_unavailable`** and **`503`** downstream errors are transient — retry with exponential backoff.
* **`410 expired`** is terminal for that resource; don't retry.
* **`429 rate_limited`** is transient too, but retry on the terms the response gives you: sleep for the `Retry-After` seconds, then back off exponentially. The budget and the tactics are on [Rate limits](/developers/rate-limits).
* **`4xx`** other than `429` means a bad request — fix the call rather than retrying.

## Where to go next

#### [Runs](/developers/runs)

Statuses, expiry, and what a `410 run_expired` means for your result.

#### [Rate limits](/developers/rate-limits)

The per-organization budget, the `429` envelope, and how to back off.

#### [Pagination and filtering](/developers/pagination-filtering)

How listing and querying work across the API.