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

# Errors

Every error response shares one envelope:

```json
{
  "error": "forbidden",
  "message": "You do not have permission to perform this action.",
  "request_id": "8f9e4c2b-0c1a-4f3e-9a8d-1b2c3d4e5f60",
  "docs_url": "https://docs.lucanto.eu/api/v1/errors/forbidden"
}
```

* **`error`** — a stable, machine-readable code. Branch on this, not the message.
* **`message`** — human-readable; wording may change between releases.
* **`request_id`** — also returned as the `X-Request-Id` header. Quote it in
  support tickets so we can pull the matching server log line.
* **`docs_url`** — deep link to the per-code documentation page.

Validation failures add an `errors` array of individual messages.

## Status codes

| Status | `error`                                                             | Meaning                                             |
| ------ | ------------------------------------------------------------------- | --------------------------------------------------- |
| 400    | `bad_request`                                                       | Malformed request                                   |
| 401    | `unauthenticated`                                                   | Missing or invalid token                            |
| 402    | `subscription_required`                                             | Workspace has no active subscription                |
| 403    | `forbidden`                                                         | Token scope or role doesn't permit this action      |
| 404    | `not_found`                                                         | Resource doesn't exist or isn't visible to you      |
| 409    | `conflict` / `idempotency_key_conflict` / `idempotency_in_progress` | Conflicting state (see [Idempotency](/idempotency)) |
| 422    | `unprocessable_entity`                                              | Validation failed (see `errors` array)              |
| 429    | `rate_limited` / `feature_limit_exceeded`                           | Throttled or plan limit reached                     |

Cross-workspace access returns `404`, not `403`, so the API never leaks the
existence of records you can't see.