Skip to content

Admin

API Keys

Minting, rotating, and revoking app keys and per-agent keys.

Alter has four key shapes, each minted and managed in the developer portal.

PrefixUsed byWhere it’s minted
alter_rk_… (runtime)Backend services using the App SDK classApp → API Keys, key type runtime (the default; CLI: alter keys mint)
alter_ak_… (agent)AI agents using the Agent SDK classApp → 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 callsProgrammatic only via app.keys.derive()
alter_key_… (legacy)Per-agent keys bound to one managed agentApp → Agents → <agent> → Keys (CLI: alter agents mint-key)

Keys minted before the scoped formats also use the legacy alter_key_… prefix, and per-agent keys still mint with the legacy prefix today. Legacy keys keep working, but the prefix does not indicate whether the key is an app or an agent key.

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.

The default key for backend code that calls third-party APIs through Alter. One per app is enough for most products.

API Keys → Mint key. The plaintext is shown once. Store it in a secret manager and revoke if it’s lost.

To rotate without downtime:

  1. Mint a new key.
  2. Deploy it to the running service.
  3. After confirming the new key is in use (Audit Logs → filter by key prefix), revoke the old one.

alter keys rotate performs the same exchange in one step: the new plaintext is returned once, and the old key keeps authenticating through a grace period until it is revoked.

API Keys → <key> → Revoke. Effective immediately. The next call with the revoked key fails with invalid_key.

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.

Agents → <agent> → Keys → Mint key. Plaintext shown once. Equivalent SDK call:

result = await alter.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.

Before hard-revoking a key, deprecate it first. A deprecated key still authenticates, but the SDK surfaces a deprecation warning every time the key is used. Watch logs for lingering callers, fix them, then 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.

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.

app.keys.rotate(key_id) rotates a derived key in place. app.keys.revoke(key_id) revokes it.

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 one-off deny rule, evaluated server-side, that can only further restrict each request; pass scopes, rule, or both. See Scopes.

Every key lifecycle event (mint, deprecate, revoke, rotate) is in the audit log. Every API call is attributed to the key by key_id and key_prefix. Filter the audit view by key to scope investigations.