Skip to main content

Integration API

WatchWarden exposes a stable HTTP API designed for external integrations such as Home Assistant, CI pipelines, and custom monitoring tools. This page is the canonical reference for the API contract.

Contract version: 1.1
Base path: <controller_url>/api/integrations/watchwarden

Stability guarantee

All endpoints listed here are considered stable. Breaking changes (removed fields, changed types, renamed paths) will be announced in release notes and accompanied by a contract version bump.


Authentication

All integration endpoints require an API token. Tokens are created in the WatchWarden UI under Settings → API Tokens.

Pass the token in one of these headers:

Authorization: Bearer ww_a1b2c3d4...

Fallback header (useful when Authorization is reserved by a reverse proxy):

X-WW-Token: ww_a1b2c3d4...

Token format: ww_ followed by 64 hex characters (e.g. ww_a1b2c3d4e5f6...).

Scopes

Each token is created with one or more scopes that limit what it can do:

ScopeAccess
fullAll endpoints (read + write). Default.
readGET endpoints only (summary, containers)
writePOST endpoints only (check, update, rollback)

Rate Limiting

Integration endpoints are rate-limited to 60 requests per minute per IP address.

Error Responses

All errors follow a consistent shape:

{
"error": "Human-readable error message"
}
StatusMeaning
400Invalid request body
401Missing, invalid, revoked, or expired API token
403Token lacks required scope
429Rate limit exceeded
500Internal server error

Endpoints

GET /summary

Returns a high-level overview of the WatchWarden deployment.

Required scope: read or full

Example request
curl -s -H "Authorization: Bearer $WW_TOKEN" \
https://watchwarden.local/api/integrations/watchwarden/summary

Response 200 OK

{
"containers_total": 42,
"containers_with_updates": 5,
"unhealthy_containers": 1,
"agents_online": 3,
"agents_total": 4,
"last_check": "2026-04-01T19:35:00.000Z"
}
FieldTypeDescription
containers_totalintTotal monitored containers
containers_with_updatesintContainers with available updates
unhealthy_containersintContainers with non-healthy status
agents_onlineintConnected agents
agents_totalintAll registered agents
last_checkstring | nullISO 8601 timestamp of most recent check

GET /containers

Returns all monitored containers with their current state.

Required scope: read or full

Query parameters

ParamTypeDescription
agent_idstringOptional. Filter by agent ID.
Example request
# All containers
curl -s -H "Authorization: Bearer $WW_TOKEN" \
https://watchwarden.local/api/integrations/watchwarden/containers

# Filtered by agent
curl -s -H "Authorization: Bearer $WW_TOKEN" \
"https://watchwarden.local/api/integrations/watchwarden/containers?agent_id=<uuid>"

Response 200 OK

[
{
"id": "abc123def456",
"agent_id": "uuid-of-agent",
"agent_name": "prod-host-1",
"name": "traefik",
"image": "traefik:v3.1",
"current_digest": "sha256:aaa...",
"latest_digest": "sha256:bbb...",
"has_update": true,
"status": "running",
"health_status": "healthy",
"policy": "auto",
"tag_pattern": "^v3\\.1\\.\\d+$",
"update_level": "minor",
"last_checked_at": "2026-04-01T19:35:00.000Z",
"last_updated_at": "2026-04-01T18:10:00.000Z"
}
]
FieldTypeDescription
idstringDocker container ID — use this for check/update/rollback
agent_idstringAgent UUID
agent_namestringHuman-readable agent name
namestringContainer name
imagestringFull image reference (name:tag)
current_digeststring | nullRunning image digest
latest_digeststring | nullLatest available digest
has_updatebooleanWhether an update is available
statusstringDocker status (running, exited, etc.)
health_statusstringhealthy, unhealthy, starting, none, unknown
policystring | nullauto, notify, manual, or null (global default)
tag_patternstring | nullRegex filter for valid tags
update_levelstring | nullmajor, minor, patch, all
last_checked_atstring | nullISO 8601 timestamp
last_updated_atstring | nullISO 8601 timestamp

POST /containers/check

Trigger update checks for containers.

Required scope: write or full

Request body

{ "container_ids": ["abc123", "def456"] }

Or check everything:

{ "all": true }

An empty body {} also checks all containers.

Example request
# Check all
curl -s -X POST -H "Authorization: Bearer $WW_TOKEN" \
-H "Content-Type: application/json" \
-d '{"all": true}' \
https://watchwarden.local/api/integrations/watchwarden/containers/check

# Check specific containers
curl -s -X POST -H "Authorization: Bearer $WW_TOKEN" \
-H "Content-Type: application/json" \
-d '{"container_ids": ["abc123def456"]}' \
https://watchwarden.local/api/integrations/watchwarden/containers/check

Response 202 Accepted

{
"message": "Check initiated for 3 agent(s)",
"agents_checked": 3
}

POST /containers/update

Trigger updates for specific containers.

Required scope: write or full

Request body

{ "container_ids": ["abc123", "def456"] }
caution

Updates are destructive — containers are recreated with the new image. Use with care in production. Updates respect dependency ordering and update groups. Blue-green (start-first) strategy automatically falls back to stop-first for containers with direct port mappings.

Example request
curl -s -X POST -H "Authorization: Bearer $WW_TOKEN" \
-H "Content-Type: application/json" \
-d '{"container_ids": ["abc123def456"]}' \
https://watchwarden.local/api/integrations/watchwarden/containers/update

Response 202 Accepted

{
"message": "Update initiated for 2 container(s)",
"agents_updated": 1
}

POST /containers/rollback

Trigger rollback for specific containers to their previous version.

Required scope: write or full

Request body

{ "container_ids": ["abc123"] }
Example request
curl -s -X POST -H "Authorization: Bearer $WW_TOKEN" \
-H "Content-Type: application/json" \
-d '{"container_ids": ["abc123def456"]}' \
https://watchwarden.local/api/integrations/watchwarden/containers/rollback

Response 202 Accepted

{
"message": "Rollback initiated for 1 container(s)",
"containers_queued": 1
}

Token Management API

These endpoints are used by the WatchWarden web UI to manage API tokens. They require JWT authentication (the admin login), not API token auth.

POST /api/api-tokens

Create a new API token.

FieldTypeRequiredDescription
namestringYesLabel for the token (max 128 chars)
scopesstring[]NoDefault: ["full"]. Options: full, read, write
expires_in_daysnumberNoToken lifetime in days. Omit for no expiration.

Response 201 Created

{
"id": "uuid",
"name": "Home Assistant",
"token": "ww_a1b2c3d4...",
"scopes": ["full"],
"expires_at": 1727827200000,
"created_at": 1720051200000
}
warning

The token field is returned only in this response. Store it securely — it cannot be retrieved again.

GET /api/api-tokens

List all tokens. Hashes and prefixes are never exposed.

DELETE /api/api-tokens/:id

Revoke a token immediately. Returns 204 No Content.


Security

  • Token hashed with SHA-256 before storage (high-entropy random input)
  • Hash comparison uses crypto.timingSafeEqual (constant-time)
  • Token prefixes stored for fast DB lookup, never exposed to API consumers
  • All create/revoke operations are audit-logged
  • Rate-limited at 60 req/min per IP
  • Scope enforcement on every endpoint
  • Optional expiration with expires_in_days