PanelDOCSv1.0.0

API REST conventions

How every token API resource is named, listed, paged, filtered and refused, and how errors look.

The newer token API resources follow one set of rules, and the older ones follow them where that does not change what they answer today. Everything is JSON in and out.

bash
A=https://api.yourdomain.com/v1
H="Authorization: Bearer hf_xxx"

Names and methods

Call Meaning
GET /v1/…/things list
GET /v1/…/things/{id} one
POST /v1/…/things create. Answers 201 with a Location header that is the new item's address
PATCH /v1/…/things/{id} change the fields you send; the others stay
PUT replace a setting that has one value (PHP settings of a website, an autoresponder, the quiet hours)
DELETE /v1/…/things/{id} remove
POST /v1/…/things/{id}/<verb> do something: start, restart, close, mark-paid, test …

Resources are plural nouns (/accounts/{username}/mailboxes, /ftp-accounts, /cron-jobs …; see single items).

Lists, paging and filters

A list answer has data (the page) and meta:

json
{
    "ok": true,
    "data": [ … ],
    "meta": { "total": 120, "page": 2, "per_page": 50, "total_pages": 3 }
}

The X-Total-Count header carries total too.

Query Meaning
page which page, from 1
per_page items per page, 1 to 200
q only items with these words in any of their values
status only items with this status. A list that has its own status values (/tickets, /orders, /invoices) says which in its description

The newer resources page by default (50 per page). The older lists answer everything until you send page or per_page, so scripts that read them keep working. A bad value (page=x, per_page=0) answers 422.

Errors

Status When
400 the body is not JSON
401 no token, a wrong token, or a token from a refused address
402 the server's licence lacks the module (Email, DNS, Billing …)
403 the token may not do this: read-only token, wrong kind of login, a team role without it
404 no such account, item or endpoint (an account that is not yours is "No such account.")
409 it exists already, or is in use
422 a field is missing or wrong; the answer names the field
429 too many requests (Retry-After, X-RateLimit-* headers), or the sign-in lock-out

The error body stays what it always was, so billing modules and scripts that read it keep working:

json
{ "ok": false, "error": "target is required." }

Ask for the standard error object with the header X-HF-Errors: object (or ?errors=object):

json
{
    "ok": false,
    "error": {
        "code": "validation_failed",
        "message": "target is required.",
        "field": "target"
    }
}

The codes are bad_request, unauthorized, licence_required, forbidden, not_found, conflict, validation_failed, rate_limited, upstream_error and server_error; fields lists the messages of every field when a form check found several. An administrator can make the object the default for every caller with "api_error_format": "object" in the panel's configuration; do that only when nothing on the server still reads the text form (billing modules, older scripts).

Idempotency and limits

Send an Idempotency-Key header with a POST that creates something. The same key with the same body within 24 hours answers the first answer again (with Idempotent-Replayed: true) and does nothing twice; the same key with another body answers 422. Every answer has X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset.

Who may do what

The rules of the panel apply to every resource. A customer's token reaches its own data. A reseller's token reaches its customers'. Administrator-only resources (/webhooks, /staff, /firewall-rules, /server/updates …) answer 403 to everyone else. A Read only token, or a read-only staff login, can only read. A team-role token reaches only what its role allows. The description at GET /v1/openapi.json shows the role each operation needs (x-hf-who, x-hf-write).