An API key is the credential an executor uses to authenticate with the control plane. Keys are scoped to an organization: a key issued under org A cannot be used to register an executor under org B. Every key is created with the executor key type — the same backend mutation is used by the Connect executor wizard and by the API keys page in the Dashboard. There is no separate “personal” key type.Documentation Index
Fetch the complete documentation index at: https://docs.novacula.io/llms.txt
Use this file to discover all available pages before exploring further.
Lifecycle at a glance
Five operations, performed from API keys in the Dashboard:| Operation | When | Result |
|---|---|---|
| Create | Bringing a new executor online | New active key; secret shown once |
| Rotate | Refreshing credentials on schedule, or after suspected leak | New active key issued, old key revoked atomically — secret shown once |
| Revoke | Decommissioning an executor or taking a key offline | Key flips to revoked; row stays for history |
| Delete | Cleaning up an already-revoked key | Row removed permanently |
| View | Auditing what’s in use | List shows status, used-by executors, last-used time |
Create a key
Open API keys → Create API key:- Name — 1–32 characters. Shown in the key list and audit log. Pick something descriptive:
prod-cluster-1-operator,eu-bare-metal-3. - Expires in — optional date. If blank, the server applies a default TTL of one year.
How keys flow through the platform
- The executor presents the key on every
syncExecutorcall. - The
AuthGuardin the control plane validates the key against the better-auth executor key type, liftsactiveOrganizationIdfrom the key’sreferenceId, and proceeds. - The bound key’s
lastRequesttimestamp is updated on every successful verification. - The first time a new key is presented, the resolver creates the
Executorrow (1:1 with the key viaExecutor.apiKeyId @unique) and emits theexecutor.connectedevent.
List
The list page renders every key in the active org:| Column | Content |
|---|---|
| Name | User-supplied label; key id shown underneath in monospace muted text |
| Status | active / revoked / expired |
| Used by | Top two executors by lastUsedAt, plus +N for the rest |
| Created | Datetime |
| Last used | Relative; never if the key has never been presented |
| Actions | Dropdown — Rotate / Revoke / Delete (Delete enabled only when the row is already revoked) |
Rotate
Rotation issues a replacement key and revokes the old one in the same flow. The new key’s name is auto-derived by appending aYYMMDD suffix to the previous name (e.g. prod → prod 260513), trimmed to stay within the 32-char limit.
The new secret is shown once in the same one-shot disclosure dialog as create. The previous row flips to revoked and the new row appears as active.
Rotation is the only way to extend a key’s TTL — expiresAt cannot be edited post-create. If a key is approaching expiry, rotate first, propagate the new value to the executor, and then delete the revoked old row.
The previous secret stays valid for the microseconds between create and revoke; there is no overlap window an executor would notice.
Revoke
Revoke flips the row’senabled flag to false. The next request from the executor presenting that key fails authentication; the row stays in the list with the badge flipped to revoked so usage history is preserved.
Revoking does not affect the bound Executor row — the row remains, but its next poll fails auth until a new key is issued. To revoke a specific executor’s bound key from its detail page, see Revoke executor access.
There is no reactivation. Once revoked, the only forward path is delete + create a new key.
Delete
Permanently removes the row from theapikey table. Disabled on active and expired rows — revoke first.
Once deleted, the previously-bound Executor row loses its credential through the Executor.apiKeyId relationship and the Used by column for this key is gone with the row.
Permissions
- Create / rotate / revoke / delete: owners and admins.
- List + read last-used: any org member.
- The full plaintext key is shown only at creation time and never re-displayed; even owners and system admins cannot read an existing key.
Best practice
- Issue one key per executor so revoking a single executor doesn’t affect others.
- Set an expiry for short-term or contractor-issued keys.
- Rotate any key that’s been seen on a developer laptop or in a chat thread, even if you can’t prove it leaked.
- Use revoke before delete when decommissioning an executor — gives you a moment to confirm the right key is being retired.