Skip to main content

API keys

The /keys page lists every key minted under your tenant — across both modes (live / test) and both types (secret sk_* / public pk_*) — and lets authorized roles mint or revoke them.

Key types

The environment and the type are both encoded in the key string. There are no separate sandbox URLs — api.drukverify.com accepts both modes; the gateway routes based on the prefix.

PrefixTypeWhere it livesUsed for
dv_sk_live_…secretServer-side only — never ship to a mobile appMinting session tokens, calling admin endpoints, server-side OCR / face / liveness calls
dv_sk_test_…secretServer-side, dev environmentsSame as above but routes to test-mode data — no PII retention, separate quotas
dv_pk_live_…publicEmbeddable in your mobile app binaryThe apiKey field on EkycConfig in the Flutter SDK; identifies the tenant + mode without granting privileged access
dv_pk_test_…publicEmbeddable, dev environmentsSame as pk_live but routes to test mode

The pk_ keys are deliberately safe to ship in app stores. Anything they could do, an unauthenticated user could do anyway — they identify the tenant for routing and rate-limiting, not for authentication.

Role gates

The mint and revoke buttons are visible only to roles that can use them. The same gates are enforced at the API layer (POST /v1/keys, DELETE /v1/keys/:id), so a manually-crafted request from a non-permitted role still gets a 403.

Actionadmindeveloperviewer
List keys
Create dv_*_live_*
Create dv_*_test_*
Revoke any key

Creating a key

Click Create key and fill in:

  • Typesk or pk.
  • Modelive or test.
  • Name — free-form, optional. Names appear in the audit log and on the keys list — helpful when you have keys for multiple environments or services. Example: "demo-backend (staging)" or "iOS app store build".

After you submit, the full key value is displayed exactly once in a confirmation modal. Copy it into your secrets manager / .env before dismissing — there is no way to recover the plaintext later. The list view only ever shows the prefix (dv_sk_live_aBc…).

Revoking a key

Click the Revoke action on a row. Revocation is immediate — any request using the key from the next round-trip onward gets a 401 with error.type = "revoked_key". The row stays in the list (greyed out, "Revoked" badge) for audit; it's never deleted.

There's no un-revoke. Mint a new key if you change your mind.

Last-used tracking

Each row shows Last used — the timestamp of the most recent successful authentication with that key. Useful for two things:

  1. Identifying dead keys ("haven't been touched in 90 days — probably safe to revoke") for credential hygiene.
  2. Spotting suddenly-quiet keys ("our backend's sk_live hasn't been used in 6 hours and we're not in a maintenance window — what's wrong?").

The field is updated every time a request authenticates with the key, with a small delay to avoid hammering the database on hot paths.

Audit trail

Every key creation and revocation produces an audit event visible on the audit log. The event records who did it (dashboard user id + email), when, and from which masked IP. Useful for after-the-fact "who minted that key in the middle of the night?" questions.