Errors
Scenema uses conventional HTTP status codes for every response and a stable JSON error shape when the response carries a body.
Error body shape
{
"error": "<human-readable message>",
"code": "<optional machine-readable code>"
}Some error responses carry additional fields relevant to the specific failure. Rate-limit responses carry retryAfterMs. Plan-gate responses carry an upgrade object with the current and required plan ids. Every additional field is optional; parsers should not fail when they are missing.
Status codes
| Code | Meaning | Retry? |
|---|---|---|
200 | Success. Response body carries the resource. | N/A |
201 | Created. Response body carries the new resource with any server-generated fields. | N/A |
204 | Success, no response body. Used by revoke and disable-toggle. | N/A |
400 | Invalid request: malformed body, missing required field, value out of range. Check the body’s error field for details. | No, fix the request. |
401 | Authentication failed: unknown key, disabled key, expired key, or malformed Authorization header. | No, provide a valid key. |
403 | Authenticated but not authorized: missing entitlement for the requested feature or plan-gate refusal. Body carries upgrade context. | No, upgrade or use a different endpoint. |
404 | Resource not found or not visible to the caller. Scoping intentionally does not distinguish the two so a caller cannot enumerate resources they do not own. | No. |
409 | Conflict: idempotency violation or state precondition failed. | Occasionally, after correcting state. |
422 | Semantic validation failure: request parsed but the values are logically inconsistent. | No, fix the request. |
428 | Precondition required: caller must complete an onboarding step (signup survey, plan pick) before the request is accepted. | After completing the step. |
429 | Rate limit exceeded. Body carries retryAfterMs; header carries Retry-After. | Yes, honor Retry-After. |
500 | Server error. Something failed on Scenema’s side. | Yes, with exponential backoff. |
502 503 504 | Upstream failure or maintenance. | Yes, with exponential backoff. |
Common code values
Where a body ships with code, it is drawn from a stable enum. The current codes:
RATE_LIMITED. Workspace rate limit reached. Ships with429. See Rate Limits.PLAN_UPGRADE_REQUIRED— feature not on your plan. Ships with403.LIMIT_REACHED— feature on your plan but the per-period quota is spent. Ships with403.PLAN_CAP_TRUNCATED— soft cap: your write succeeded but the payload was clipped to fit your plan. Ships with the standard success code for the endpoint; the body carries the truncation notice so you can prompt the user to upgrade if the full length matters.INSUFFICIENT_CREDITS— workspace credit balance cannot cover the operation. Ships with402. Body carries the full balance and upgrade options.
Idempotency and retries
Read requests are always safe to retry. Mutation requests are idempotent at the resource level:
- Creating the same resource twice yields two distinct rows.
- Revoking or disabling something already gone or already disabled returns the terminal success code (
404or204) without side effects. - Toggling
enabledto the state it already holds is a no-op.
Retry policy that works across every endpoint:
- On
429, honorRetry-After. Do not use your own backoff schedule. - On
5xx, use exponential backoff starting at 500ms with a cap at 30s and a request-level max of five attempts. - On
4xxother than429, do not retry. Fix the request or surface the error to the operator.
Debugging authentication failures
401 is the single most common error to encounter during setup. In order of likelihood:
- Missing
Bearerprefix on the header. The correct form isAuthorization: Bearer sk_.... SendingAuthorization: sk_...returns401. - Wrong header name. Scenema uses
Authorization, notX-API-KeyorApi-Key. - Trailing whitespace or newline on the key. Common when copy-pasting; the extra character makes the hash lookup fail.
- Expired key. Check the row in the Settings tab for the expiry.
- Disabled key. Check the row’s
enabledtoggle. - Revoked key. No row in the list means the key was revoked; mint a new one.
Scenema does not distinguish “unknown key” from “revoked key” from “disabled key” in the error message to avoid leaking whether a specific value has ever existed. If you know the key existed and is now failing, check the Settings tab first.