Authentication
Verdifax authenticates API callers via a single header. Keys are provisioned out-of-band and shown to the operator exactly once.
Header
X-Verdifax-Key: vfx_<24-byte-random-hex>
Every authenticated endpoint accepts the same header. /health is public.
Two modes
Open mode — when no API keys exist in the database (a fresh deploy, before any key has been provisioned), every authenticated endpoint admits the caller as anonymous (api_key_id = 0). This keeps the docker quickstart trivial.
Locked mode — once any key exists, the API server enforces the header. Calls without a valid X-Verdifax-Key get 401. Run history is scoped to the key that produced it: /runs only returns runs owned by the calling key, and /runs/{id} 404s if the key didn't own that run.
Provisioning a key
curl -s -X POST http://localhost:9090/admin/keys \
-H "Content-Type: application/json" \
-d '{"name":"compliance-team-2026"}' | python3 -m json.tool
{
"ok": true,
"id": 1,
"name": "compliance-team-2026",
"secret": "vfx_a1b2c3d4...",
"hint": "Store this secret now — it will never be shown again."
}
The server stores only sha256(secret). Lose the secret and you must revoke + reissue.
Listing keys
curl -s http://localhost:9090/admin/keys \
-H "X-Verdifax-Key: vfx_..." | python3 -m json.tool
Returns names, creation timestamps, last-used timestamps, run counts, and revocation status — never the secrets.
Revoking a key
curl -s -X DELETE http://localhost:9090/admin/keys/1 \
-H "X-Verdifax-Key: vfx_..."
Revocation is immediate. Subsequent calls with that key get 401.
Rate limiting
Every authenticated endpoint is rate-limited at 100 requests/minute per key by default (configurable via --rate-limit). Anonymous callers in open mode are limited per remote address.
