# panel-api HTTP API wrapper around panelctl with a web UI. Default bind: `127.0.0.1:9911` ## Endpoints ### Health & UI | Method | Path | Description | |--------|------|-------------| | GET | `/` | Web UI (served from `frontend/index.html`) | | GET | `/health` | Health check | ### Apps — Read | Method | Path | Description | |--------|------|-------------| | GET | `/apps` | List all apps | | GET | `/apps/` | Show single app manifest | | GET | `/apps//status` | Container status (running/stopped) | | GET | `/apps//compose` | Read compose.yaml content | | GET | `/apps//logs?tail=N` | Fetch last N log lines (default 100) | | GET | `/apps//backups` | List available backups | | GET | `/apps//backups/` | Download backup zip | ### Apps — Write | Method | Path | Description | |--------|------|-------------| | POST | `/apps/init` | Create a new app | | POST | `/apps//deploy` | Deploy (compose up + caddy reload) | | POST | `/apps//restart` | Restart (compose down + up) | | POST | `/apps//stop` | Stop (compose down) | | POST | `/apps//render-route` | Re-render Caddy route | | POST | `/apps//compose` | Save compose.yaml content | | POST | `/apps//validate-compose` | Validate compose file | | POST | `/apps//backup` | Create volume backup (zip) | | POST | `/apps//restore` | Restore from backup | | POST | `/apps//remove` | Remove app | ## Example payloads ### Create app (single domain) ```json { "name": "whoami", "domain": "whoami.srazka.com", "port": 18080, "auth": true } ``` ### Create app (multiple domains) ```json { "name": "myapp", "domain": "app.srazka.com,www.app.srazka.com", "port": 18081, "auth": true } ``` Or using the `domains` array format: ```json { "name": "myapp", "domains": ["app.srazka.com", "www.app.srazka.com"], "port": 18081, "auth": true } ``` ### Create app (wildcard domain) ```json { "name": "wildcard", "domain": "*.srazka.com", "port": 18082, "auth": false } ``` Note: Wildcard domains require DNS challenge configuration in Caddy. ### Save compose ```json { "content": "services:\n app:\n image: nginx:latest\n ports:\n - '127.0.0.1:18080:80'\n" } ``` ### Remove and keep volumes ```json { "keepVolumes": true } ``` ### Restore from backup ```json { "file": "whoami-20260101-120000.zip" } ``` ## Response format All JSON responses include an `ok` boolean: ```json { "ok": true, "apps": [...] } ``` Error responses: ```json { "ok": false, "error": "description", "stderr": "panelctl error output" } ``` ## Status response ```json { "ok": true, "name": "whoami", "running": true, "containers": [ { "name": "whoami-app-1", "state": "running", "image": "docker.io/traefik/whoami:latest" } ] } ``` ## Local test ```bash curl -s http://127.0.0.1:9911/health | jq . curl -s http://127.0.0.1:9911/apps | jq . curl -s http://127.0.0.1:9911/apps/whoami/status | jq . curl -s http://127.0.0.1:9911/apps/whoami/logs?tail=50 | jq . curl -s http://127.0.0.1:9911/apps/whoami/backups | jq . ```