Admin
API Keys
Minting, rotating, and revoking app keys and per-agent keys.
Alter recognizes four key shapes. Root and agent keys can be created in the developer portal; derived keys are programmatic only.
| Prefix | Used by | Where it’s minted |
|---|---|---|
alter_rk_… (runtime) | Backend services using the App SDK class | App → API Keys, key type runtime (the default; CLI: alter keys mint) |
alter_ak_… (agent) | Agent-typed key that is not linked to any managed agent, so it cannot use connections delegated to an agent or secrets bound to one. For an AI agent, use its per-agent key (below). | App → API Keys, key type agent (CLI: alter keys mint --key-type agent) |
alter_dk_… (derived) | Short-lived, scope-narrowed sub-keys for plugins or tool calls | Programmatic only via app.keys.derive() |
alter_key_… (legacy) | Per-agent keys bound to one managed agent: the key an AI agent uses with the Agent SDK class | Returned by alter agents create; more from App → Agent Identity → <agent> → API keys (CLI: alter agents mint-key) |
Per-agent keys still mint with the legacy alter_key_… prefix today; the prefix does not indicate whether the key is an app or an agent key. App keys minted before the scoped formats also carry that prefix, and like every key created before the September 2026 key-security upgrade they can no longer authenticate — see Keys created before the September 2026 upgrade.
Every secret on this page is shown once and cannot be retrieved later. For where each one should be kept, and what you are responsible for, see Your Credentials.
Every key authenticates the same way — the SDK handles signing and presentation transparently. The wire protocol is identical; the difference is which principal the backend resolves the call to.
App keys
Section titled “App keys”The default key for backend code that calls third-party APIs through Alter. One per app is enough for most products.
For PAT-authenticated CLI automation, the key routes enforce these scopes:
| Operation | PAT scope |
|---|---|
| List or show key metadata | dashboard_keys:read |
| Create, rotate, or rename | dashboard_keys:write |
| Revoke | dashboard_keys:admin |
The PAT owner must still be a current organization admin to create or rotate a key. These dashboard scopes are separate from the app-key action scopes used by app.keys: derivation requires keys:derive, while programmatic rotation and revocation require keys:admin for the target key.
Open API Keys and select Create key. The plaintext is shown once. Store it in a secret manager and revoke if it’s lost.
Every app key has a finite expiration. The create form defaults to the organization’s configured Default key TTL (days) (90 days on a new organization); operators can choose a preset or any custom whole-day duration up to Maximum key TTL (days) (365 days on a new organization). Relative durations are resolved from the backend’s clock, so an exact maximum is not rejected because the browser clock differs. CLI and JSON callers get the same default when both expiration fields are omitted or null. Old rows that predate the finite-TTL policy are labeled No expiration (legacy key) rather than being presented as a supported mint option.
Rotate
Section titled “Rotate”To rotate without downtime:
- Mint a new key.
- Deploy it to the running service.
- After confirming the new key is in use (Audit Logs → Access & Requests → By Agent, then select the key-prefix chip), revoke the old one.
alter keys rotate performs the same exchange in one step: the new plaintext is returned once, the app-key successor receives a fresh lifetime from the organization’s current Default key TTL (days), and the old key remains valid for a 30-day overlap window unless it is revoked sooner. A key shown as No expiration (legacy key) predates the September 2026 key-security upgrade and cannot be rotated: create a new key instead (details). Programmatic app.keys.rotate(key_id=...) applies the same finite-lifetime rule, uses a configurable overlap of 0–30 days, and defaults to 7 days. Managed-agent keys retain their separate agent lifecycle when rotated.
Revoke
Section titled “Revoke”API Keys → <key> → Revoke. Effective immediately. The next call with the revoked key fails with key_revoked (KeyRevokedError in both SDKs), and the key remains listed with a revoked status.
Keys created before the September 2026 upgrade
Section titled “Keys created before the September 2026 upgrade”In September 2026 Alter changed how it stores and verifies API keys. Every key (and every personal access token) created before that upgrade can no longer authenticate, because Alter no longer holds anything that can recognise it. Such a key:
- fails every call with
invalid_key(InvalidKeyErrorin both SDKs). The error’shintexplains that keys created before the upgrade must be replaced; the answer is deliberately the same as for a mistyped key, so it never confirms whether a particular key existed; - is revoked by Alter, so it is listed with a revoked status and stops counting toward the per-app key limit;
- cannot be rotated — create a new key (Mint, or
alter keys mint) and deploy it in its place.
Personal access tokens created before the upgrade behave the same way: sign in again with alter auth login, or create a new token in the dashboard.
Per-agent keys
Section titled “Per-agent keys”An agent can hold many API keys at once. Use this for:
- Standalone agent processes — keys per process / pod / container.
- Per-tenant agents — one tenant per agent, one key per tenant.
- Rotation without downtime — same pattern as app keys, scoped to the agent.
Agent Identity → <agent> → API keys → Mint key. Plaintext shown once. Equivalent SDK call:
result = await app.agents.mint_key(agent_id=AGENT_ID)print(result.api_key)Each key has a key_prefix (the first N characters of the plaintext) shown in the UI; use it to identify keys in audit logs without exposing the secret.
Deprecate (soft-revoke)
Section titled “Deprecate (soft-revoke)”Before hard-revoking a key, deprecate it first. A deprecated key still authenticates, and every authenticated response to it carries an X-Alter-Key-Deprecated: true header. The SDK surfaces a deprecation warning the first time a client sees that header, once per client so a busy caller does not flood its own logs, while the header stays on every response for per-call telemetry. Python emits it through the warnings module as a UserWarning, falling back to the SDK logger when warnings are configured as errors. TypeScript emits it through the SDK logger (console.warn by default; route or silence it with the logger option). Watch logs for lingering callers, fix them, then revoke.
Revoke
Section titled “Revoke”agents.revoke_key(). Terminal — the key never authenticates again.
The portal refuses to revoke a key that would leave the agent with zero active keys (raises LastActiveKeyError via SDK). Pass force=True to override, or mint a replacement key first.
Derived sub-keys
Section titled “Derived sub-keys”For short-lived, scope-narrowed keys (handing access to a plugin, a tool call, a code sandbox):
sub_key = await app.keys.derive( scopes=["grants:read"], expires_in=3600, # one hour)print(sub_key.api_key)The derived key intersects the parent key’s scopes with the requested scope set — it can only narrow, never broaden. Useful for handing the SDK to a less-trusted component without minting a long-lived agent.
Derived keys cannot be rotated. Derive a replacement from the parent key, then revoke the old derived key with await app.keys.revoke(key_id=KEY_ID).
Attenuating in-process
Section titled “Attenuating in-process”For a single call site that should run with narrower scopes than the parent key, use with_constraints() instead of deriving a key:
limited = app.with_constraints(scopes=["grants:read"])await limited.list_grants()The returned SDK instance carries the narrowed scopes through to every request automatically. No key is minted; the constraint is in-process and disappears with the instance. with_constraints() also accepts an optional rule — a request rule, evaluated server-side, carried by every request the returned instance makes, that can only further restrict each one; pass scopes, rule, or both. See Scopes.
Every key lifecycle event (mint, deprecate, revoke, rotate) is in the audit log. Every API call carries the key ID; while the key metadata remains available, the audit view also resolves its name and prefix. Use the By Agent key-prefix chips to scope an investigation.