Errors you can program against
Every error is RFC 9457 problem+json: an HTTP status, a stable machine code to switch on, a human-readable detail, and a request_id you can quote if you write to us. Codes are stable within v1; new ones may be added.
The shape
{
"type": "https://fullhall.au/docs/api/errors#invalid",
"title": "Invalid request",
"status": 422,
"code": "invalid",
"detail": "email: Enter a valid email address.",
"request_id": "0b7c9e2a-…",
"errors": [{ "field": "email", "message": "Enter a valid email address." }]
}The errors array appears on 422s only. Switch on code, show detail to a human, log request_id.
Every code
| Code | Status | Meaning |
|---|---|---|
| unauthorized | 401 | Missing, malformed, revoked, or expired API key. |
| forbidden | 403 | The key works but lacks the scope this endpoint needs. |
| not_found | 404 | No such resource in your organisation. Other organisations' ids read the same way. |
| conflict | 409 | The write clashes with existing data: a duplicate email or name, not enough storage, or a contact on the membership register. |
| invalid | 422 | Validation failed. The errors array lists each field and what's wrong with it. |
| rate_limited | 429 | Too many requests from this key right now. Wait Retry-After seconds. |
| quota_exceeded | 429 | Your organisation used today's request quota. The quota block says when it resets. |
| idempotency_in_progress | 409 | Another request with this Idempotency-Key is still running. Retry shortly. |
| idempotency_mismatch | 422 | This Idempotency-Key was already used with a different body. Use a fresh key. |
| bad_request | 400 | Malformed JSON, a forged or foreign cursor, or a bad parameter. |
| unsupported_media_type | 415 | Send request bodies as Content-Type: application/json. |
| payload_too_large | 413 | Request bodies are capped at 1 MB. |
| internal | 500 | Something broke on our side. Retry, and quote the request_id if it keeps happening. |
Retrying
Retry 429s after the Retry-After header, and 500s with backoff. Send an Idempotency-Key on POSTs so a retried create can never run twice; see pagination and limits for the idempotency rules. Don't retry 4xxs other than 429: they'll fail the same way until the request changes.