A scoped API key is a single opaque string a tenant mints for one end user,
bound to one account — or one wallet within it. Unlike a workspace token, it is
durable: it keeps working, and keeps its account unlocked, until the service
restarts. The end user holds the one string (for example in localStorage) and
never sees the workspace password.
The canonical flow is a tenant minting a key for an end user who later redeems a key export against it — the workspace password never leaving the tenant’s side:
sequenceDiagram autonumber actor U as End user participant T as Tenant backend participant S as TEE Docker U->>U: generate an X25519 keypair, keep the private half U->>T: ask for access, hand over the inquiry public key T->>S: POST /v1/auth/api-key — tier unlimited, inquiryKey, accountPassword if Cold Vault Note over S: the account is unlocked and pinned open inside the enclave S-->>T: 201 — one durable scoped-key string T-->>U: the scoped key, kept in the browser Note over U,S: later — the workspace password is never shared U->>S: POST /v1/accounts/slug/wallets/id/export?vm=evm — Bearer scoped key S-->>U: a blob sealed to the inquiry key U->>U: unseal with the private half to recover the private key
The endpoint shapes for minting and introspection are on API keys; this page is the model behind them.
Durable, and in memory
A live key is stay-exposed: while it exists it pins its workspace and its bound account open, so the idle, absolute, and account-custody timers do not apply to it. All of that state — the binding, the tier, the inquiry key — lives in memory only. Nothing about a scoped key is written to disk, and a restart voids every key. “Durable” means “until the process restarts,” not “forever on disk.”
Nothing decrypted is persisted to achieve this: the never-lock behaviour comes from keeping an already-unsealed session alive in the enclave, never from storing a re-unlock secret. No workspace or account password is ever held at rest.
Two tiers
A key is minted at one of two fixed tiers, expressed as its scopes:
| Tier | Scopes | What a scoped key can reach (this release) |
|---|---|---|
basic (default) |
read, write |
Read its bound account, wallets, and addresses |
unlimited |
read, write, sign, export |
The above, plus sealed export (with a live inquiry key) |
The write and sign scopes sit on the lease but are not reachable by a scoped
key: it is confined to its bound account’s read routes plus export. Signing and
account/wallet management require a workspace token, so unlimited over
basic buys a scoped key only sealed export. Mint it deliberately, for users who
need export. See Scopes and tiers.
Export needs an inquiry key
Export is the highest-consequence operation, so it is never sealed to an operator key. The end user generates their own X25519 keypair, keeps the private half, and gives the tenant only the public inquiry key at mint. Every export the key performs is sealed to it, and opens only for the holder of the private half.
- The inquiry key unlocks a small functionality list — today just
export. - It is time-boxed by
validationDuration(default four hours). After it lapses the base key keeps working, but export locks again. - Without an inquiry key, export is refused even on an Unlimited key.
The client-side unseal is in Export key material.
Cold Vault accounts
An account may carry its own password — an extra secret beyond the workspace
password. Such an account can still be minted for: the tenant relays that
password as accountPassword at mint, the service unlocks the account, and the
durable key keeps it open. The password is used once and never stored.
Capacity and eviction
A durable key holds a decrypted workspace handle in memory until restart, so handle capacity is finite. When admitting a new key would exceed a tenant’s capacity, the tenant’s least-recently-used durable key is evicted to make room. An evicted key’s next request fails exactly as after a restart — re-mint it. Each use touches the key’s recency, and every eviction is recorded in the audit log so an evicted client knows to re-mint.
Revocation is coarse
There is no per-key revoke. DELETE /v1/auth/token is accepted for a scoped key
but does nothing — a restart (or an eviction) is what ends it. Plan to re-mint
after a restart rather than to revoke, and keep the blast radius of any one key
small by scoping it to a single account or wallet.
Identity binding
A key is bound to its account by the account’s slug (and to a wallet by its
stable id). A slug can be reused after an account is deleted, so deleting an
account that a live key is bound to is recorded in the audit log — a later
account created with the same slug would otherwise inherit that key’s authority.
Related
- API keys — the mint and introspection endpoints
- Scopes and tiers — the capability model
- Export key material — the client-unseal flow
- Workspaces and tokens — the session model a token uses instead