# Errors Handle Form Plume API errors: one JSON envelope with a stable machine-readable code, a human message, and a field pointer for validation failures. Every error the [Form Plume API](/docs/api) returns uses the same JSON envelope: ```json { "error": { "code": "bad_request", "message": "strictness must be one of low, medium, high", "field": "settings.spam.strictness" } } ``` - `code` is stable and machine-readable. Branch on it, not on the message. - `message` says what to fix in plain English. It may be reworded over time, so log it for humans rather than parsing it. - `field`, when present, points at the offending input with a dotted path into the request body, for example `settings.spam.strictness`. ## Error codes | Status | Code | What it means | | --- | --- | --- | | 400 | `bad_request` | The request body is invalid. For field-level failures, `field` names the input and `message` lists the accepted values. | | 401 | `unauthorized` | The bearer token is missing, malformed, or revoked. | | 403 | `read_only_key` | A read-scope key attempted a write. Use a full-scope [API key](/docs/api/authentication) instead. | | 403 | `session_required` | The endpoint is account-level (billing, membership, key management) and only accepts a dashboard session. | | 404 | `not_found` | The resource does not exist or belongs to another workspace. The API does not distinguish the two. | | 429 | `rate_limited` | You exceeded the per-key request limit. See [rate limits](/docs/api/rate-limits). | Unknown top-level fields in a request body are rejected with a 400, so a typo like `"nmae"` fails loudly instead of being silently ignored. Each page in the [API Reference](/docs/api-reference) lists the statuses that endpoint can return. ## Handling errors in code Codes are stable, so error handling stays short: - Retry on `rate_limited` after the `Retry-After` delay. - Surface `bad_request` with its `field` to whoever built the request. - Treat `unauthorized` as a signal to stop and check the key, not retry. - Log everything else with the full envelope. It is probably a bug. These envelopes cover the Form Plume API only. Errors your visitors see when submitting a form are documented in [Success and errors](/docs/forms/success-and-errors).