Idempotency and errors
Error format
Section titled “Error format”All API errors return JSON. The shape is:
{ "message": "Human-readable description of what went wrong" }Validation and business-rule failures may include an error code and a
details array. The full schema lives in the ApiError model in the
reference.
Idempotency and retries
Section titled “Idempotency and retries”Selected write endpoints accept an Idempotency-Key request header so that a
retry after a network failure does not create a duplicate. It is currently
enabled on payment and invoice write endpoints; other POST and PUT endpoints do
not yet honour the key.
How it works:
- Send a unique
Idempotency-Key(for example a UUID) with the request. - The key is stored together with a fingerprint of the request (HTTP method, path, and JSON body) for 24 hours.
- Replaying the same key with the same request returns the original stored
response and sets
Idempotent-Replayed: true, without re-running the operation. - Reusing the same key with a different body returns
409 Conflict.
Recommended pattern:
- Generate the key before the call and keep it for any retry.
- On a transport error, retry with the same key.
- For endpoints that do not support the key, query the resource by your own reference before retrying, to avoid duplicates.
Status codes
Section titled “Status codes”| Code | Meaning |
|---|---|
| 200 | Success with body. |
| 204 | Success, no body. |
| 400 | Validation error or business rule violation. Body explains. |
| 401 | Authentication failed. See Authentication. |
| 403 | Authenticated but lacks the required right. |
| 404 | Resource not found, or hidden from this principal. |
| 413 | Request body exceeded the size limit. |
| 500 | Server error. Safe to retry after backoff. |
| 504 | Query timeout. Paginate or filter more aggressively. |