API Reference
HTTP API endpoints exposed by dockward on localhost, including trigger, status, blocked digest, audit, and metrics routes.
Last updated: February 28, 2026
API Reference
The dockward API binds exclusively to 127.0.0.1:<port>. Default port is 9090. Configure via api.port in the config file.
Endpoints
| Method | Path | Description |
|---|---|---|
POST |
/trigger |
Trigger an immediate poll for all auto_update services |
POST |
/trigger/<name> |
Trigger an immediate poll for one service |
GET |
/blocked |
Map of blocked digests keyed by service/image |
DELETE |
/blocked/<name> |
Unblock a service (legacy; prefer POST /unblock/<name>) |
POST |
/unblock/<name> |
Unblock a service |
GET |
/not-found |
Map of unresolvable local digests keyed by service/image |
GET |
/errored |
Map of services with persistent poll errors |
GET |
/status |
Aggregated state for all configured services |
GET |
/status/<name> |
Aggregated state for a single service |
GET |
/audit |
Recent audit log entries as JSON |
GET |
/health |
Liveness check |
GET |
/metrics |
Prometheus text format metrics |
GET |
/ui |
Web dashboard |
GET |
/ui/events |
SSE stream of live audit entries |
POST /trigger
Triggers an immediate poll for all services with auto_update: true, bypassing the configured poll_interval.
curl -sf -X POST localhost:9090/trigger
Response:
{"status":"triggered","scope":"all"}
POST /trigger/<name>
Triggers an immediate poll for a single service by name.
curl -sf -X POST localhost:9090/trigger/myapp
Success response:
{"status":"triggered","scope":"myapp"}
Skipped — auto_update: false:
{"status":"skipped","reason":"auto_update is false"}
Skipped — deploy already in progress:
{"status":"skipped","reason":"deploy in progress"}
All return 200 OK. A 404 indicates the service name is not in the config.
GET /blocked
Returns all blocked digests. A digest is blocked after a rollback to prevent the same bad image from being redeployed. The block clears automatically when the remote digest changes.
Keys are in service/image format, values are the blocked digest.
curl -s localhost:9090/blocked
Example response:
{"myapp/myapp:latest":"sha256:deadbeef..."}
Empty object when nothing is blocked:
{}
DELETE /blocked/<name> · POST /unblock/<name>
Manually unblocks a service, allowing the next poll to attempt a deploy. The POST /unblock/<name> form is used by the web UI; both are equivalent.
curl -sf -X DELETE localhost:9090/blocked/myapp
curl -sf -X POST localhost:9090/unblock/myapp
Response when unblocked:
{"status":"unblocked","service":"myapp"}
Response when service was not blocked:
{"status":"not_blocked","service":"myapp"}
Unblocking before pushing a fixed image triggers another deploy of the same bad image, which will roll back and re-block.
GET /not-found
Returns services whose local image digest could not be resolved. Dockward suppresses deploys until the remote digest changes.
Keys are in service/image format, values are the last known remote digest.
curl -s localhost:9090/not-found
Example response:
{"myapp/myapp:latest":"sha256:abc123..."}
GET /errored
Returns services with a persistent poll error. Dockward notifies on first occurrence and suppresses repeats until the error changes or resolves.
curl -s localhost:9090/errored
Example response:
{"myapp":"remote digest: HEAD http://localhost:5000/v2/myapp/manifests/latest: dial tcp 127.0.0.1:5000: connect: connection refused"}
Empty object when no services are errored:
{}
GET /status
Returns the aggregated state for all configured services plus watcher-level metadata.
curl -s localhost:9090/status
Example response:
{
"uptime_seconds": 86400,
"last_poll": "2026-02-28T10:30:00Z",
"poll_count": 288,
"services": [
{
"name": "myapp",
"status": "ok",
"auto_update": true,
"auto_start": false,
"auto_heal": true,
"healthy": true,
"deploying": false,
"degraded": false,
"exhausted": false,
"restart_failures": 0,
"updates_total": 5,
"rollbacks_total": 0,
"restarts_total": 1,
"failures_total": 0,
"image": "myapp:latest",
"image_digest": "sha256:abc123...",
"containers": [
{
"name": "myapp_api_1",
"state": "running",
"status": "Up 2 hours (healthy)",
"image": "myapp:latest"
}
],
"has_stats": true,
"cpu_percent": 2.4,
"memory_percent": 18.7,
"memory_usage_mb": 187.3,
"memory_limit_mb": 1000.0
}
]
}
status field — priority-ordered, only the highest applies:
| Value | Meaning |
|---|---|
exhausted |
Max restart attempts reached; manual intervention required |
degraded |
Healer detected a die or unhealthy event; attempting recovery |
errored |
Persistent poll error (registry unreachable, compose failure, etc.) |
blocked |
Digest blocked after rollback; retries when remote digest changes |
not_found |
Local image not found; suppressed until remote digest changes |
deploying |
Image update in progress |
ok |
Running and healthy |
unhealthy |
Health gauge reports unhealthy; no active recovery |
unknown |
No health data yet (process just started or no Docker event received) |
Field notes:
blocked,not_found,errored— omitted from JSON when emptyhealthy— omitted until the healer receives a Docker health eventimage,image_digest— omitted until first successful deploy or poll cyclecontainers— omitted for services with nocompose_projectorsilent: truehas_stats—falseuntil the first monitor poll cyclelast_poll— omitted until the first poll cycle completes
GET /status/<name>
Returns the aggregated state for a single service. Same shape as a single entry in the services array above (not the wrapper object).
curl -s localhost:9090/status/myapp
Returns 404 if the service name is not in the config.
GET /audit
Returns the last N audit log entries as a JSON array. Returns an empty array when audit.path is not set.
Query parameters:
| Parameter | Default | Max | Description |
|---|---|---|---|
limit |
100 |
500 |
Number of entries to return (most recent first) |
curl -s "localhost:9090/audit?limit=20"
Example response:
[
{
"timestamp": "2026-02-28T10:00:00Z",
"service": "myapp",
"event": "updated",
"message": "Deployed new image successfully.",
"level": "info",
"old_digest": "sha256:aaa...",
"new_digest": "sha256:bbb..."
}
]
GET /health
Liveness check. Returns 200 OK when the process is running.
curl -s localhost:9090/health
{"status":"ok"}
GET /metrics
Prometheus text exposition format. See Metrics Reference.
curl -s localhost:9090/metrics
GET /ui
Web dashboard. Open in a browser:
http://127.0.0.1:9090/ui
See Web UI Reference.
GET /ui/events
Server-Sent Events stream of live audit entries. Replays the last 50 entries on connect, then streams new entries as they are logged.
Consumed automatically by the web UI. Can also be consumed directly:
curl -s localhost:9090/ui/events