Skip to main content

Server API

The server API is the way into the server for a program: a billing system that creates accounts, a script that suspends one, a CI job that starts a backup. It covers what an admin user does across accounts, not what an account holder does inside one; that is the account API, which each account reaches with its own keys.

A call authenticates with a server API key (API Keys), an espat_… bearer token that acts as the admin user who owns it.

Where it is​

The API lives on the admin host, under the admin app:

https://admin.<server hostname>/api/v1/

The same API, with the same keys, also answers at https://<server hostname>/api/v1/: Apache proxies /api/v1 on the bare hostname to the admin app. A URL in a response always names admin.<server hostname>. Nothing else of the admin app is on the bare hostname; it serves a splash page at /, its favicons and logo, and a 404 for everything else.

The reference is on the admin host only, at /api/docs (Integrations › API Documentation in the admin app). It is generated from the server itself, so it matches the version you run, and it has the fields of every request and response. The page offers the OpenAPI document as OpenAPI JSON (/api/docs.json) and OpenAPI YAML (/api/docs.yaml), and lists every webhook event type in a Webhooks group, with its headers, body and a sample request.

Authentication​

Send the key as a bearer token:

curl -H "Authorization: Bearer espat_..." \
https://admin.<server hostname>/api/v1/ping

GET /api/v1/ping answers with the server's id and the admin user the key acts as:

{
"message": "pong",
"server": { "id": "0192b7c4-…" },
"admin_user": { "id": "0192b7c4-…", "username": "alice" }
}

A request without a valid key answers 401 with an application/problem+json document and a WWW-Authenticate: Bearer header. A read-only key on a write operation answers 403.

Only a server API key

The API firewall accepts nothing else: not an admin session, and not the token that server:login mints, which is a web sign-in token for the login page (Break-glass on the host).

A key is not held to its admin user's allowed IP addresses (Allowed addresses).

What the API looks like​

The server API speaks plain JSON: a request body is a JSON object with the fields the reference names, and a response is a JSON object. A list is an object that holds the array and, where the list is paged, where the next page starts (next for accounts, nextBefore for webhook deliveries). It does not use the JSON:API envelope of the account API.

StatusMeaning
200, 201, 204Done. A creation that shows a secret once, such as a setup link or a webhook signing secret, shows it in this response only.
401No valid key.
403The key is read-only and the operation writes.
404No such account, admin user, endpoint or task.
409A rule of the domain refuses it: a username that exists, an account pending deletion, a purge whose grace period has not elapsed. The body says why.
422A missing or invalid field.

Most paths name an account by its username, an admin user by its username, and a domain user by its address; webhook endpoints, backups and purges go by id.

What it covers​

The operations, by what they act on. Every GET needs the all:readonly scope; the rest need all:readwrite (API Keys has the two scopes and the read-only default).

The server​

Method and pathWhat
GET /api/v1/pingWho you are, as above.
GET, PATCH /api/v1/serverThe server and its settings: where its panels, database tools, name servers and SSH daemon are; the admin second-step policy, what the account "Can't sign in?" page offers, the account purge grace period, whether purges run automatically.

Accounts​

Method and pathWhat
GET, POST /api/v1/accountsList the accounts; create one. A new account has no domain and no password; the response carries its single-use setup link and PIN, shown once.
GET, PATCH /api/v1/accounts/{username}An account with its status, domains and limits; change its limits or set a password.
POST /api/v1/accounts/{username}/domainsAttach a hostname and provision its services: domain, identity, mail, website and the www alias.
POST /api/v1/accounts/{username}/setup-linksA new setup link. It invalidates the current password and ends every session.
POST /api/v1/accounts/{username}/impersonationsA short-lived URL that signs its holder in as the account (Act in an account).
POST, DELETE /api/v1/accounts/{username}/suspensionSuspend; unsuspend.
POST, DELETE /api/v1/accounts/{username}/terminationTerminate, which starts the deletion flow; restore a terminated account, which comes back suspended.
DELETE /api/v1/accounts/{username}One step towards gone: an active or suspended account is terminated, a terminated one is purged. immediate, finalBackup and purgeBackups are query parameters.
GET /api/v1/account-purges, GET /api/v1/account-purges/{id}, POST /api/v1/account-purges/{id}/retriesThe deletions, where each has got to, and a retry of a failed one.
GET, POST /api/v1/accounts/{username}/api-keys, DELETE …/api-keys/{id}The account's own API keys (epat_…): list, create one for it, revoke.
PUT /api/v1/host-users/{address}/passwordSet, or generate, the password of a domain user.

Suspend, terminate and delete an account explains the states and the grace period.

Admin users​

Method and pathWhat
GET, POST /api/v1/admin-usersList; create one, which answers its setup link.
GET, PATCH, DELETE /api/v1/admin-users/{username}One admin user; set its password or replace its allowed IPs; delete it. Deleting an admin user deletes its API keys.
POST /api/v1/admin-users/{username}/setup-linksReset the credentials and answer a new setup link.
POST /api/v1/admin-users/{username}/login-tokensMint a sign-in token, as server:login does.

Backups​

Method and pathWhat
GET, POST /api/v1/backup-repositories, GET, PATCH …/{id}, POST …/{id}/checksThe repositories, and a check of one.
GET /api/v1/backup-assets, GET …/{id}, GET …/{id}/snapshotsWhat the server backs up, and the snapshots of one asset.
POST /api/v1/backup-assets/{id}/backups, POST …/{id}/restoresBack one asset up now; restore a snapshot of it.
POST /api/v1/accounts/{username}/backupsBack every asset of an account up now.
GET /api/v1/backup-tasks/{id}A backup or a restore, to poll.

Backups explains repositories, assets and retention.

Webhooks​

The server's webhook endpoints (Webhooks): /api/v1/webhook-endpoints, …/{id}/tests, …/{id}/secret-rotations, …/{id}/deliveries, …/{id}/retries, /api/v1/webhook-deliveries/{id} and /api/v1/event-types. Pausing, resuming and enabling an endpoint is a PATCH of its status.

Why the two APIs are separate

The account API acts as one account and reaches everything inside it. The server API acts as an admin user and reaches every account from the outside: it creates, limits, suspends and deletes them, and hands out the credentials their holders start with. A system that needs to act inside an account creates an account key for it with POST /api/v1/accounts/{username}/api-keys and uses the account API with that.