HTTP API

Portoser's web backend exposes a REST API used by the web UI and the CLI's history commands. Every endpoint lives under /api/.

The backend is FastAPI. Auto-generated OpenAPI docs are available at /docs and /redoc on a running instance.

Authentication

When KEYCLOAK_ENABLED=true, the backend's KeycloakAuthMiddleware requires a bearer token on every protected route. When disabled (the default for ./compose.sh up), endpoints are open and a synthetic dev user is injected.

For first-party tools (the CLI, the web UI) the bearer token comes from the Keycloak login flow. For your own scripts, get a token from the Keycloak /realms/<realm>/protocol/openid-connect/token endpoint.

Core routers

/api/services

Method Path Purpose
GET /api/services List all services from the registry
GET /api/services/{name} Single service detail

/api/machines

Method Path Purpose
GET /api/machines List machines
GET /api/machines/{name} Single machine detail
POST /api/v1/devices Register a new device (note: /api/v1/ legacy path)

/api/deployment

Method Path Purpose
POST /api/deployment/execute Execute pending moves from the cluster view
GET /api/deployment/state Current pending state

/api/health

Method Path Purpose
GET /api/health/dashboard Aggregated health for the whole cluster
GET /api/diagnostics/health/all Full diagnostic snapshot
POST /api/diagnostics/run Run the diagnose phase on demand

/api/dependencies

Method Path Purpose
GET /api/dependencies/graph Dependency graph for ReactFlow

/api/history

Method Path Purpose
GET /api/history/deployments List deployments (filterable by service / machine / status)
GET /api/history/deployments/{id} One deployment with config snapshot
GET /api/history/stats Aggregate stats
GET /api/history/rollback/{id}/preview Preview the changes a rollback would make
POST /api/history/rollback/{id}/execute Execute the rollback

/api/vault

Method Path Purpose
GET /api/vault/status Vault health, sealed state, address
GET /api/vault/services List services with declared Vault secrets
GET /api/vault/services/{service} Secrets declared for one service (values masked)
POST /api/vault/services/{service}/secrets Add or update a secret
POST /api/vault/migrate Migrate a service's .env into Vault
POST /api/vault/migrate-all Migrate every service with a .env

/api/certificates

Method Path Purpose
GET /api/certificates List managed certs
POST /api/certificates/generate/{service} Generate a new cert
POST /api/certificates/renew/{service} Force renewal
GET /api/certificates/keycloak-ca Download Keycloak CA bundle
POST /api/certificates/keycloak-ca/copy/{service} Distribute the CA to a service's host

/api/knowledge

Method Path Purpose
GET /api/knowledge/playbooks List recorded playbooks
GET /api/knowledge/insights/{service} Per-service insights

/api/mcp

Method Path Purpose
GET /api/mcp/status FastMCP server status + base URL
GET /api/mcp/config SSE config for MCP clients
GET /api/mcp/tools List registered MCP tools
POST /api/mcp/tools Create a tool (code + metadata)
GET /api/mcp/tools/{name} Tool definition
PUT /api/mcp/tools/{name} Update tool
DELETE /api/mcp/tools/{name} Delete tool
GET /api/mcp/audit/logs Audit log of tool operations

See MCP Tools for the FastMCP-side surface.

/api/metrics

Method Path Purpose
GET /api/metrics/all Snapshot of all device metrics
GET /api/metrics?format=prometheus Prometheus-format scrape

WebSocket endpoints

Path What it streams
/api/metrics/ws Per-device CPU / memory / disk metrics, subscription-based
/api/uptime/ws Service start / stop / failure events (live event stream)
/ws Deployment events (logs from in-flight deploys)

See Health Monitoring for the message shapes.

Stability

The API is in alpha. Until v1.0, paths and shapes can change between releases. Subscribe to the changelog for breaking changes.

What's not exposed via HTTP

A few subsystems are CLI-only today:

  • The full observe / diagnose / solve / standardize cycle (the web UI exposes diagnostics/run only)
  • Cluster compose orchestration (portoser cluster compose up)
  • Registry edits (use $EDITOR registry.yml and reload)

These are likely to gain HTTP surface, but only if there's a clear use case for it from the UI or MCP.