Skip to main content

API Keys

The API Keys view lets Lumio operators inspect and manage any account's or user's API keys for support and incident response - listing keys, editing a key's label and scopes, rotating a leaked secret, and revoking a key. It covers both key kinds: personal user API keys (lm_usr_, stored in api_keys) that carry a single member's identity, and account service keys (lm_svc_, stored in account_service_keys) that belong to the account and outlive the member who minted them.

This is the operator surface, gated on the admin-scope account-apikeys:* family. It is distinct from the account-scope apikeys:* family a member uses to manage their own keys under Dashboard → API Keys - holding one never grants the other.

Where to find it

There is no standalone sidebar entry. The API-keys panel is reached in two places:

  • Admin → Accounts → account detail - lists both kinds for that account: its members' personal lm_usr_ keys and the account's lm_svc_ service keys.
  • Admin → Users → user detail - lists that user's personal lm_usr_ keys only (a service key has no owning user).

Quick start

  1. Open Admin → Accounts, drill into an account (or Admin → Users → a user), and scroll to the API Keys panel.
  2. Each key renders as a card showing its kind badge (personal / service), label, non-secret prefix, scopes, and created / last-used dates. The secret itself is never shown.
  3. Use Edit to change a key's label and scopes, Rotate to regenerate its secret, or Revoke to delete it.
  4. Rotate reveals the new full key exactly once - copy it and hand it back to the account. Everything else on the card is non-secret.

Detailed walkthrough

API Keys panel

One card per key. Each card shows:

  • Kind - a personal (lm_usr_) or service (lm_svc_) badge.
  • Label - the human-friendly name, with the key's non-secret prefix in monospace.
  • Scopes - the key's permission list, as chips.
  • Owner / account - for a personal key, the owning user; the account it is bound to for both kinds.
  • Created and Last used - dates; "Last used" is omitted when the key has never been used.

Card actions are each gated on their own permission: Edit (account-apikeys:edit), Rotate (account-apikeys:rotate), Revoke (account-apikeys:delete).

Editing a key (label + scopes)

Edit (gated on account-apikeys:edit) updates a key's label and scope list. Scope edits are validated against the assignable-scope registry for the key's kind (the same ZAF-1170 registry the dashboard picker uses): an unknown, deny-listed, or user-scoped-on-a-service-key scope is rejected before the write.

An operator can never push a key above its own principal:

  • For a personal key, the scopes are additionally capped to the key owner's own grantable permissions - an operator cannot grant a member's key a permission the member does not hold.
  • For a service key, the account is the principal, so the ceiling is the registry (minus the deny-list).

Rotating a key

Rotate (gated on account-apikeys:rotate) regenerates the key's secret in place: the key id, label, and scopes are unchanged, but the old secret stops working immediately and a new full key is returned exactly once. The plaintext is shown in a one-time reveal - copy it and hand it back to the account through a secure channel. It is never shown again, never returned by the list, and never logged.

Revoking a key

Revoke (gated on account-apikeys:delete) hard-deletes the key row. Any subsequent request using that key returns 401. The delete is idempotent - revoking an already-gone key resolves to the same not-found result rather than erroring.

Permissions

The panel is gated on the admin-scope account-apikeys:* family - admin-scope (global) permissions checked against the caller's admin role, seeded to system_admin, and enforced by AdminPermissionGuard (GraphQL) / require_admin_permission (REST). They are not the account-scope apikeys:* permissions a member uses on their own keys.

ActionPermission
View any account's / user's keysaccount-apikeys:read
Edit a key's label + scopesaccount-apikeys:edit
Rotate a key's secretaccount-apikeys:rotate
Revoke (delete) a keyaccount-apikeys:delete

Dashboard entry requires admin:access. System admins implicitly hold every account-apikeys permission.

API

{kind} is personal (lm_usr_) or service (lm_svc_); the GraphQL enum ApiKeyKind uses PERSONAL / SERVICE.

UI actionGraphQLREST
List an account's keys (both kinds)adminAccountApiKeys(accountId)GET /v1/admin/accounts/\{account_id\}/api-keys
List a user's keys (personal only)adminUserApiKeys(userId)GET /v1/admin/users/\{user_id\}/api-keys
Edit a key (label + scopes)adminUpdateApiKey(kind, id, label, permissions)PATCH /v1/admin/api-keys/\{kind\}/\{id\}
Rotate a key's secretadminRotateApiKey(kind, id)POST /v1/admin/api-keys/\{kind\}/\{id\}/rotate
Revoke a keyadminDeleteApiKey(kind, id)DELETE /v1/admin/api-keys/\{kind\}/\{id\}

The two rotate results return { key, apiKey } (personal) / { key, serviceKey } (service) - the full key string plus the updated non-secret metadata. Every operator action emits a system-scope audit event (system:api_key_updated / system:api_key_rotated / system:api_key_revoked) with the operator as the actor; these rows never surface in the target account's or user's own audit log.

Tips & gotchas

  • The rotated secret is shown once. The card only ever displays the non-secret prefix; a secret lost after the one-time reveal cannot be recovered - rotate again.
  • Operator edits cannot escalate a key. A personal key stays capped to its owner's permissions and a service key to the account's registry ceiling, so an operator can never grant a scope the principal itself does not hold.
  • account-apikeys:*apikeys:*. The former is admin-scope (this page); the latter is account-scope (the member's own Dashboard → API Keys). Holding one does not unlock the other.
  • Revoke is idempotent and has no confirmation. One click deletes the key.
  • Personal keys carry a member identity; service keys do not. That is why the user-detail panel lists only personal keys, and why service-key scopes are capped to the account rather than a user.
  • Accounts - the account-detail page that surfaces this panel
  • Users - the user-detail page that surfaces personal keys
  • System Keys - internal service-to-service keys (lm_sys_), a separate operator surface
  • Audit Log - the system:api_key_* operator events these actions emit
  • Permissions - the account-apikeys:* family