API keys
Credentials for automation, scoped to the permissions you grant.
View as MarkdownAn API key is a machine credential for a workspace, carrying a subset of the permission catalog.
Use one in CI rather than your own session: it is scoped to exactly what you grant, and revoking it does not sign you out.
Creating
sctl apikey create ci-backups --perms backups:read,backups:writeCreated key "ci-backups" (7c1e...).
Secret (copy now, not shown again):
sk_live_...
Permissions: backups:read, backups:write--perms is required and takes a comma-separated list of permission slugs. The command is
also available as sctl key.
The secret is shown once and is never stored by us. We keep the key's identifier so we know which key is calling. If you lose it, create a new key and revoke the old one.
Listing and revoking
sctl apikey list
sctl apikey revoke <key-id>NAME ID PERMISSIONS
ci-backups 7c1e... backups:read,backups:write
monitoring 9a3f... backups:read,artifacts:readChoosing permissions
Grant the narrowest set that does the job. The distinction that matters most:
| Permission | Lets the key |
|---|---|
backups:read | See that a backup exists, and its configuration |
backups:write | Create, configure, trigger, pause and delete |
artifacts:read | See artifacts, sizes, checksums and key IDs |
artifacts:download | Read your data |
A monitoring key needs backups:read and artifacts:read. It does not need
artifacts:download, and giving it that turns a monitoring credential into an exfiltration
one.
Shapes worth copying:
| Purpose | --perms |
|---|---|
| Apply manifests from CI | backups:read,backups:write |
| Trigger a backup after a deploy | backups:read,backups:write |
| Monitor without touching | backups:read,artifacts:read |
| Restore automation | backups:read,artifacts:read,artifacts:download |
What a key cannot hold
Some permissions are refused on any machine credential, whatever you ask for.
| Refused | Why |
|---|---|
workers:* | A compromised key could mint worker credentials |
api-keys:* | One leaked key could mint more, and revoking the original would not revoke what it made |
billing:* | The workspace's cards |
destinations:write | Linking a bucket hands over a long-lived S3 key pair |
connections:write | The OAuth flow ends at a browser consent screen a machine cannot complete |
artifacts:confirm | Worker-only. That is a worker's signal about its own work |
Asking for one fails with 422 naming the slug. Creating a workspace is also refused, since
that requires a human principal.
Using a key
There is no separate mode. The key is a bearer credential exactly like a session token, so it goes where the session token would:
export SCTL_ACCESS_TOKEN='sk_live_...'
export SCTL_WORKSPACE_ID='4b7e1d90-...'
sctl backup list$env:SCTL_ACCESS_TOKEN = 'sk_live_...'
$env:SCTL_WORKSPACE_ID = '4b7e1d90-...'
sctl backup listBoth variables are required. A machine never ran sctl workspace switch, so nothing has
told it which workspace to act on. SCTL_WORKSPACE_ID comes from sctl workspace list.
Or call the API directly:
curl -fsS https://api.saved.sh/v1/backups \
-H "Authorization: Bearer $SCTL_ACCESS_TOKEN"Storing one
| Do | Do not |
|---|---|
| GitHub Actions secrets, GitLab CI variables | Commit it |
| Vault, AWS Secrets Manager, 1Password | Bake it into an image |
| An environment variable read at runtime | Echo it in CI output |
On Linux and macOS, a leading space before export keeps the line out of shell history in
most shells. Better still, read the key from a secrets manager rather than typing it.
Rotation
Zero-downtime order:
- Create the new key with the same permissions.
- Deploy it everywhere the old one is used.
- Confirm traffic works on the new key.
- Revoke the old one.
sctl apikey create ci-backups-2026-08 --perms backups:read,backups:write
# deploy, verify, then:
sctl apikey revoke <old-key-id>Revocation is not instantaneous. Validations are cached for about a minute, so a revoked key can keep working briefly. Treat it as effective within a minute, and if the key leaked, also rotate anything it could reach.
Keys outlive people
A key belongs to the workspace, not to whoever created it, so removing a member does not revoke their keys. That keeps automation running when someone leaves, and it means offboarding has a second step:
sctl apikey listName keys after their use rather than their creator (ci-deploy, monitoring, not
sams-key), so that review is possible at all.
Limits
| Plan | API keys per workspace |
|---|---|
| Trial | 2 |
| Paid | 20 |