Skip to content

API ​

Everything the panel does, it does through its own HTTP API. There is no private path the interface uses and callers cannot.

Authentication ​

Either sign in for a session token:

bash
curl -X POST 'https://panel:2053/PATH/api/auth/login' \
  -H 'Content-Type: application/json' \
  -d '{"username":"admin","password":"…"}'

or use an API token: the one the installer printed, or one from Settings → Authentication → API Token or wui token issue --name NAME. Send it as:

Authorization: Bearer wui_…

What a token cannot do

A token is a machine's. What only an administrator may do answers 403 this needs a signed-in administrator, not an API token: the administrator's own account and two-factor, issuing or revoking tokens, backups, registering nodes and their trust, the panel's settings and template, a restart. Everything about customers, devices, tunnels, hosts, outbounds and routing is open to a token; that is what it is for.

Extra "installer" tokens

Before this was fixed, every update by the installer left one more full-access token named installer on the panel. Each is a working credential nobody uses. Keep the one your automation reads from install-result.env, and revoke the rest in Settings → Authentication → API Token (the list shows each one's prefix and when it was last used).

The documentation is in the panel ​

API in the sidebar lists every endpoint, grouped, with an example body and a curl command carrying the address you reached the panel on. The page is built from the same table the routes are registered from, so it can only describe endpoints that exist, and a new one is documented by being added.

GET /api/docs returns the same as JSON.

A few you will reach for ​

GET /api/overview/fulltelemetry, panel state and inventory in one call
GET /api/clients?search=&status=&group=&page=&perPage=customers
POST /api/clientscreate one; telegramId, quotaBytes, expiresAt, deviceLimit, interfaceIds
POST /api/clients/{id}/resetreset traffic
GET /api/clients/{id}/configs · GET /api/devices/{id}/profilesevery config, per device and host
GET /api/interfaces · POST · PATCH /{id} · DELETE /{id}tunnels
GET /api/outbounds · POST /api/outbounds/{id}/checkhops and probes
GET /api/routing · POST /api/routing/rules/orderrules
GET /api/template?section= · PUTthe whole configuration
POST /api/backups · GET /api/backups/{name}backups
GET /api/backups/password · PUT /api/backups/passwordwhether archives are encrypted; set the backup password ({"password":"…"}, at least ten characters; empty stops encrypting)
GET /api/system · GET /api/system/historythe host
GET /api/health200 {"ok":true} or 503, with no sign-in, for an uptime checker; it is under the panel's own path, and only someone signed in is told why it is not ok
GET /api/metricsfor Prometheus: each tunnel up or down, the loop's last run, usage writes failing, nodes reachable, and the backups kept

Errors come back as {"error": "…", "field": "…"} with a status that means what it says; a validation error names the field.

Released under the AGPL-3.0 License.