Response shape
Every error response carries the same body shape:code defaults to a status-class value (bad_request, unauthorized, forbidden, not_found, conflict, payload_too_large, unprocessable_entity, rate_limited, internal_error, service_unavailable, …) derived from the HTTP status. A number of endpoints enrich it with a more specific code for a particular failure (e.g. auth_required, invalid_hash_proof) — see the per-status sections below for the ones worth branching on. 5xx responses additionally carry request_id inside error for support correlation.
REST calls to api.mnemom.ai also always carry an X-Request-Id response header (success or error) — paste it into a support ticket to pull the server-side logs for that request. This is distinct from X-Mnemom-Request-Id, which only appears on gateway-routed (LLM-proxy) responses — see Headers for the split. On gateway-routed responses, X-Mnemom-Verdict is also always present (see headers) — even on a 4xx, it reflects what Safe House observed before the error fired. Retry-After is present on 429 and maintenance/some 503 responses.
Branch on error.code, not on error.message. Messages are human-facing and may evolve; codes are stable contract.
Status codes at a glance
400 Bad Request
Most 400s carry the defaultbad_request code with a message describing the specific validation failure (missing required field, malformed value, body that isn’t parseable JSON). A few endpoints use a more specific code:
If you see an unfamiliar 400, capture the
X-Request-Id and open a support ticket.
401 / 403 / 404 — auth and ownership
Agent containment (403). A
paused or killed agent gets every gateway-routed request rejected with a distinct code:
details.reason is agent_paused or agent_killed. Checked before any billing evaluation, so a contained agent always sees 403, never 402. See Agent containment for the containment API and lifecycle.
402 Payment Required — billing and depletion
Gateway-routed requests (gateway.mnemom.ai) can be rejected for two distinct billing reasons, both under the billing_error code, distinguished by details.reason:
balance_depleted. Add a payment method / top up µ, then retry; this is not a transient condition, so retrying immediately without resolving billing will keep failing. See Pricing for how µ balances and auto top-up work.
422 — semantically rejected
422 covers a request that was well-formed and authorized but rejected on its content — e.g. an out-of-bounds index on a Merkle-proof lookup, or a value that fails a downstream validation rule specific to that endpoint. The response body’s details (when present) carries the specifics; there is no single named code shared across every 422 — check the endpoint’s own reference page.
Safe House content interventions do not go through this status — see Safe House interventions below.
429 — rate limits
429 responses always carry a Retry-After header. The value is seconds (integer per RFC 9110 §10.2.3):
Idempotency-Key header — if the request actually went through and the API is reporting back the 429 (rare but possible mid-failure), the second attempt is idempotent on key match.
5xx / 529 — server-side, maintenance, and saturation
The 503/529 distinction on gateway-routed calls matters for your fallback strategy: 503 means the gateway is fine but the LLM provider isn’t; 529 means the gateway itself is shedding load. A client that has a backup provider should switch on 503 but not on 529.
Safe House interventions are not error responses
The Safe House front door screens every inbound surface a gateway-routed request carries — the inbound message, and each tool result being handed back to the model — and emits a verdict (pass | observed | nudged | enforced) per X-Mnemom-Verdict. In enforce mode, an offending inbound message or tool result is replaced in place with a quarantine notice (or redacted, on the back door) and the — possibly modified — request still proceeds to the upstream LLM provider:
This holds for the inbound message itself, not only for tool results — front-door enforcement never turns your chat/completion call into a 4xx. Do not read a 200 as “no front-door action this turn”: read
X-Mnemom-Verdict, not the status code, to know whether an intervention happened.
The X-Mnemom-Verdict response header reflects the full per-checkpoint state even on error responses that arise for unrelated reasons (e.g. a 401) — useful for distinguishing “front-door intervention” (front=enforced) from “agent’s own integrity intervention” (integrity=enforced).
A quarantined message is also logged for asynchronous review: fetch it via GET /v1/safe-house/quarantine/{quarantine_id} or, with operator role, release it via POST /v1/safe-house/quarantine/{quarantine_id}/release. This is a separate, async surface from the synchronous same-turn replacement above.
integrity=unverified does not get its own status code. Unlike the Safe House front/back door, the integrity checkpoint has a fifth value, unverified — the analyzer timed out, errored, or the circuit breaker was open, so no trustworthy verdict was produced. This is never reported as pass. In integrity_mode: enforce, the response is withheld and replaced same-turn (fail-closed), the same way an enforced intervention is — still a 2xx, not a dedicated 4xx/5xx, since the intervention is delivered as the response body rather than as an error. In observe/nudge, the response is forwarded unmodified and the unverified state is recorded for post-hoc review. See X-Mnemom-Verdict for the full semantics.Retry semantics summary
Idempotency-Key semantics + the Idempotent-Replay: true response echo are documented in the Headers reference.
See also
- Headers — request-id, verdict structure, retry headers.
- Safe House — the four-mode protection contract and three-layer detection model.
- API Versioning Policy — what we will (and won’t) change about the error surface across versions.
- API Overview — base URL, auth, rate-limit headers.