HTTP API
The API controls the same supervisor as the CLI. Enable the web UI or a standalone API server before using these examples. They assume the default web address, http://127.0.0.1:3120.
See authentication when using a non-loopback address. The API JSON Schema describes the response types.
Encrypt remote API access
The web UI and standalone API listeners serve plain HTTP. Direct non-loopback requests send X-Pitchfork-Token unencrypted, allowing anyone who can observe that traffic to capture the token and reuse it to control the supervisor. Keep the listener bound to loopback (127.0.0.1 or ::1). For remote access, place it behind an HTTPS reverse proxy on the same host and keep the HTTP backend on loopback. See the proxy authentication guidance for token forwarding and proxies on another host.
The following REST endpoints are available on the web UI port (or the dedicated API port if configured). All endpoints accept and return JSON unless otherwise noted.
For routes containing {id}, URL-encode the entire qualified daemon ID as one path segment: myproject/api becomes myproject%2Fapi. Keep the unencoded namespace/name form in JSON values. In JavaScript, use encodeURIComponent(id) when constructing these URLs.
GET /api/stats
Return system-level statistics.
curl http://127.0.0.1:3120/api/statsResponse:
{
"process_count": 42,
"cpu_count": 8,
"total_memory": 17179869184
}GET /api/daemons
List all daemons with full runtime state.
curl http://127.0.0.1:3120/api/daemonsResponse:
[
{
"id": {
"namespace": "myproject",
"name": "api",
"qualified": "myproject/api",
"safe_path": "myproject--api"
},
"title": "API Server",
"pid": 12345,
"status": { "type": "running" },
"dir": "/home/user/myproject",
"cpu_percent": 2.3,
"memory_bytes": 67108864,
"uptime_secs": 3600,
"proxy_url": "https://api.localhost",
"slug": "api",
"active_port": 3000,
"resolved_port": [3000]
}
]GET /api/daemons/
Get a single daemon by qualified ID.
curl http://127.0.0.1:3120/api/daemons/myproject%2FapiReturns a single ApiDaemonEntry object (same shape as /api/daemons items).
POST /api/daemons/{id}/start
Start a daemon.
curl -X POST http://127.0.0.1:3120/api/daemons/myproject%2Fapi/startResponse:
{ "ok": true }POST /api/daemons/{id}/stop
Stop a running daemon.
curl -X POST http://127.0.0.1:3120/api/daemons/myproject%2Fapi/stopPOST /api/daemons/{id}/restart
Restart a daemon.
curl -X POST http://127.0.0.1:3120/api/daemons/myproject%2Fapi/restartPOST /api/daemons/{id}/enable
Enable a daemon so it can be started.
curl -X POST http://127.0.0.1:3120/api/daemons/myproject%2Fapi/enablePOST /api/daemons/{id}/disable
Disable a daemon.
curl -X POST http://127.0.0.1:3120/api/daemons/myproject%2Fapi/disableGET /api/logs/{id}/tail
Stream logs for a daemon as newline-delimited JSON (Content-Type: application/x-ndjson). Each line is a JSON object. Use curl -N to display entries as they arrive, then press Ctrl+C to stop following.
curl -N http://127.0.0.1:3120/api/logs/myproject%2Fapi/tailResponse format (NDJSON):
{"id":1,"timestamp":"2026-05-31 10:00:00","daemon_id":"myproject/api","message":"Hello from api daemon"}
{"id":2,"timestamp":"2026-05-31 10:00:02","daemon_id":"myproject/api","message":"Another log line"}The stream can also emit a control object such as {"_clear":true,"_gen":1} when the daemon's logs are cleared. Consumers should discard their buffered history when they receive it.
GET /api/namespaces
List all registered namespaces.
curl http://127.0.0.1:3120/api/namespacesPOST /api/namespaces
Register a namespace by directory.
curl -X POST http://127.0.0.1:3120/api/namespaces \
-H "Content-Type: application/json" \
-d '{"dir": "/home/user/new-project"}'DELETE /api/namespaces/
Remove a namespace.
curl -X DELETE http://127.0.0.1:3120/api/namespaces/oldprojectGET /api/proxies
List all configured proxy slugs.
curl http://127.0.0.1:3120/api/proxiesGET /api/processes/{id}/tree
Get the process tree for a daemon, including all child processes.
curl http://127.0.0.1:3120/api/processes/myproject%2Fapi/treeResponse:
[
{
"pid": 12345,
"name": "node",
"exe": "/usr/local/bin/node",
"cpu_percent": 2.3,
"memory_bytes": 67108864,
"virtual_memory_bytes": 268435456,
"uptime_secs": 3600,
"thread_count": 7,
"status": "Sleep",
"children": [
{
"pid": 12346,
"name": "node",
"exe": "/usr/local/bin/node",
"cpu_percent": 0.5,
"memory_bytes": 33554432,
"virtual_memory_bytes": 134217728,
"uptime_secs": 3590,
"thread_count": 7,
"status": "Sleep",
"children": []
}
]
}
]Request failures
Inspect the HTTP status and response body when a request fails. Use URL-encoded qualified IDs (namespace%2Fname) in daemon URLs. Control requests can return HTTP 200 with "ok": false and an "error" message, so check the response body as well. Investigate missing daemons, invalid configuration, or failed startup through the daemon's status and logs.
