Errors
HTTP status codes Tanqory returns, what the spec says, and how to recover.
The OpenAPI spec declares only a free-text description on 4xx / 5xx
codes — the structured envelope is not yet in the spec. The shape below
is documented from the live gateway, verified against real responses
(June 2026). The spec will be amended to declare it formally in a later
round ([FOUNDER TO CONFIRM]).
The envelope (runtime contract)
Every error response is a single error object. A validation failure —
the richest case — looks like this (verbatim from the gateway):
{
"error": {
"type": "validation_error",
"code": "validation_failed",
"title": "Please check your input",
"message": "Some fields need attention before you can continue.",
"status": 400,
"param": "email",
"errors": [
{ "field": "email", "code": "invalid_type", "message": "Required" },
{ "field": "password", "code": "invalid_type", "message": "Required" }
],
"doc_url": "https://docs.tanqory.com/errors/validation_failed",
"request_id": "e7cab0b72a2507b9953f4d1d3afb092f",
"instance": "/api/v1/auth/register",
"timestamp": "2026-06-09T09:49:35.685Z"
}
}
| Field | Always? | Meaning |
|---|---|---|
error.type | ✓ | Category enum. Verified values: authentication_error, invalid_request_error, validation_error. (More exist; switch on code, not type.) |
error.code | ✓ | Stable machine-readable code (snake_case). Switch on this. |
error.title | ✓ | Short human-readable title. |
error.message | ✓ | Human-readable detail. May contain end-user PII — do not log naively. |
error.status | ✓ | HTTP status, mirrored in the body. |
error.param | validation | The top-level offending field. |
error.errors[] | validation | Per-field problems — { field, code, message } (field-level code e.g. invalid_type). |
error.doc_url | ✓ | Canonical doc for the code: https://docs.tanqory.com/errors/{code}. |
error.request_id | ✓ | Send this to support — it identifies the request in our trace. |
error.instance | ✓ | The request path that produced the error. |
error.timestamp | ✓ | ISO-8601 server time. |
Error code catalogue (verified)
Switch on error.code. Codes verified against the live gateway:
code | type | HTTP | When |
|---|---|---|---|
auth_token_invalid | authentication_error | 401 | Missing / invalid / expired bearer token. Re-authenticate; don't retry the same token. |
resource_not_found | invalid_request_error | 404 | Path or resource id doesn't exist. Verify id + tenant; don't retry. |
validation_failed | validation_error | 400 | One or more fields rejected — inspect errors[]. Fix input; don't retry the same payload. |
This catalogue lists only codes confirmed from real responses. The full
catalogue is generated from the gateway and grows as more codes are
verified — never hard-code against an unlisted code. Each code's
doc_url is the source of truth for that code.
Status codes that appear in the spec
The table below counts how many publishable operations declare each status code in the Admin API. The "What spec says" column quotes the first declared description verbatim from the spec — your client should treat the runtime envelope as authoritative.
| Status | Ops declaring it | Verified spec description (sample) | What the client should do |
|---|---|---|---|
200 | 326 | (no description — success) | Continue. |
201 | 40 | "Registration successful" (envelope schema declared on this code: RegisterResponseDto) | Continue. |
204 | 2 | (no body) | Continue. |
302 | 1 | "Redirects to domain settings page" | Follow the Location header (browser flow only — server-to-server should not auto-follow without user consent). |
400 | 39 | "Unsupported provider" | Fix client input. Do not retry the same payload. |
401 | 32 | "Invalid credentials" | Re-issue the token; do not retry the same token. See Authentication. |
403 | 2 | "Account locked" | The principal is recognised but blocked. Do not retry without user intervention. |
404 | 23 | "Export request not found" | Verify the ID + tenant. Do not retry. |
409 | 5 | "Email already registered" | Inspect error.code to decide between user-prompt vs. automatic retry. |
429 | 1 | "Too many export requests" | Honor the Retry-After header. See Rate limits. |
503 | 1 | "Service is not ready" | Retry after a short delay. Check status.tanqory.com if it persists. |
Gaps in the spec — do not infer:
- 5xx codes other than 503 are not yet declared on individual ops in this spec.
- 405, 415, 422 — not declared on any op today. The runtime may return them on legitimate misuse; treat as 4xx generic.
- 402, 423, 430 — not used by Tanqory today.
Idempotency
Two POST endpoints declare an Idempotency-Key header in the spec
today:
| Endpoint | Use the key when |
|---|---|
POST /api/v1/stores | Creating a store — guard against double-create on network failures. |
POST /api/v1/stores/process-payment | Charging a payment method — must never replay. |
Submit the same key on retry; the gateway returns the original
response. For other mutating endpoints, an Idempotency-Key header is
accepted silently but is not yet a declared spec contract — relying on
it elsewhere is at your own risk until the spec is amended.
Retry guidance
| Status | Retryable? | How |
|---|---|---|
2xx | n/a | Success — no retry. |
400, 404, 409 | No | Client error — fix the request first. |
401, 403 | No | Re-authenticate; do not retry the same token. |
429 | Yes | Honour Retry-After header — see Rate limits. |
5xx | Yes | Exponential backoff starting at 250 ms, max 4 attempts. Send the same Idempotency-Key if the endpoint declares it. |
Next steps
| Topic | When to read it |
|---|---|
| Authentication | On every 401. |
| Rate limits | On every 429. |
| Webhooks | If you are retrying because a webhook delivery failed. |
| Status | If 5xx persists beyond your retry budget. |