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 namesserver:admin-user:createwhen it does not.<name>is for you, so the list says which system holds the key.--scopeisall:readonlyorall:readwrite, and defaults toall:readonly.--expires-attakes a date and time, e.g."2026-12-31 23:59:59". Without it the key never expires.--jsonprints 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.
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.
| Scope | Label on the page | Allows |
|---|---|---|
all:readonly | All (read-only) | Every GET of the server API. |
all:readwrite | All (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.
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.