Client area

Docs

Conventions

The shape of every response, in one page: envelopes, cursors, typed ids, money, dates and the naming rules both facades share.

The envelope

A single resource is wrapperless. The object is the response body — no data key to unwrap, no envelope to remember.

A collection is wrapped, because it needs to carry pagination alongside the rows: data, hasMore, nextCursor and total.

On success the request id travels in the X-Request-Id response header. On failure it is in the body as well. Log it either way — it is what support will ask you for.

Pagination

Pagination is cursor-based. limit is an integer starting at 1, defaults to 25, and has a per-endpoint maximum — 200 on most collections, lower on a few. Each endpoint's reference page states its own ceiling. An over-limit value returns 422 validation_failed with a /limit pointer in errors[], rather than silently clamping.

Treat nextCursor as opaque — its type is not part of the contract. Pass whatever you received straight back as cursor; never parse it, increment it, or construct one.

Identifiers

Service, invoice and domain ids are integers that come from the client area. Take them from a listing endpoint and pass them back unchanged. A few internal objects use prefixed ULIDs instead: req_ (request id), tok_ (API token), job_ (async job) and pact_ (pending action).

Where a resource has a canonical name, the natural key is the identifier instead: the address for a mailbox or forwarder, the username for a database user, the domain for a zone, the fingerprint for an SSH key.

Money

Money is a decimal JSON number in major units, always paired with a sibling currency. No integer minor units leak out of the API, and no amount ever appears without the currency next to it.

Dates

Most timestamps are ISO-8601 UTC with milliseconds and a Z: "2026-08-29T12:34:56.000Z", suffixed AtpaidAt, createdAt. A few carry a plain YYYY-MM-DD date under the same suffix, notably expiresAt on services and invoices. Parse defensively.

Booleans and null

Booleans are real JSON booleans, prefixed is, has or can: isSuspended, hasMore, canBeRenewed. DirectAdmin's ON/OFF/yes/no/1/0 vocabularies are normalised upstream and never reach you.

unlimited is null — not the string "unlimited", not -1. Where it helps, a limit is expressed as an object so the unit is unambiguous.

A field may be absent or explicitly null — handle both. 0 and false are never treated as empty and are always present.

Naming and paths

  • camelCase in JSON, in both facades, with units in the name: memoryGb, diskUsedMb, ttlSeconds.
  • REST paths are /api/v1/{resource}, with /actions/{verb} for anything that is not CRUD.
  • On an action path the method expresses intent: GET prices or previews it, POST performs it, DELETE cancels a scheduled one. Destructive operations always have a paired GET to use as a dry run.
  • MCP tool names are snake_case and verb-object, named by hand rather than derived from the path.
Esc
navigate open Esc close