API reference
Management endpoints use cookie-session authentication and CSRF protection. For multi-instance behavior, see instances.
| Method | Endpoint | Description |
|---|---|---|
POST | /api/auth/sessions | Check password; return totpRequired when a code is needed (CSRF required) |
POST | /api/auth/sessions/totp | Complete password sign-in with { code } (pending session + CSRF) |
POST | /api/auth/totp/setup | Propose a seed using fresh credential proof (management + CSRF) |
POST | /api/auth/totp/confirm | Activate the proposed seed using { code } (management + CSRF) |
DELETE | /api/auth/totp/setup | Cancel proposed enrollment (management + CSRF) |
DELETE | /api/auth/totp | Disable TOTP using fresh credential proof (management + CSRF) |
POST | /api/auth/passkeys/reauthentication/options | Begin action-bound passkey verification (management + CSRF) |
POST | /api/auth/passkeys/reauthentication | Verify assertion; return one-use credential proof (management + CSRF) |
DELETE | /api/auth/sessions/current | Revoke the current session (CSRF required) |
GET | /api/auth/csrf | Obtain the CSRF token for the current or a new pre-login context |
POST | /api/auth/setup | Initialize stored credentials once and return a recovery key (CSRF required) |
GET | /api/auth/credentials | Read the administrator username (management session required) |
PATCH | /api/auth/credentials | Update username (current password) or password (fresh credential proof); renew session and revoke old sessions (management + CSRF) |
GET | /api/auth/passkeys | List passkey metadata and HTTPS configuration (management session required) |
POST | /api/auth/passkeys/registration/options | Begin registration with name and fresh credential proof (management + CSRF) |
POST | /api/auth/passkeys/registration | Verify and persist a registration response (management session + CSRF) |
POST | /api/auth/passkeys/authentication/options | Begin discoverable passkey sign-in (anonymous context + CSRF) |
POST | /api/auth/passkeys/authentication | Verify a signed assertion and issue a management session (anonymous context + CSRF) |
DELETE | /api/auth/passkeys/:id | Remove with fresh credential proof; revoke old sessions and renew this one (management + CSRF) |
POST | /api/auth/recovery | Reset password using a recovery key and rotate that key (CSRF required) |
GET | /api/auth/tokens | List token metadata (management session only) |
POST | /api/auth/tokens | Create a read-only integration token (session + CSRF) |
DELETE | /api/auth/tokens/:id | Revoke an integration token (session + CSRF) |
GET | /api/auth/status | Read authentication, enrollment and session state without credentials |
GET | /api/metrics | Parsed HTTP metrics for the Metrics tab |
GET | /api/metrics/config | Check if Caddy metrics directive is enabled |
PUT | /api/metrics/config | Enable or disable Caddy metrics directive |
GET | /api/metrics/raw | Raw Prometheus metrics (public if CADDY_UI_PUBLIC_METRICS=true) |
GET | /api/status | Server status, route count, upstream health, and uptime |
GET | /api/status/caddy-config | Full raw Caddy JSON config |
GET | /api/status/process | Caddy process info including version |
GET | /api/caddyfile | Read Caddyfile from disk |
GET | /api/caddyfile?download=true | Download Caddyfile as a timestamped attachment |
PUT | /api/caddyfile | Save, validate, format, and reload |
POST | /api/caddyfile/validations | Validate (and optionally format) without saving |
POST | /api/caddyfile/reloads | Reload Caddy from disk |
GET | /api/caddyfile/history | List all Caddyfile snapshots |
GET | /api/caddyfile/history/:filename | Read a specific snapshot |
DELETE | /api/caddyfile/history/:filename | Delete a snapshot |
GET | /api/routes | List all routes across all HTTP servers |
POST | /api/routes | Add a reverse proxy route |
PATCH | /api/routes/:id | Update a UI-managed route by ID |
DELETE | /api/routes/:id | Remove a route and its Caddyfile block |
GET | /api/route-notes | Read all route notes |
PUT | /api/route-notes/:domain | Set or clear a route note |
GET | /api/health | Live upstream check via Caddy pool API with TCP fallback (not recorded in uptime history) |
GET | /api/health/uptime | Uptime stats per upstream from persisted history, sampled every 30 seconds by the backend |
GET | /api/health/history | Raw timestamped checks for one upstream, for the route status history view |
GET | /api/tls | List all certificates with expiry and status |
DELETE | /api/tls/:domain | Delete an orphaned, superseded, or expired internal cert |
GET | /api/tls/ca | Download Caddy’s root CA certificate |
GET | /api/logs | Last 200 lines of the configured Caddy log; 404 if missing, 503 if the container is unreachable, 500 if reading fails |
GET | /api/logs/stream | SSE stream of live log output; failures include an error code and request ID |
GET | /api/logs/config | Read log configuration; coded read/parse failures |
PUT | /api/logs/config | Update validated log configuration |
GET | /api/server-names | Read server labels for the selected instance |
GET | /api/server-names/all | Read server labels for every instance |
PUT | /api/server-names/:id | Set a server label |
DELETE | /api/server-names/:id | Remove a server label |
GET | /api/notifications/config | Read notification settings |
PUT | /api/notifications/config | Update notification settings |
POST | /api/notifications/test | Send a test notification |
Empty and unavailable results
An empty result means the resource is empty, not that it couldn’t be read:
GET /api/routesreturns[]only when Caddy has no HTTP routes. If Caddy’s config can’t be read, it returns503with{ "code": "CADDY_CONFIG_UNAVAILABLE" }.GET /api/tlsreturns[]when Caddy hasn’t stored any certificates yet. Caddy only creates its data directory when it first stores something, so a missing data path also returns[]; in local mode the backend log notes when that path may be a missing volume mount. If certificate storage exists but can’t be read (permissions, or the container can’t be reached), it returns500with{ "code": "CERTIFICATE_READ_FAILED" }. Check the backend log for the reason and path.- When certificate storage is readable but Caddy’s config isn’t,
GET /api/tlsstill lists the certificates withisManaged: null. Without Caddy’s config, caddy/ui can’t tell whether a certificate is still in use, so none are markedorphaned. GET /api/route-notesreturns{}when no notes file exists yet. If the notes file can’t be read or isn’t a valid JSON object, it returns500with{ "code": "ROUTE_NOTES_READ_FAILED" }.PUT /api/route-notes/:domainfails the same way and leaves the file unchanged.GET /api/caddyfile/historyreturns[]when there are no snapshots. If the history directory can’t be read, it returns500with{ "code": "CADDYFILE_HISTORY_READ_FAILED" }.GET /api/logsreturns200with{ "lines": [], "path": "..." }for an empty readable file. A missing file returns404withLOG_FILE_MISSING, and a Docker-mode container that can’t be reached returns503withLOG_SOURCE_UNAVAILABLE. Permissions, command or other read failures return500withLOG_READ_FAILED. Failure responses include a request ID; the application logs retain the underlying reason and instance path.GET /api/logs/streamreports failures as SSE events on the established HTTP stream. Events includecode,errorandrequestId, usingLOG_FILE_MISSINGfor a missing file,LOG_SOURCE_UNAVAILABLEfor an unreachable container andLOG_STREAM_ERRORfor other failures. The UI stops failed live mode; start it again after correcting the problem.
The Caddy log source reads the selected instance’s configured log file, rather than Docker’s captured stdout/stderr. A writable directory mount alone does not enable file logging: Caddy must be configured to write to the selected path. The UI displays unavailable reads separately from an empty file. Refresh retries the read and clears the error after success.
Logging configuration
GET /api/logs/config returns defaults when the Caddyfile has no default logger.
A Caddyfile read failure returns 500 with CADDYFILE_READ_FAILED; a configuration
the structural scanner cannot interpret returns 500 with
LOG_CONFIG_PARSE_FAILED. Both include a request ID and retain the cause in the
application logs. Parsing failures never masquerade as disabled logging. The
configuration panel shows a localized error instead of loading indefinitely.
PUT /api/logs/config requires a boolean enabled. When enabling logging, provide
a nonempty string path without control characters, a single size token such as
50mb or 1.5GiB for rollSize, a non-negative safe integer for rollKeep,
json or console for format, and DEBUG, INFO, WARN or ERROR for level.
Paths containing spaces are supported. Invalid request values return 400 with
VALIDATION_FAILED before a write is prepared. Disabling requires only
{ "enabled": false }; unused option values are not serialized.
Caddy still validates the edited configuration before it is written and applied.
A semantic rejection returns 422 with CADDYFILE_VALIDATION_FAILED, leaving the
file and live configuration unchanged. Logging edits replace the existing default
logger, including a bare log or log default, and preserve named loggers and
unrelated source bytes. New logger text follows the local indentation and line
endings; the whole file is not formatted.