English
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/full | telemetry, panel state and inventory in one call |
GET /api/clients?search=&status=&group=&page=&perPage= | customers |
POST /api/clients | create one; telegramId, quotaBytes, expiresAt, deviceLimit, interfaceIds |
POST /api/clients/{id}/reset | reset traffic |
GET /api/clients/{id}/configs · GET /api/devices/{id}/profiles | every config, per device and host |
GET /api/interfaces · POST · PATCH /{id} · DELETE /{id} | tunnels |
GET /api/outbounds · POST /api/outbounds/{id}/check | hops and probes |
GET /api/routing · POST /api/routing/rules/order | rules |
GET /api/template?section= · PUT | the whole configuration |
POST /api/backups · GET /api/backups/{name} | backups |
GET /api/backups/password · PUT /api/backups/password | whether archives are encrypted; set the backup password ({"password":"…"}, at least ten characters; empty stops encrypting) |
GET /api/system · GET /api/system/history | the host |
GET /api/health | 200 {"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/metrics | for 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.
