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

# Errors

> The v2 error envelope and codes.

Every v2 error returns a stable JSON envelope with a machine-readable `code` —
match on `code`, not on the message (messages may change):

```json theme={null}
{
  "error": {
    "code": "E1012",
    "message": "API key lacks the required scope for this operation",
    "doc_url": "https://docs.usertour.io"
  }
}
```

Validation errors (`E1017`) may additionally carry an `issues` array with one
entry **per problem**, so you can fix every field in a single round-trip
instead of resubmitting once per error:

```json theme={null}
{
  "error": {
    "code": "E1017",
    "message": "steps[0].target: selector is required; steps[1]: unknown step type",
    "issues": [
      { "rule": "schema", "path": "steps[0].target", "message": "selector is required" },
      { "rule": "step_shape", "path": "steps[1]", "message": "unknown step type" }
    ],
    "doc_url": "https://docs.usertour.io"
  }
}
```

Each issue has a `rule` (which validation layer rejected it: `schema`,
`reactive_condition`, `action_not_allowed`, `step_shape`, `reference_target`,
`auto_start`, `media_url`), a `message`, and — when it maps to a request field —
a `path` into the request body.

HTTP status follows the usual conventions: `2xx` success, `4xx` your request,
`5xx` Usertour.

## Codes

| Code    | Status | Meaning                                                                                                                                                                                                                                                                                                   |
| ------- | ------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `E1000` | 403    | Invalid / unknown API token                                                                                                                                                                                                                                                                               |
| `E1010` | 401    | Missing `Authorization` header                                                                                                                                                                                                                                                                            |
| `E1011` | 403    | Token not scoped to the requested project                                                                                                                                                                                                                                                                 |
| `E1012` | 403    | Token lacks the required scope                                                                                                                                                                                                                                                                            |
| `E1019` | 403    | Environment does not belong to the project                                                                                                                                                                                                                                                                |
| `E1029` | 403    | Environment is outside the token's environment allowlist                                                                                                                                                                                                                                                  |
| `E1032` | 403    | Creating an environment needs a token WITHOUT env-targeted capabilities (user/company/session/segment/analytics, content:publish) — those must name environments, and no allowlist can cover an environment that does not exist yet; use a separate project-level-only token                              |
| `E1038` | 403    | Custom CSS requires the Growth plan or above — below that the runtime strips `customCss` at delivery, so the write is refused instead of silently stored (echoing a stored value back, or clearing it, always passes)                                                                                     |
| `E1020` | 401    | API token has expired                                                                                                                                                                                                                                                                                     |
| `E1001` | 404    | User not found                                                                                                                                                                                                                                                                                            |
| `E1002` | 404    | Company not found                                                                                                                                                                                                                                                                                         |
| `E1003` | 404    | Company membership not found                                                                                                                                                                                                                                                                              |
| `E1004` | 404    | Content or content version not found. The message distinguishes two states: a plain "Content not found" means the id never existed here; an "exists but is ARCHIVED (soft-deleted)" message means the content is in the trash — list it with `deleted=true`, restore it with `POST /content/{id}/restore` |
| `E1005` | 404    | Content session not found                                                                                                                                                                                                                                                                                 |
| `E1021` | 404    | Theme not found                                                                                                                                                                                                                                                                                           |
| `E1022` | 404    | Attribute definition not found                                                                                                                                                                                                                                                                            |
| `E1024` | 404    | Event definition not found                                                                                                                                                                                                                                                                                |
| `E1025` | 404    | Segment not found                                                                                                                                                                                                                                                                                         |
| `E1026` | 404    | Environment not found                                                                                                                                                                                                                                                                                     |
| `E1033` | 404    | Unknown API route (no /v2 endpoint matches the path)                                                                                                                                                                                                                                                      |
| `E0003` | 400    | Request is invalid against current domain state                                                                                                                                                                                                                                                           |
| `E1017` | 400    | Request validation failed (bad body / params; may carry `issues`)                                                                                                                                                                                                                                         |
| `E1015` | 400    | Invalid `scope` filter value                                                                                                                                                                                                                                                                              |
| `E0022` | 409    | Cannot delete the last environment                                                                                                                                                                                                                                                                        |
| `E0023` | 409    | Cannot delete the primary environment — set another environment as primary first                                                                                                                                                                                                                          |
| `E0049` | 409    | Version is published (read-only) — fork a draft with the versions endpoint first                                                                                                                                                                                                                          |
| `E0050` | 409    | Version was modified concurrently — re-read and retry                                                                                                                                                                                                                                                     |
| `E1023` | 409    | Resource conflict (e.g. duplicate `codeName`)                                                                                                                                                                                                                                                             |
| `E1028` | 409    | Content is still published — unpublish from every environment before deleting                                                                                                                                                                                                                             |
| `E1030` | 409    | Event definition already has recorded events                                                                                                                                                                                                                                                              |
| `E1037` | 409    | The built-in "all" segment cannot be modified or deleted — create a condition segment for a filtered audience                                                                                                                                                                                             |
| `E1036` | 409    | Predefined attribute/event definitions cannot be modified or deleted — create your own definition instead                                                                                                                                                                                                 |
| `E1034` | 409    | Cannot delete the default theme — set another theme as the project default first                                                                                                                                                                                                                          |
| `E1035` | 409    | System themes cannot be modified or deleted — duplicate one into your own theme (setting one as the project default is allowed)                                                                                                                                                                           |
| `E1031` | 409    | Theme is used by live or draft content — switch that content to another theme first                                                                                                                                                                                                                       |
| `E1027` | 422    | Content version is not publishable (fails render-usability validation)                                                                                                                                                                                                                                    |
| `E1013` | 429    | Rate limit exceeded — on Cloud the limit follows your plan (100/500/1000/3000 requests/min); self-hosted deployments have a flat per-token limit instead (default 1000/min, tunable via [`API_THROTTLE_LIMIT`](/open-source/env)). The standard `Retry-After` header says how long to back off            |

<Note>
  Write endpoints validate the request body against the schema and return `E1017`
  with a message pointing at the offending field — for example, a malformed
  `data` body for a non-flow content type, or a step referencing an unknown value.
  Bodies are validated **strictly**: an unknown top-level key (e.g. `isPrimary`
  copied from a read response) is rejected with `E1017`, never silently dropped.
  A body that is not valid JSON at all is also `E1017` (`Invalid JSON body: ...`).
</Note>

## Pagination cursors never error

An invalid or expired `cursor` does **not** return an error — the request
succeeds with an empty final page:

```json theme={null}
{ "results": [], "next": null, "previous": null }
```

This is deliberate: a cursor the server itself issued can stop matching rows
when the underlying data is deleted mid-pagination, and from the server's side
that is indistinguishable from a mistyped cursor. Treating both as "you have
reached the end" keeps a client that is iterating `next` links from crashing
halfway through a sync. If you loop on `next`, an empty page with `next: null`
is your termination signal — don't probe cursors expecting a 4xx.
