Skip to main content

API Keys

A server API key is the credential of the Server API. It is a bearer token, espat_<id>_<secret>, that acts as the admin user who owns it: what that admin user may do, the key may do, within its scope. It is the only credential the API accepts, and it is not held to its admin user's allowed IP addresses; Allowed addresses says why.

Keys are on Integrations › API Keys in the admin app, and in elpanctl as server:api-key:*. The page lists every key of the server, whoever made it; a key created on the page belongs to the admin user who created it, and one created on the command line belongs to the admin user you name.

Create a key​

elpanctl server:api-key:create <username> <name> [--scope=<scope>]... [--expires-at=<time>] [--json]
  • <username> is the admin user the key acts as. It must exist (Admin Users); the command names server:admin-user:create when it does not.
  • <name> is for you, so the list says which system holds the key.
  • --scope is all:readonly or all:readwrite, and defaults to all:readonly.
  • --expires-at takes a date and time, e.g. "2026-12-31 23:59:59". Without it the key never expires.
  • --json prints the result as one JSON object, for a script that saves the token.

The command prints the key's id, its owner, its scopes, its expiry and the token, and warns that the token is not shown again. On the page, Create API Key asks for the same name, scopes and expiry, and shows the token once, on the list, after the key is made.

The token is shown once

Put it in the system that will use it right away. Afterwards the list shows only the start of the secret. A token you lost is a new key; a token that leaked is a revocation, below.

Scopes​

Admin authority is flat: there are two scopes and no per-family ones.

ScopeLabel on the pageAllows
all:readonlyAll (read-only)Every GET of the server API.
all:readwriteAll (read and write)Everything.

Write access includes read access. Every operation that changes something, from suspending an account to starting a backup, needs all:readwrite; a read-only key gets 403 from it.

The default is read-only

server:api-key:create grants all:readonly unless you pass --scope. A key for a system that creates accounts (Billing systems) is created with --scope=all:readwrite, or it fails at its first write.

Status, expiry and last use​

A key is Active, Expired or Revoked. An expired or revoked key is refused like a wrong one, with 401. An expired key stays in the list; a revoked one stays for a week, then Housekeeping removes it.

The list shows each key's last use. The server records it at most once every ten minutes, so the time is the start of a key's recent activity, not its latest request.

elpanctl server:api-key:list [--format=tsv|jsonl] [--no-header]

lists every key with its id, name, admin user, scopes, the start of its secret, status, creation, expiry and last use. --format=tsv and jsonl are for scripts; the default is a table.

Give every key an expiry, and revoke one that nobody has used for months. A key with all:readwrite and no expiry is as powerful as its owner's sign-in, and is asked no second step.

Revoke a key​

elpanctl server:api-key:revoke <id> [--force]

or Revoke on the key's row. Revocation is immediate and permanent: the next request with that token is refused, and the key is listed as revoked for a week. --force skips the confirmation, for a script. The id is in server:api-key:list.

A key is also gone when its admin user is deleted: server:admin-user:delete and the Delete on the Admin Users page take the user's keys with them.

Creating and revoking a server key is an apikey.created or apikey.revoked event on the server's Webhooks.

Keys without an owner​

A key made before keys belonged to an admin user has no owner, and the API refuses it with a 401 problem document titled "Server API key has no owner". Such keys show a No owner badge on the page, and server:api-key:list counts them in a warning and shows (none: refused) in the Admin User column.

The fix is part of every upgrade: elpanctl deploy:run, which the package runs after an update (Updates), gives every such key to the admin user root, keeping its token, id and scopes, so the system that holds the token keeps working. root is created for it when missing. If you would rather not wait, create a replacement with server:api-key:create <username> <name> --scope=all:readwrite and revoke the old one.