Every failed request to the public API returns a single, predictable envelope:
| 1 | { |
| 2 | "error": { |
| 3 | "code": "not_found", |
| 4 | "message": "The requested resource was not found.", |
| 5 | "doc_url": "https://webmoment.app/docs/errors#not_found" |
| 6 | } |
| 7 | } |
| 8 | |
error.codeis a short, machine-readable identifier.error.messageis a human-readable string. Safe to display in developer tooling; not localized.error.doc_urlis optional and points back to this site.
Canonical error codes
| Code | HTTP | Meaning |
|---|---|---|
bad_request | 400 | Malformed request. The body or query failed schema validation; message will name the offending field. |
unauthorized | 401 | Missing or invalid bearer token. |
forbidden | 403 | Token lacks the scope required for this endpoint. |
not_found | 404 | Resource does not exist (or is not in this workspace). |
conflict | 409 | The request collides with the current state (e.g. duplicate URL with duplicateAction: "capture_existing"). |
unprocessable_entity | 422 | Zod validation failed. Inspect message to find the field. |
rate_limit_exceeded | 429 | Quota exhausted. Honour the Retry-After header. |
internal_server_error | 500 | Server-side failure. Safe to retry with exponential backoff. |
Recommended handling
- Treat
4xxas terminal. Re-read the docs, fix the request, and retry. Do not retry automatically on 4xx. - Treat
5xxas transient. Retry with exponential backoff (jittered) up to 5 times before surfacing to a human. - Treat
429specially: readRetry-Afterand wait exactly that many seconds before retrying.
Reference
The Error schema is part of the public OpenAPI spec and is
referenced as #/components/schemas/Error.

