Docs
Errors
Every non-2xx response is an RFC 7807 Problem Details document with a stable code and, wherever one exists, a recovery hint that names the next call.
Anatomy of an error
Every non-2xx response carries Content-Type: application/problem+json and the same
shape. There is no second error format hiding behind a different endpoint.
Two fields do the work that most APIs leave to the reader. code is a stable machine
identifier you can branch on — it is never renamed, only added to. recovery names the
call to make next, in a sentence a model can act on without a round trip to a human.
Every field
application/problem+json
| Name | Type | Description |
|---|---|---|
type
required
|
string (URI) | Dereferenceable. It resolves to the page for this code — that is the contract, not a decoration. |
title
required
|
string | A short, human summary that does not vary with the instance. |
status
required
|
integer | The HTTP status, repeated in the body so a logged payload is self-contained. |
detail
required
|
string | What went wrong this time, with the specific values involved. |
code
required
|
string | The stable machine identifier. Codes are never renamed; new conditions get new codes. |
instance
required
|
string | The path that produced the error. |
requestId
required
|
string | Prefixed ULID. Log it, and quote it to support. |
timestamp
required
|
string (ISO-8601) | UTC, with milliseconds and a trailing Z. |
errors
|
array | Per-field failures, present when the request was rejected field by field. |
pointer
|
string |
A JSON Pointer — /records/0/value — not a dotted path.
|
detail
|
string | What is wrong with that one field. |
code
|
string | The code for that field-level failure. |
recovery
|
object | Present wherever there is an obvious next call. This is the field written for agents. |
action
|
string | The name of the call to make next. |
hint
|
string | One sentence a model can act on directly. |
Status codes
Applied uniformly across all 16 conditions:
| Status | Meaning |
|---|---|
| 202 | Accepted — a human must confirm before it executes |
| 400 | Malformed request |
| 401 | Missing or invalid token |
| 402 | Payment required |
| 403 | Insufficient scope, or an ownership failure |
| 404 | Not found |
| 405 | Method not allowed |
| 409 | Conflict, or an operation already in progress |
| 410 | A time-limited window has closed |
| 422 | Semantic validation failure |
| 429 | Rate limited |
| 500 | Internal error |
| 501 | Not supported on this node or account |
| 502 | Upstream failure — DirectAdmin, the client area, a hosting node or a registry |
| 503 | A node is temporarily unavailable |
| 504 | An upstream system timed out |
Every endpoint documents 401, 403, 404, 429 and
500 as boilerplate; the reference page for each endpoint lists only what is
additionally possible there.
The code table
The full registry lives in the API — each entry a title, a default detail template and an HTTP
status — and both this table and the /errors/{code} pages are generated
from it. Every code is a frozen identifier; branch on it, never on the prose.
| Code | Status | Title |
|---|---|---|
invalid_request
|
400 | The request could not be understood |
invalid_pagination_limit
|
400 | Pagination limit out of range |
unauthorized
|
401 | Missing or invalid API token |
token_revoked
|
401 | This API token has been revoked |
token_expired
|
401 | This API token has expired |
payment_required
|
402 | Payment required |
insufficient_scope
|
403 | This token does not have the required scope |
readonly_scope
|
403 | This token is read-only |
not_owned
|
403 | Not owned by this account |
domain_not_owned
|
403 | Domain not owned by this account |
node_not_allowed
|
403 | That hosting node is not permitted |
ip_not_allowed
|
403 | This token may not be used from this IP address |
origin_not_allowed
|
403 | Requests from this origin are not accepted |
suspended
|
403 | This service is suspended |
access_blocked
|
403 | This request could not be completed |
not_found
|
404 | Not found |
service_not_found
|
404 | Service not found |
invoice_not_found
|
404 | Invoice not found |
record_not_found
|
404 | DNS record not found |
mailbox_not_found
|
404 | Mailbox not found |
database_not_found
|
404 | Database not found |
job_not_found
|
404 | Job not found |
pending_action_not_found
|
404 | Pending action not found |
method_not_allowed
|
405 | Method not allowed on this resource |
conflict
|
409 | The request conflicts with the current state |
hosting_not_ready
|
409 | The hosting account is not ready yet |
attempt_replayed
|
409 | This attempt key has already been used |
quota_exceeded
|
409 | Quota exceeded |
confirmation_expired
|
410 | The confirmation window has closed |
validation_failed
|
422 | The request failed validation |
password_too_weak
|
422 | The password does not meet the policy |
job_not_allowed
|
422 | That background job is not on the allow-list |
rate_limited
|
429 | Too many requests |
confirmation_required
|
202 | A human must confirm this action |
internal_error
|
500 | Something went wrong on our side |
capability_missing
|
501 | This node does not support that operation |
feature_not_available
|
501 | That feature is not available on this account |
upstream_error
|
502 | An upstream system returned an error |
client_area_error
|
502 | The Inleed client area returned an error |
da_error
|
502 | DirectAdmin returned an error |
node_error
|
502 | The hosting node could not be reached |
circuit_open
|
503 | That node is temporarily unavailable |
upstream_timeout
|
504 | An upstream system timed out |
shell_not_enabled
|
409 | Shell access is not enabled for this account |
shell_failed
|
502 | The command could not be run on the hosting server |
command_blocked
|
422 | This command is not allowed on the shell |
Errors in MCP
The MCP facade splits failures on one question: can the model fix this by retrying differently?
-
Almost everything is a result with
isError: true— validation failures, business rejections, ownership failures, upstream errors. Clients feed those back to the model, which corrects itself. They carry the samecodeandrecoveryas the REST error. -
A JSON-RPC
erroris reserved for things a retry cannot fix: an unknown tool, a schema violation, an internal failure.