ozpanel sovereign hosting
Get ozpanel

Operator & API reference

API and automation

OpenAPI, sessions and scoped tokens, access tokens, conventions, jobs and events, console vs CLI, every CLI command.

Overview

One HTTP API behind every console. Agentic ready: every route self-documented, typed, scoped, danger-rated.

  • Basehttps://panel.example.com/api/v1, any node, same state.
  • OpenAPI/api/v1/openapi.json (3.0), generated from the route registry. Undocumented route = server refuses to start.
  • Swagger UI/docs/. Each operation: summary, schemas, x-min-role, scope, danger level.
  • Planned routes[PLANNED], x-status: planned, answer 501.
  • VersionGET /version: release, node, implemented and planned route counts.
  • Not availableMCP server · webhooks · flows · idempotency keys.

Authentication and tokens

SessionAPI token
GetPOST /auth/login (+ /auth/2fa/verify)POST /auth/tokens or ozpanel admin token
SendCookie + X-CSRF-Token on writesAuthorization: Bearer ozp_…
AuthorityFull roleRole narrowed by scopes
Dangerous routesBy roleOnly with allow_dangerous
Lifetime12 h slidingUntil expires_at or revoked
POST /auth/tokens {"name":"billing","scopes":["tenants:write","provision:write","stats:read"],
  "allowed_ips":["203.0.113.10"],"expires_at":"2027-01-01T00:00:00Z","allow_dangerous":false}
curl -H 'Authorization: Bearer ozp_…' https://panel.example.com/api/v1/ozpanel/health
FieldValuesDefault
namelabelrequired
scopes<tag>:read|write|admin, <tag>:*, *required
allowed_ipsaddressesany
expires_atRFC 3339none
allow_dangerousbool; high and critical routesfalse
  • RulesGET needs :read, others :write. Narrow only. Checks: auth → admin restriction → role → scope → danger → CSRF.
  • Storageozp_ + 64 hex, shown once, SHA-256 stored.
  • Call logGET /auth/tokens/{id}/calls; revoke DELETE /auth/tokens/{id}.
  • WhoOperators, tenants and mailbox owners mint their own; tenant tokens stay in the tenant.

Access tokens (mail and SSO)

Separate type: ES256 JWT with subject, level (mailbox · tenant · admin · service) and scopes (mail:imap, mail:smtp). Cluster-wide revocation, checked every use. RFC 7662 introspection for Dovecot. Routes: /tokens/me, /tokens/tenant, /tokens. CLI: token-mint, token-revoke, token-check.

Other credentials

Recovery token (recovery routes only) · node certificates on 9601 (node routes only).

Conventions

{"ok": true,  "data": {…}, "error": null}
{"ok": false, "data": null, "error": "specific message"}
CodeMeans
200 / 201 / 207OK · created · partial fan-out
400 / 401 / 403 / 404Bad field · no auth · not allowed · not found or not yours
409 / 429Quota, exists, precondition · rate limited
500 / 501 / 503Error with reason · planned · dependency down

JSON bodies ≤64 KiB (uploads 512 MiB) · 60 s timeout · Cache-Control: no-store · secrets shown once · dry_run where a route says so · no global pagination (limit, offset, days, lines per route).

Jobs and events

KindCalls
JobsGET /ozpanel/jobs, /ozpanel/jobs/{id}, /ozpanel/jobs/{id}/events (SSE), POST …/cancel
Scheduled tasksGET /schedule?node=, /schedule/{task}/runs, POST …/ack; severity never · failing · late · hung · ok
RealtimeGET /realtime/subscribe?module=&category=&node=&min_priority=&backlog=20 (root-mounted SSE)
Log streams/logs/agent/stream, /logs/service/{unit}/stream, /apps/{name}/logs/stream
NotificationsPanel feed, email, Web Push. See Notifications.

Every service module also has GET/PUT /{module}/settings, /{module}/settings/verify, /{module}/config/live, /stored, /diff (unredacted).

Routes by area

AreaPrefixesChapter
Install, cluster/install, /cluster, /meshInstall, Cluster
Web/caddy, /certs, /phpfpm, /domainsWeb
Apps/apps, /app-port-requests, /recipes, /podmanApps
Mail/mail, /postfix, /dovecot, /rspamd, /mailgwMail
Webmail, push/mail/me, /webmail, /oauth, /notify, /meWebmail
DNS/dns, /namecheapDNS
Databases/mariadb, /galera, /postgresql, /repmgrd, /pgbouncer, /redisDatabases
Tenants, storage, backups/tenants, /plans, /provision, /files, /terminal, /backups, /juicefs, /garage, /storageTenants
Security/nftables, /network-policy, /crowdsec, /ssh, /secrets, /authSecurity
Platform/ozpanel (health, config-check, jobs, audit, modules), /schedule, /stats, /logshere

Route tables

Moved here from the chapters so the user path carries no routes. Paths are relative to /api/v1.

Web, PHP, domains

PathRole
GET/POST /caddy/vhosts, GET/PUT/DELETE /caddy/vhosts/{domain}, …/cert, …/logs, …/dns, …/verify, …/mtls*domain_admin
/caddy/status, health, config, raw, settings, plugins, upstreams, tls, tls/audit, tls/recheck, metrics, live, verify, reload, reconfigure, storage*, welcome*super_admin
/certs, /certs/status, /certs/sync, /certs/importsuper_admin
POST /phpfpm/pools, DELETE /phpfpm/pools/{domain}, /phpfpm/pools/{domain}/phpdomain_admin
/phpfpm/status, health, versions, pools, policy, settings, raw, reloadsuper_admin
/domains, /domains/{domain}, …/overview, …/provisiondomain_admin

Apps and containers

PathRole
GET/POST /apps · GET/PUT/DELETE /apps/{name} · …/start /stop /restart /enable /disable · …/placement · …/run-on · …/image · …/logs · …/inspect · …/relink · …/events · …/ports · /app-events · /recipes · POST /terminal/app-sessionsdomain_admin
/app-port-requests, …/approve, …/deny · /podman/status, /podman/containers, /podman/prunesuper_admin

Mailbox console (self-service)

CallDoes
POST /mail/me/passwordMail and app sign-in together
POST /mail/me/app-passwords {"name"}Shown once; up to 5
GET/POST /tokens/me, …/{jti}/revoke, …/{jti}/apple-mailAccess tokens; Apple Mail profile
GET/PUT /mail/me/filters, PUT /mail/me/vacationRules, away message
PUT /mail/me/webmail-default {"client":"roundcube|sogo"}Default roundcube
GET /mail/me/diagnostics, /stats, /activitySelf-check and figures

Files

File callNotes
GET /files/list, /files/download?path=
POST /files/upload≤512 MiB; disk limit checked
POST /files/mkdir, /move, /chmod, /archivetar.gz create/extract
DELETE /files {path,recursive}

Console or CLI

TaskConsoleCLI / script
Install first node—scripts/install-node.sh or ozpanel install
Follow / resume install/admin/install → Resumeozpanel bootstrap
First admin—--admin-email or ozpanel admin create
Forced first-login password—--first-login or ozpanel first-login
Join a nodeCluster → Operations (generic form)POST /cluster/join on the master
Evict / readmitEvict button; readmit via generic formPOST/DELETE /cluster/nodes/{name}/evict
Floating IPCluster → Floating IP--floating-ip
Module settingsEach module's Settings tabAPI
WebmailSupport services: install, reconfigure, verify, DB migrate, password rotateAPI
StorageGarage/JuiceFS enable, fsck, metadata engine, data dirsAPI
Deploy / updateCluster → Updatesscripts/deploy-node.sh to the master
Recovery/recovery (recovery token), grantsozpanel recover, admin recovery-token, admin recovery-grant
Tokens, admin IPs—ozpanel admin token, allow-ip, console-restriction

The ozpanel CLI

ozpanel <command> [flags]; --config defaults to /etc/ozpanel.json.

CommandKey flagsDoes
versionRelease and bundled artifacts with sha256
serveThe panel (systemd)
migrateApply schema migrations
installSee Install; --floating-ip applied at the handoverMake this machine a node
init-config--floating-ip: "this node's floating IP — its public address when it sits behind NAT"Write node config
bootstrap--pause-at-handover, --freshRun or resume steps
first-login--host, --port, --temp-password, --new-passwordProvider password change
recover--apply, --force, --settle 75s, --configStranded node
admin create | passwd | token | recovery-token | recovery-grant | allow-ip | console-restrictionSee InstallLogins, tokens, access
identity csr | sign | install | show--allow-unregistered on signOffline enrolment
token-mint | token-revoke | token-check--subject --level --scopes --label --expires · --jti · --tokenAccess tokens
usage-collect, backup-run --schedule, mail-backup-run --job, mail-digestCron jobs
pull-release, boot-gate, pgbouncer-follow-primary, galera-ready-gate, galera-position, galera-recover, juicefs-mount-gate, caddy-storage-gate, app-gate, app-ready, ssh-wait-listen, tinc-wait-bind, mailgw, mesh-join, service-ids, sync-mesh-peersService hooks, run by systemd or daemons
ozpanel admin token --email admin@example.com --name deploy --ttl 1h --dangerous
ozpanel token-mint --subject user@example.com --level mailbox --scopes "mail:imap mail:smtp" --label "Mail app"

Previous: Security