Documentation

API key lifecycle

How to mint, store, rotate, and revoke Prometheus API keys — with the one-time copy semantics called out up front.

API keys are the only credential that lets the MCP server and CI jobs talk to the indexer worker. They are scoped to a single tenant, hashed at rest, and shown in cleartext exactly once. This page walks the full lifecycle.

Anatomy of a key

prom_live_8f3a1c2b9d4e5f6071829a3b4c5d6e7f0a1b2c3d4e5f6071
└──┬──┘└────────────────── 32-byte secret ──────────────────┘
   │
   └── environment prefix: prom_live_ (prod) or prom_test_ (staging)
  • 32 bytes of cryptographic randomness, base16-encoded.
  • Hashed with Argon2id before lookup. The cleartext never hits the database after issuance.
  • Per-tenant. A key never carries authority over a different tenant, no matter what the calling code sets.

1. Create

app.prom.codes/api-keys  →  Create key

Owner or admin role required. Pick a human-readable label (e.g. ci/github-actions, claude-desktop/laptop) so the audit log and revocation list stay legible. Submit, and the new key appears in a one-time reveal panel.

The corresponding api_key.create row lands in /app/audit immediately, with the actor, the new key's id, and the label you chose.

2. Use

Pass the key as a bearer token to every worker call and as the PROMETHEUS_API_KEY environment variable to every MCP server process:

curl -H "Authorization: Bearer prom_live_..." https://api.prom.codes/healthz
{
  "mcpServers": {
    "prometheus": {
      "command": "npx",
      "args": ["-y", "@prometheus/context-mcp@latest"],
      "env": {
        "PROMETHEUS_API_KEY": "prom_live_..."
      }
    }
  }
}

The worker reads the key on every request, hashes it, and looks up the tenant. There is no session — every call is independently authenticated.

3. Rotate

Rotation is just "create new, switch over, revoke old":

  1. Create a new key with a label that includes today's date.
  2. Roll every consumer (CI, MCP hosts, ad-hoc scripts) to the new key. Keys are stateless, so the cutover can be staggered.
  3. Verify the new key is taking traffic by watching api.prom.codes logs (visible in /app/audit under api_key.use once Phase 3 ships per-key usage rows).
  4. Revoke the old key. From this moment on, any leftover consumer gets a 401.

There is no automatic rotation schedule today. We recommend rotating on a quarterly cadence and immediately on personnel change or suspected compromise.

4. Revoke

app.prom.codes/api-keys  →  Revoke

Revocation is immediate. The worker re-checks the key on every request, so the next call after the revoke returns 401 UNAUTHORIZED. A revoked key cannot be reactivated — mint a new one if you need to undo the action.

The audit log records api_key.revoke with the actor and the key id. The key's cleartext is never logged.

What to do on a leak

  1. Revoke immediately — do not wait for the rotation step.
  2. Mint a fresh key with a clearly different label so post-mortem diffing is easy.
  3. Walk the audit log for the leaked key's id — any api_key.use rows (Phase 3) tell you whether the key was exercised between leak and revocation. If you suspect indexed data is now in the wrong hands, mail security@prom.codes so we can help you assess blast radius.
  4. Update your secret store so the leak does not recur. We recommend direnv, 1Password, or your CI's encrypted variables over plain .env files.

Naming conventions that pay off

PatternExampleWhy
Purpose / hostci/github-actionsLets you revoke a single CI without breaking laptops.
Operator + datehans/2026-05Trivial to age out at rotation.
Workspace hintmonorepo/indexerUseful once per-workspace keys ship in Phase 4.