Skip to content

Admin API — keys and models

MethodPathAuthPurpose
GET/admin/keysAdmin roleKey pools per use-case category, with masked previews and live status.
POST/admin/keysAdmin roleAdd a key. It is probed live and only stored if the probe succeeds.
DELETE/admin/keys/:idAdmin roleRemove a stored key.
GET/admin/keys/:id/metricsAdmin roleDaily usage series for one key. Accepts ?days=.
POST/admin/keys/:id/validateAdmin roleRe-probe a key on demand. Success revives a key marked dead.
PUT/admin/categories/:categoryAdmin roleSet the provider and model for one use-case category.
Terminal window
curl -s https://<your-host>/admin/keys -H "authorization: Bearer $TOKEN"

Returns the use-case categories, the provider and model each is running, and the keys in each pool with:

  • a masked preview such as AIza…3f9 — never the value,
  • live status: active, cooldown (with a deadline) or dead,
  • today’s metered usage against the slot’s configured limit,
  • which other categories hold the same physical key.
Terminal window
curl -s -X POST https://<your-host>/admin/keys \
-H "authorization: Bearer $TOKEN" \
-H 'content-type: application/json' \
-d '{"category":"evaluation","provider":"google","label":"personal key","value":"<the-key>"}'

The key is probed live before it is stored:

Probe result Outcome
Success 201, stored and immediately in rotation
Rejected (invalid, unauthorised, wrong model) 422 with a reason class. Nothing is stored
Rate limited 201 with a warning — the key authenticated, so it is stored on cooldown
Network failure Retried once, then fails closed

Failed validations are recorded in an audit trail with the masked preview only.

Terminal window
curl -s -X POST https://<your-host>/admin/keys/<id>/validate -H "authorization: Bearer $TOKEN"

Returns 200 either way with the outcome. A successful probe revives a key that was marked dead, everywhere it is pooled — this is the recovery path after fixing billing or re-enabling an API.

Terminal window
curl -s "https://<your-host>/admin/keys/<id>/metrics?days=30" -H "authorization: Bearer $TOKEN"

A daily series of requests, successes, rate limits, auth failures and token totals, plus combined totals across every record holding the same physical key. These are Watcher’s own counts — an estimate, not a provider bill.

Terminal window
curl -s -X DELETE https://<your-host>/admin/keys/<id> -H "authorization: Bearer $TOKEN"
Terminal window
curl -s -X PUT https://<your-host>/admin/categories/evaluation \
-H "authorization: Bearer $TOKEN" \
-H 'content-type: application/json' \
-d '{"provider":"google","modelId":"gemini-2.5-flash"}'

Models come from a curated allowlist per category; anything else is rejected. The change is probed with a live call first. With no active key to probe with, it is saved and flagged unverified rather than refused.

See Models and keys for what each category does.

  • Plaintext keys are never returned by any route — only masked previews.
  • Keys are encrypted at rest; the master key exists only in the environment.
  • Every write is audited with the masked preview, never the value.
  • Probe targets are fixed per provider and can never be pointed at a URL you supply.