API Reference

Audit Log

Query the org-scoped audit trail — who did what, when

Audit API

State-changing API calls are recorded in the audit_log table — app operations, cluster registrations, secret-store changes, webhook events, team creation, remediation approvals. Entries are org-scoped and immutable.

Endpoints

List Audit Entries

GET /api/v1/audit

Permission: audit:read (every org role except Viewer has it).

Query Parameters

ParameterTypeDescription
limitintMax results (default 50, max 200)
offsetintPagination offset

There are no actor/action/resource/from/to filters — the endpoint only pages. Filtering server-side is a good first issue; until then, page and filter client-side.

Response — 200 OK

{
  "entries": [
    {
      "id": 182,
      "created_at": "2024-01-15T10:30:00Z",
      "user_id": "usr_01H8X2K3",
      "action": "app.sync",
      "resource_type": "app",
      "resource_id": "my-app",
      "resource_name": "my-app",
      "details": { "operation": "Sync", "revision": "a1b2c3d4e5f6" }
    },
    {
      "id": 181,
      "created_at": "2024-01-15T10:28:15Z",
      "user_id": "",
      "action": "incident.emit",
      "resource_type": "incident",
      "resource_name": "deploy/my-app",
      "details": { "title": "…", "severity": "warning" }
    }
  ],
  "limit": 50,
  "offset": 0
}

Fields are ordered newest-first. user_id is empty for system/caller-less actions (webhook deliveries, tag poller).

Audited Actions

From the handlers (server/internal/handler) — the actual values emitted:

ActionEmitted by
app.createPOST /apps
app.deleteDELETE /apps/{ns}/{name}
app.sync / app.deploy / app.rollback / app.restart / app.approveoperation endpoints
app.scale / app.freeze / app.unfreezeworkload controls
app.promote / app.clone / app.adoptpro endpoints
cluster.register / cluster.update / cluster.remove / cluster.test/clusters
cluster.shellPOST /clusters/{name}/shell
team.createPOST /teams
webhook.create / webhook.delete / webhook.test/webhooks
incident.emitPOST /incidents
secretstore.create / secretstore.update / secretstore.delete / secretstore.test/secret-stores
registry.create / registry.update / registry.delete / registry.test/registries
remediation.approve / remediation.reject/remediations (MCP)
apikey.create / apikey.revoke/auth/api-keys

Example

Paginated export

offset=0
while true; do
  curl "http://localhost:8080/api/v1/audit?limit=200&offset=$offset" \
    -b cookies.txt > "audit-$offset.json"
  count=$(jq '.entries | length' "audit-$offset.json")
  [ "$count" -lt 200 ] && break
  offset=$((offset + 200))
done

Retention

📋 Not implemented — entries accumulate indefinitely; there is no TTL or AUDIT_RETENTION_DAYS setting.

Access Control

  • GET /audit requires audit:read — held by org Owner, Admin, and Contributor; Viewer cannot read it
  • Entries are immutable — no API can edit or delete them
  • Entries are org-scoped — callers only see their own org's log

On this page