Alloovium

Core Concepts

Errors

Every 4xx / 5xx response from the public API follows RFC 7807 — a single stable envelope with a machine-readable code you can branch on.

Envelope

All error bodies look like this:

json
{ "type": "https://api.alloovium.com/errors/insufficient_scope", "title": "Insufficient scope", "status": 403, "detail": "API key is missing required scope: vault:write", "instance": "/api/v2/vault/projects", "code": "insufficient_scope", "request_id": "req_01HQZ4R9VYTC5H6NPRDFG8EJUS" }
FieldAlways presentDescription
typeyesURI identifying the error category. Based on the code.
titleyesShort human-readable summary. May be translated in the future.
statusyesHTTP status code, duplicated for clients that only parse the body.
detailyesLonger description with specifics. Safe to log; never contains stack traces.
instancenoRequest path that produced the error.
codeyesStable machine-readable identifier. Branch your code on this.
request_idyes (5xx)Attach to support tickets for end-to-end trace.

Branch on code, not title

The Branch on code, not title and detail fields are human-readable and may change. The code field is covered by our stability contract and will never silently rename.

Error code reference

401 — authentication

CodeMeaning
missing_api_keyNo Authorization header, or not Bearer scheme
invalid_api_keyKey does not match any active credential
invalid_tokenOAuth Bearer JWT is malformed, expired, or signature invalid
api_key_revokedKey was revoked via the dashboard
api_key_expiredKey passed its expiry date
user_inactiveOwning user has been deactivated
tenant_disabledOwning tenant is suspended

402 — billing

CodeMeaning
payment_requiredTenant billing is past due. Resolve in the dashboard.

403 — authorization

CodeMeaning
insufficient_scopeThe credential is valid but doesn't carry the required scope. Response includes a missing_scopes array.
permission_deniedThe user lacks a project- or feature-level permission (e.g. vault:deny_create_project).
oauth_not_supportedThis capability does not accept OAuth tokens. Call it with an API key.
json
{ "type": "https://api.alloovium.com/errors/insufficient_scope", "title": "Insufficient scope", "status": 403, "detail": "API key is missing required scope: vault:write", "code": "insufficient_scope", "missing_scopes": ["vault:write"] }

404 — not found

CodeMeaning
not_foundResource does not exist, or the caller cannot see it. The API deliberately does not distinguish these two cases so attackers cannot probe cross-tenant IDs.

409 — conflict

CodeMeaning
idempotency_key_reusedSame Idempotency-Key was seen with a different request body in the 24-hour window.
idempotency_in_progressEarlier request with this key is still executing. Retry in a moment.

413 / 400 — uploads

CodeMeaning
file_too_largeUploaded file exceeds the maximum allowed size.
unsupported_file_typeFile extension is not in the supported set (pdf, docx, xlsx, pptx, images, etc.).
invalid_document_idA referenced document_id could not be resolved.

422 — validation

CodeMeaning
validation_errorRequest payload failed validation. Body includes a field_errors array listing offending fields.
invalid_cursorPagination cursor was malformed, truncated, or tampered with.
invalid_idempotency_keyIdempotency-Key header did not match the allowed pattern (1-255 chars, A-Z a-z 0-9 . _ -).

429 — rate limit

CodeMeaning
rate_limitedToken bucket exhausted. Body includes retry_after_seconds. See the Rate Limits page for the full retry strategy.

5xx — server

CodeMeaning
internal_errorUnexpected server error. Retry with exponential backoff and attach request_id to any support ticket.
not_implementedEndpoint was removed or is not yet implemented in your environment.

Request IDs

Every response — error or success — carries an header header. On 5xx, the same ID is also embedded in the body. Include it when contacting support:

text
X-Request-Id: req_01HQZ4R9VYTC5H6NPRDFG8EJUS

Support can trace the request through every layer — load balancer, FastAPI handler, database queries, downstream LLM calls — using just that ID.

Pydantic validation errors (422)

When FastAPI's Pydantic validator rejects a request body before it reaches a handler, the same envelope carries a field list mapping to the failing field paths:

json
{ "type": "https://api.alloovium.com/errors/validation_error", "title": "Request validation failed", "status": 422, "detail": "1 field failed validation", "code": "validation_error", "field_errors": [ {"loc": ["body", "name"], "msg": "Field required", "type": "missing"} ] }

Handling errors in code

python
import httpx class AllooviumError(Exception): def __init__(self, payload): self.code = payload.get("code") self.status = payload.get("status") self.detail = payload.get("detail") self.request_id = payload.get("request_id") super().__init__(f"{self.code}: {self.detail}") def raise_for_problem(resp: httpx.Response): if resp.is_success: return try: payload = resp.json() except Exception: resp.raise_for_status() return raise AllooviumError(payload) try: resp = httpx.get(url, headers=headers) raise_for_problem(resp) except AllooviumError as e: if e.code == "insufficient_scope": prompt_user_to_grant_scope() elif e.code == "rate_limited": sleep_and_retry() else: log.error("Alloovium call failed", code=e.code, request_id=e.request_id) raise

See also

  • Rate Limits — full retry strategy for 429 and 5xx.
  • Idempotency — how to keep retries from creating duplicates.