Skip to content

API

REST API under /api/v1, plus Prometheus and health endpoints. The OpenAPI 3 document is served at /api/v1/openapi.json.

Authentication

Log in to obtain a session cookie, or use an API token as a Bearer header. Tokens are created in the console under Settings → Access (or via POST /api/v1/auth/tokens, admin only) and are shown exactly once — only a keyed digest is stored. A token's scope caps its owner's role, so an admin can issue a read-only token without creating a second account:

curl -c jar -X POST http://host:8089/api/v1/auth/login \
  -H 'Content-Type: application/json' -d '{"name":"admin","password":"…"}'
curl -b jar http://host:8089/api/v1/stats

Roles: viewer (reads), editor (mutations), admin (everything). Optional TOTP 2FA; failed logins are rate-limited with exponential backoff.

Endpoints

Method Path Role Purpose
GET /stats viewer realtime counters
GET /querylog?qname=&action=&limit= viewer search the query log
GET /querylog/export viewer NDJSON export
GET/POST /rules viewer/editor list / add / remove allow-deny
POST /toggle editor global blocking on/off
POST /cache/flush editor clear the cache
POST /gravity/refresh editor re-fetch blocklists
GET /clients viewer top clients
GET /system viewer version / uptime / upstreams
GET /ws viewer WebSocket live stream (see below)
GET /metrics — Prometheus exposition
GET /healthz, /readyz — liveness / readiness

Errors

Every refusal under /api/v1 is JSON of one shape, {"error": "…"}, with the status carrying the meaning: 400 for a malformed or wrongly typed request, 401 without credentials, 403 for a role too low, 404 for an unknown id or path, 405 for a method the path does not take. The OpenAPI document declares each operation's security and parameters, and gives it a stable operationId.

Live stream

/api/v1/ws sends typed JSON frames: one hello (stats, series, recent) on connect, a query per resolved query, and a stats snapshot every two seconds. A client that cannot keep up is not buffered without bound; the server skips events for it and reports the running count in the dropped field of stats frames. The query log keeps every event.