API keys
API keys are the credentials your automation uses to call the Evershell
control plane API. Sessions sign in humans; API keys sign in
scripts, CI runners, agents, and the evershell CLI.
Creating a key
Section titled “Creating a key”- Sign in to the console as Owner or Operator.
- Settings → API keys → New key.
- Pick a label and a permission template (see below).
- Click Create key. The next screen shows the full secret once — copy it into your secret manager or CI’s environment variables. There is no way to retrieve it later; if you lose it, revoke and create a new one.
Or via the API:
curl -X POST https://<your-slug>.evershell.ai/v1/api-keys \ -H "Authorization: Bearer <your-session-jwt>" \ -H "Content-Type: application/json" \ -d '{"label": "CI runner", "permission_set": "submit_observe"}'The response carries value — the full sk_* secret. The same
“only returned once” rule applies on the API path.
Permission templates
Section titled “Permission templates”Keys can’t pick arbitrary scopes — they pick one of three
closed-enum templates. The template determines which /v1/* routes
the key can hit. Each scope below is explained in the
permissions reference.
| Template | Permissions | When to use |
|---|---|---|
full_access | caps:write, workspace:read, workspace:write, tasks:write, audit:read | Automation that manages providers / agent roles / content packs and runs work |
submit_observe | workspace:read, workspace:write, tasks:write, audit:read | CI runners / agent runners that drive work but don’t change configuration |
read_only | workspace:read, audit:read | Monitoring, dashboards, audit shipping |
Note that tasks:write (unscoped) is granted to keys even though no
default member role holds it — keys
have no user identity to attribute the per-user :own narrowing
against, so they get the org-wide variant.
Things keys never get, regardless of template:
- Member management (
members:write) and billing (billing:write) — people-management and financial actions are human-only. - Issuing more keys (
apikeys:write) — keys can’t create more keys. New keys come from a signed-in human so the audit trail stays meaningful. - Credential management (
auth:write) — creating, rotating, or deleting the outbound credentials your agents use (OAuth connections, service accounts, third-party API keys, etc.) stays human-only. - Secret management (
secrets:write) — Vault values that get injected into outbound calls (signing keys, API tokens, custom headers) are at least as sensitive as the credentials they often hold. Same rationale: human-only.
Using a key
Section titled “Using a key”Pass the key as a bearer token in the Authorization header:
curl -H "Authorization: Bearer sk_..." https://<slug>.evershell.ai/v1/workspacesFor SSE consumers that can’t set headers (browser EventSource),
keys may also be presented in the query string:
curl "https://<slug>.evershell.ai/v1/activity/stream?api_key=sk_..."Session tokens (eyJ...) are never accepted in the query string —
URLs leak through referrer headers and server logs. The query path
only accepts sk_* keys.
A key bound to one org can’t be used against another — cross-org
requests return 403.
Revoking a key
Section titled “Revoking a key”From the console: Settings → API keys → the trash icon on the row. Confirm in the dialog.
From the API:
curl -X DELETE https://<slug>.evershell.ai/v1/api-keys/<key-id> \ -H "Authorization: Bearer <your-session-jwt>"Revocation is eventually consistent. A revoked key may continue to authenticate for a short window (typically under a minute) due to permission caching on the control plane. If you’ve leaked a key and need immediate effect, revoke and treat the window as mitigation overlap — change any downstream secret that the leaked key would have had access to as well.
Every key create and revoke lands in your org’s audit
log as api_key_created /
api_key_revoked. The detail carries the label, prefix, and
permission template — never the secret value. Actions performed
with a key are attributed to the system actor on each row; we’re
working on per-key attribution in a follow-up.