Status codes
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.Error bodies
The common shape:detail field when there is something actionable to say.
Common errors
401 — "a secret key (sk_*) is required"
401 — "a secret key (sk_*) is required"
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.401 — "invalid_or_missing_secret_key"
401 — "invalid_or_missing_secret_key"
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.400 — "external_user_id is required"
400 — "external_user_id is required"
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.500 — "could not store user"
500 — "could not store user"
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.
404 on an artifact URL
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.The widget loads but nothing happens
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 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.
Subdomains do not inherit from the apex domain.
MCP errors
MCP uses JSON-RPC error codes inside200 responses, as clients expect, with
two exceptions.
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 for the full breakdown.