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

# Errors

> Status codes and error bodies across the API, MCP and artifact surfaces.

## Status codes

| Code  | Meaning                                                                |
| ----- | ---------------------------------------------------------------------- |
| `200` | Success.                                                               |
| `202` | Accepted with no body. MCP, when a batch contained only notifications. |
| `400` | Malformed body, or a missing required field.                           |
| `401` | No key, the wrong kind of key, or an invalid grant token.              |
| `404` | No such resource — or an entitlement failure on the artifact endpoint. |
| `429` | Rate limited. Carries a `retry-after` header.                          |
| `500` | The operation failed server-side.                                      |
| `503` | The platform is not configured.                                        |

<Note>
  `503` and `401` are kept distinct deliberately. `503` means **Peeve** is
  misconfigured — there is no database to check keys against. `401` means **your
  request** is. Collapsing them turns a five-minute setup problem into an
  afternoon of debugging the wrong thing.
</Note>

## Error bodies

The common shape:

```json theme={null}
{ "error": "a secret key (sk_*) is required" }
```

Some endpoints add a `detail` field when there is something actionable to say.

## Common errors

<AccordionGroup>
  <Accordion title="401 — &#x22;a secret key (sk_*) is required&#x22;">
    You sent a publishable key to `/v1/users`. That endpoint accepts secret keys
    only, and sends no CORS headers — it is not callable from a browser. Move
    the call to your backend.
  </Accordion>

  <Accordion title="401 — &#x22;invalid_or_missing_secret_key&#x22;">
    From `/api/killswitch`. No key was sent, or it was not a valid secret key.

    Also check the key has not been revoked. Allow up to 20 seconds for a
    revocation to propagate — key lookups are cached for that long.
  </Accordion>

  <Accordion title="400 — &#x22;external_user_id is required&#x22;">
    `POST /v1/users` needs a stable id for the user. It is the identity key that
    ties a record to its history, so it cannot be blank.
  </Accordion>

  <Accordion title="500 — &#x22;could not store user&#x22;">
    The upsert failed. Peeve logs the failure *shape* only — never the payload —
    because database errors can echo the offending row, which for that table
    means ciphertext at best and personal data at worst. Retry; if it persists,
    contact support with the timestamp.
  </Accordion>

  <Accordion title="404 on an artifact URL">
    Either the artifact name is not one of the four, the key in the path is not
    a valid publishable key, or the workspace is not entitled — a plan below
    Growth, a disabled agent channel, or the kill switch on. The entitlement
    case returns `404` with
    `Agent access is not enabled for this workspace.`
  </Accordion>

  <Accordion title="The widget loads but nothing happens">
    Not an API error, but the most common report. In order:

    **The workspace is not entitled to serve** — kill switch on, trial expired,
    or subscription lapsed. The widget is told not to mount at all. Check
    [the kill switch](/authentication/keys#the-kill-switch) and your
    subscription.

    **The workspace has not been mapped yet** — the widget stays hidden for end
    users until a production map exists, so a real visitor never meets an
    unmapped cursor. Run the baseline capture from the dashboard.

    **The origin does not match** — see [Origins](/authentication/origins).
    Subdomains do not inherit from the apex domain.
  </Accordion>
</AccordionGroup>

## MCP errors

MCP uses JSON-RPC error codes inside `200` responses, as clients expect, with
two exceptions.

| Code     | HTTP      | Meaning                                                |
| -------- | --------- | ------------------------------------------------------ |
| `-32700` | 200       | Parse error                                            |
| `-32600` | 200       | Invalid request: missing method                        |
| `-32601` | 200       | Method not found                                       |
| `-32602` | 200       | Invalid params — unknown or missing tool name          |
| `-32001` | 200 / 503 | Agent channel not available, or an invalid grant token |
| `-32002` | **429**   | Rate limited                                           |

Rate limiting is a real `429` so clients back off. A platform failure is a real
`503`. Everything else stays `200`.

See [the MCP section](/mcp/overview) for the full breakdown.
