Skip to content

Audit & stats endpoints

Read-only endpoints the SPA hits for the dashboard. All tenant-scoped.

GET /audit?limit=N

Recent decisions, newest last in the array (SPA reverses to newest-first). limit defaults to 100, max 10000.

GET /events (SSE)

text/event-stream. One data: line per new decision. Caddy is configured with flush_interval -1 so chunks aren't buffered.

GET /stats?window=N

Aggregates over the last N seconds. Default 3600.

json
{
  "by_action":        { "allow": 142, "redact": 8, "deny": 3 },
  "by_rule":          { "redact_pii_on_egress": 8, ... },
  "by_agent_total":   { "support-bot-v2": 1000, ... },
  "by_agent_blocked": { ... },
  "timeline":         [ { "ts": 1715520000, "allow": 12, ... }, ... ]
}

GET /vocabulary

Distinct values observed in the audit data — used to populate filter autocomplete on Live Traffic.

json
{
  "agents":  ["support-bot-v2", "qa_eval_loop", ...],
  "actions": ["http_request", "tool_call", "llm_prompt"],
  "hosts":   ["api.anthropic.com", "api.openai.com", ...],
  "tools":   ["shell.exec", "fs.read", ...],
  "models":  ["claude-sonnet-4-6", "gpt-5-mini", ...]
}

GET /audit/export?format=csv|json&window=N

Same data as /audit but as a streaming download with Content-Disposition set. format=csv is the format the dashboard's Export CSV button uses; format=json is the same data as the live audit endpoint.

GET /principals/summary

Per-principal-type rollups for the Spend KPI:

json
{
  "user":    { "count": 12, "names": [...], "cost_usd": 124.18, "tokens": 4_120_000, "calls": 18_300 },
  "agent":   { "count":  8, "names": [...], "cost_usd": 218.40, "tokens": 8_440_000, "calls": 21_900 },
  "unknown": { "count":  0, ... }
}

Documentation for kilasec — the AI Agent Firewall.