Error codes
Every response uses a uniform envelope, so clients key on success rather than branching on HTTP
status alone:
{ "success": false, "data": null, "error": { "code": "DISCUSSION_LOCKED", "message": "…" }, "meta": null }
Successful responses carry success: true and the payload in data (with pagination in meta).
Codes to handle
| Status | Code | Meaning & action |
|---|---|---|
| 400 | BAD_REQUEST | Malformed input. Fix the request. |
| 400 | VALIDATION_ERROR | The request body or params failed schema validation — the most common integration error. The message names the offending field. |
| 401 | UNAUTHORIZED | Missing/invalid API key, or an identity proof that was missing or failed to verify. See Identity signing → debug. |
| 403 | IDENTITY_VERIFICATION_REQUIRED | Deployed tenant has no identity source configured yet. Mint a secret or add an OIDC issuer. |
| 403 | FORBIDDEN | The key/principal lacks the required capability. |
| 403 | DISCUSSION_LOCKED | Write attempted on a locked discussion. |
| 403 | EDIT_WINDOW_EXPIRED | Comment edit attempted past its edit window. |
| 404 | NOT_FOUND | No such resource — expected when reading a discussion before its first comment. |
| 409 | CONFLICT | Uniqueness violation (e.g. duplicate report); IDEMPOTENCY_IN_PROGRESS for an in-flight retry. |
| 422 | UNPROCESSABLE_ENTITY | Syntactically valid but violates a business rule (e.g. reply past max depth); also idempotency-key body mismatch. |
| 429 | RATE_LIMITED | Rate limited — honour the Retry-After header. |
| 503 | IDENTITY_PROVIDER_UNAVAILABLE | (OIDC tenants) Your identity provider's keys were unreachable with a cold cache. Transient — retry. |
| 5xx | INTERNAL_ERROR / SERVICE_UNAVAILABLE | Transient — retry with backoff. |
Why 401 vs 403 IDENTITY_VERIFICATION_REQUIRED are split
They answer different questions: 403 IDENTITY_VERIFICATION_REQUIRED means "this tenant isn't
configured for verified identity yet" (mint the secret / add an issuer), while 401 means "the
tenant is configured, but your proof was missing or didn't verify" (attach the headers, or fix
your signing). Branch on the code, not the message — messages may
change, but codes are part of the versioning contract.