Errors and status codes¶
All Xref API responses use a consistent JSON envelope for both successful and error responses.
Response envelope¶
| Field | Type | Description |
|---|---|---|
data |
object | array | null | The successful payload. null on error responses. |
status_message |
string | Coarse-grained status: informational, ok, redirect, client_error, or server_error. |
message |
string | Human-readable detail. Empty on success; populated for errors. |
The HTTP status code and the status_message are always consistent — for
example, an HTTP 404 always carries status_message: "client_error". Use
the HTTP status code as your primary signal and the message for diagnostics
or surfacing to humans.
Cache headers (Cache-Control: no-store, Pragma: no-cache,
Expires: 0) are set on every response.
Status code matrix¶
| Status | status_message |
Meaning | Retry? |
|---|---|---|---|
200 |
ok |
Successful read. | — |
201 |
ok |
Successful create (POST /v1/requests). |
— |
202 |
ok |
Reserved. Not currently emitted. | — |
400 |
client_error |
Validation failure — missing/invalid field, bad JSON, unsupported query value, package not ACTIVE, schema mismatch. |
Fix the body, then retry. |
401 |
client_error |
Missing or invalid X-Xref-API-Key / X-Xref-User-Email headers, or invalid / expired ?t= report token. |
Fix the headers or re-query for a fresh token, then retry. |
403 |
client_error |
User email is not a permitted member of the API key's organisation, or the organisation has no credits remaining, trial has expired, or subscription is inactive. | Check user membership and organisation plan/credits, then retry. |
404 |
client_error |
Package or request not found, or not visible to the caller's organisation / tier. | Don't retry — the resource doesn't exist for this caller. |
422 |
client_error |
Reserved. v1 emits 400 for all validation failures. Future versions may use 422 to distinguish semantic from syntactic validation. |
Fix the body, then retry. |
429 |
client_error |
Per-API-key throttle exceeded. Retry-After header included. |
Wait Retry-After seconds, then retry. |
5xx |
server_error |
Internal error; the request log carries a trace id. | Retry with backoff. Treat the outcome as unknown for POST /v1/requests. |
Examples¶
200 OK — success¶
201 Created — request accepted¶
{
"data": {
"request_id": "9b2a14ee-9d0e-4d3a-aff2-7f68c19f3f3a",
"status": "RECEIVED"
},
"status_message": "ok",
"message": ""
}
400 Bad Request — validation failure¶
{
"data": null,
"status_message": "client_error",
"message": "recipient.email: enter a valid email address"
}
401 Unauthorized — missing or invalid API key¶
{
"data": null,
"status_message": "client_error",
"message": "Missing X-Xref-Api-Key or X-Xref-User-Email"
}
403 Forbidden — user not permitted or plan exhausted¶
{
"data": null,
"status_message": "client_error",
"message": "User is not a member of the organisation"
}
{
"data": null,
"status_message": "client_error",
"message": "Organisation has no credits remaining"
}
{
"data": null,
"status_message": "client_error",
"message": "Organisation subscription is not active"
}
404 Not Found — package or request not visible¶
429 Too Many Requests — throttled¶
Headers:
Body:
The Retry-After value is the number of seconds remaining in the breached
window (per-minute or per-hour, whichever was hit first).
5xx Server Error — internal error¶
A 5xx response indicates that the server was unable to process the request.
GET requests can be retried. For
POST /v1/requests, see
Idempotency and retries
before retrying.