Skip to main content

API Keys

DriftWise uses API keys to authenticate non-interactive requests (CI pipelines, automation, the DriftWise operator). Keys are scoped to a single organization and prefixed with dw2_. For endpoint shapes, see the api-keys tag of the API reference.

Creating a key

Key creation lives on the Settings page of the dashboard — click Create API Key, give it a name, pick scopes, and copy the raw key that appears once. DriftWise stores only an HMAC-SHA-256 hash of the key under an environment-held pepper, so a database-only leak leaves attackers with opaque bytes they cannot authenticate with.

Programmatic creation is also available via the API, but the resulting raw key is shown exactly once in the raw_key field of the response and is never retrievable afterward — list endpoints always return it as empty.

Key-creation is gated to owner/admin roles. API keys inherit the creator's write-scoped access, so allowing a viewer or member to mint a key was an escalation path: the key would outlive any role demotion and continue to grant whatever the key's scope permitted.

Scopes

Scopes gate what HTTP methods a key can invoke:

  • read — GET/HEAD/OPTIONS only
  • write — full mutation access (within the role gates that also apply per-handler)
  • Empty or wildcard — unrestricted (legacy back-compat)

Scopes are validated at create time, not at first use. A typo like ["admin"] (intending ["write"]) fails fast with 400 instead of silently rejecting every subsequent request.

Using your key

Pass the key in the X-API-Key header or as Authorization: Bearer dw2_.... Both work on every endpoint. Scripts typically use X-API-Key because it doesn't collide with OIDC Bearer tokens on the same client.

The analyze endpoint, for example, accepts a Terraform plan JSON in the request body and returns an LLM-generated risk narrative. See the drift tag of the API reference for the full request/response shape.

Revocation

Revocation is OIDC-only — API keys cannot revoke other API keys. That's a lateral-movement defense: a compromised write-scoped key that could revoke every other key would let an attacker lock out the real owners without touching any human-attributable surface.

Revocation propagates across backend pods within one Redis round-trip via the shared revocation store. On Redis failure it falls back to the 30-second cache TTL floor on each pod — a compromised key remains usable on other pods for up to 30 seconds after revocation.

Already-revoked keys return 404 on a second revoke attempt — indistinguishable from "wrong key ID," which is deliberate. Both cases mean "there's nothing here to revoke."

Plan limits

The number of active keys per org is capped by plan tier (Free: 2, Team: 10, Enterprise: unlimited). Exceeding the limit returns 402 Payment Required with the canonical PaymentRequiredResponse body. See Plans & Billing for the limit structure.

Best practices

  • Rotate regularly. Aim for quarterly rotation at minimum; monthly if CI keys have write scope.
  • Store in a secret manager. Never commit keys to the repo. Environment variables in CI (GitHub Actions secrets, GitLab CI variables, Vault bindings) are the minimum.
  • Scope narrowly. If a CI job only reads scan results, use a read key. A write-scoped key left behind by a deprovisioned pipeline is the classic audit finding.
  • Audit via admin_audit_log. Every create and revoke is audited with the actor's user ID and the key prefix. Incident response can always answer "who created this key, when."