This service holds key material. A few habits keep an integration from becoming the weak link.
Never commit these
.env.localand any environment file carrying real valuesconfig/tenants.json— API keys and secret hashes- Workspace directories and service state
- Tokens, workspace passwords, account passwords
- Exported key material, including sealed blobs
Credentials
Tenant credentials (X-Api-Key + X-Api-Secret) administer every workspace
you own and mint tokens for all of them. They belong on a server you control —
never in a browser, mobile app, or anything shipped to a user.
Workspace passwords are unrecoverable. The service cannot reset one or recover a workspace without it. Store them the way you store root credentials.
Workspace tokens are bearer credentials: whoever holds one has the scopes it carries until it expires or is revoked. Treat a token like a password for its whole lifetime.
Scoped API keys are the durable, single-string keys a tenant mints for an end
user, bound to one account or wallet. They stay live — and keep their account
unlocked — until the service restarts, so a token revoke does not contain one;
see API keys. The end user stores the one string (for example
in localStorage) and never sees the workspace password.
Ask for the narrowest scope
Scopes are fixed at mint time but cheap to re-mint. A service that only reads
and signs should hold ["read","sign"], so a leaked token cannot create or
delete anything.
export is not something a workspace token exercises on its own. The two export
routes require an Unlimited scoped API key minted with a live
inquiry key, and the result is sealed to that key — see
Scopes and permissions and Export.
A durable scoped API key is different: DELETE /v1/auth/token is a no-op for
it, and it holds its account open until the service restarts or the key is
evicted under capacity pressure. There is no per-key revoke, so plan to re-mint
after a restart rather than to revoke — see
API keys.
Deletion is real
Deleting a workspace or an account destroys the key material inside it. There is no undo and no recovery from the service side.
Deleting a workspace that is currently in use is refused with 409
workspace_in_use. ?force=true overrides that one
refusal — it closes the live session and deletes anyway. It overrides nothing
else: a 403 from the storage layer stands with or without it. The refusal is
the safety rail, so reach for force only when you have established that nothing
is mid-operation. See Manage workspaces.
Sealed exports are still key material
A sealed blob is your key, encrypted to the end user’s own inquiry key — the X25519 recipient supplied when the tenant minted the scoped API key. Only the matching private half can open it, and that half stays with the end user, never with the server or the operator. That makes a sealed blob safe from a thief who lacks the private key, and nothing else. Keep it out of logs, issue trackers, chat, and CI artifacts. Give it no longer a retention than you would give the key itself.
Check recipientFingerprint before decrypting: it identifies which key the blob
was sealed to.
Guard the private half the way you guard the key material itself. It is the one value that turns every sealed blob you have ever received back into plaintext, and nothing in the service can rotate or revoke it for you.
Handling errors safely
- Branch on
error.code, never onmessage. - Do not log whole request bodies from account creation, unlock, or token mint — they carry passwords and secrets.
- Keep
requestIdfor support. Every error body carries one, and it also comes back on thex-request-idresponse header. It is safe to share; the rest of the error may not be.
Signatures
- A signature is a bearer instrument. The service returns it; broadcasting is yours, so treat a returned signature as sensitive until it is on-chain.
- Sign a digest or raw bytes only when you built them yourself. The service
signs exactly what you send — it does not re-hash or frame a
/sign/digestor/sign/bytespayload.
Operational hygiene
- Run one service instance per state directory. A second instance on the same storage is refused, deliberately, to protect wallet and quota records.
- Rotate tenant credentials through your operator rather than sharing them across environments.