Keys & authorizations
This page explains the keys that can write data under your wallet, where those grants live, and how to review or revoke them. It also covers agent keys: the keys you create so an agent, a script or a server can publish, redeploy, roll back and manage your projects without your browser.
Prerequisite: signed in. Background: Your data on-chain.
Prompt for your agent
Copy this into Claude Code, Cursor or any agent that can run shell commands. Creating a key is yours alone; the agent tells you exactly which key to create, then proves it works.
Read https://docs.stasho.xyz/guides/keys-and-authorizations.md. I want you to manage my
Stasho projects. Tell me exactly which agent key to create: in Settings → Authorizations for an
All sites key, or in one project's Settings → Agent access for a key tied to it. Say which
Projects choice, which scopes you need and why, the shortest expiry that fits, and whether to
pick "My agent signs" (if so, generate your own signing keypair and give me the public key
to paste; never show me the private key). If I need an App VM app rolled back, say that only
a key that signs for itself can do it. I will put the key in the STASHO_AGENT_KEY
environment variable: never ask me to paste it in chat. Then verify the key works with a
read call and tell me what it lists. Never ask for my wallet key.Why other keys write under your wallet
Your project data lives on-chain under your wallet address — but you wouldn't want to approve a wallet popup for every status change of every deploy. So the network supports delegation: your wallet signs, once, a security record listing other keys allowed to write specific kinds of messages on your behalf. Everything in that record is public and auditable.
Three keys are always involved; two more appear once you work with an agent.
| Key | Held by | What it's for |
|---|---|---|
| Your wallet | You | The owner. Signs the grants below; the only key that can change them. |
| Browser session key | Your browser | Signs your own writes (creating projects, saving settings) without a wallet popup each time. Rotates on a 24-hour cycle; a new one is created and the old one revoked automatically as you use the app. |
| Stasho delegate | Our backend | Writes deployment progress (queued → building → live) and pins artifacts as your builds run — the writes that happen while your browser is closed. |
| Agent key | Your agent, script or server | A bearer token (stasho_ak_…), not an on-chain key. Acts as you on your projects, within the scopes you gave it, over the agent API. Stasho stores only its hash. |
| Agent signing key | Your agent | Optional. A public key you paste when creating an agent key with My agent signs: the agent then signs its own site records on the network, and the key is listed here as an Agent signer row. |
The grants are scoped: the session key can write project and deployment records only; the Stasho delegate can write those, plus your custom-domain records, on a separate channel. Neither can touch the security record itself — so a leaked session key can forge deploy statuses for a day at worst, never lock you out or grant itself more power. An agent key that can create, change or remove sites needs one of two things on-chain, chosen when you create it: with Stasho signs for me, your signature lets the delegate write site records on the agent's behalf (the delegate row then wears an Agent keys badge); with My agent signs, the agent's signing key gets a row of its own and the delegate gains nothing.
The Authorizations section
Settings → Authorizations lists every key currently (or previously) authorized under your wallet, labelled by what it is:
| Row | What it is |
|---|---|
| Stasho (current) | The Stasho delegate. Wears an Agent keys badge, with a Withdraw button, while it may create, change and remove sites for your agent keys. |
| Stasho (retired) | A previous delegate key, kept so its old writes stay verifiable. |
| This browser | Your active session key. This browser (expired) is one of this browser's that has rotated out. |
| Another browser or session | A session key registered by a different browser or device of yours — or not. |
| Agent signer · key names | An agent's signing key, naming the agent keys that use it; Agent signer (key revoked) when none is left. |
| Other | A grant Stasho did not create, for instance from another tool. |
Each row shows what the key may write and offers Revoke; the delegate row offers Re-authorize when a grant is missing. Below the list, the Agent keys section holds every agent key of your account with Create key.
Agent keys
An agent key is created in one of two places, and both lists show the same keys:
- Settings → Authorizations → Agent keys, for a key that works on all your sites. The dialog there has no project choice.
- A project's Settings page → Agent access, for a key tied to that one project. Every kind of project has this card: an uploaded site, a repo project and an App VM app.
What an agent can do with a key is the whole agent API. What a key can hold depends on what the project is:
| Project | Scopes its key can hold |
|---|---|
| Uploaded site | publish, domains, delete, read, rollback |
| Repo project (static site built from GitHub) | read, deploy, rollback, domains |
| App VM app | read, deploy |
The Agent access card offers exactly the scopes in its row. A key for all projects offers every scope. Each key in the list shows its name, which projects it reaches, its scopes, its expiry and when it was last used, with Rotate (a new key with the same settings, shown once; the old one stops at once) and Revoke. Each build a key publishes reads "Published with key" in the site's deployment list.
Creating a key
Create key opens a dialog with:
Name — the attribution: it shows on every build, domain and site the key touches, so name it after what holds it ("Worker prod", "Claude chat").
Projects: This project or All sites. A key for one project cannot create sites.
Scopes: what the key may do:
readlists projects, reads one and lists its deployments. It is ticked by default and not implied by the others, so apublishkey reads nothing under/projectsunless it also hasread.deployredeploys a repo project or an App VM app, like Redeploy in the dashboard.rollbackrolls a project back to an earlier live build and undoes it, like Roll back to this and Undo rollback.publish,createanddeletepublish a new version of an uploaded site, create one and delete one.domainsattaches, checks and detaches custom domains, on uploaded sites and on repo static sites.
deleteneeds an expiry (90 days at most) and an email on file for your account, so you can be told when a key deletes a site or detaches a domain.Expires — 1, 7, 30 or 90 days, or Never. For a chat agent, 1 or 7 days; Never only for a server you control.
Who signs the site records: shown when a scope writes project records (
create,domains,delete,rollback):- Stasho signs for me: Stasho's delegate creates, changes and removes site records for this key. One signature now: the next step, Allow Stasho to manage your sites, ends in Sign and create key.
- My agent signs: paste the agent's public signing key (an uncompressed secp256k1 key,
0x04followed by 128 hex characters). The agent signs its own records, and the key is listed as an Agent signer row. Only on an All sites key with at least one of those scopes.
The key is shown once, on the Key created view, together with a ready-made prompt to hand your agent. Copy it then: anyone who has it can act on your sites within its scopes until it expires, including anyone who can read the chat you paste it into. A key with only publish, read and deploy needs no signature at all: a redeploy is a build dispatch, not a record write. A rollback key does need it, because a rollback writes the project's record.
Rolling back an App VM app
An App VM reads a rollback only from your own wallet or from a key that signs for itself, not from Stasho's delegate. So a rollback of an App VM app needs an All sites key created with My agent signs and the rollback scope. A key tied to one App VM app cannot hold rollback, because a project key cannot carry a signing key, and any other key answers app_rollback_needs_signer and changes nothing. Without such a key, you roll back in the dashboard (see Manage deployments). When you create an All sites key with rollback and leave Stasho signing, the dialog says an App VM will need the My agent signs option.
Revoking
Revoke a session key any time — for instance one from a device you've lost. Your next write bundles the removal into the on-chain record.
Revoke an agent key from either list: anything using it stops working at once. When it is the last key that needed Stasho's permission to manage sites, the dialog offers Also withdraw (one signature) so the delegate's grant goes with it. When a signer key is revoked, its signing key stays authorized while another key still uses it; with the last one the dialog also revokes the Agent signer row, one signature.
Withdraw, on the delegate row, removes the delegate's permission to create, change and remove sites and revokes every key that relied on it; keys under My agent signs and keys with only publish, read or deploy keep working.
Revoke an Agent signer row directly, and the agent keys that use it can no longer create, change or remove sites; publishing with them keeps working, and existing deployments are unaffected.
Revoke all other sessions removes every session key that is not this browser's in one signature. It also revokes all agent keys and their signing keys, and withdraws the delegate's grant: the clean-slate button.
Revoke the Stasho delegate and deploys stop working: builds can't report status and artifacts can't be pinned. The deployment that hits the wall shows Re-authorization required (awaiting_resign), and the Redeploy button becomes Re-authorize. This is reversible — re-authorizing is one wallet signature, and the next deploy proceeds.
The same Re-authorization required state can appear without you revoking anything — e.g. when the app needs a grant that didn't exist when you first signed up (this happened to alpha users when custom domains shipped). The fix is the same single signature in Settings → Authorizations.
Verification
- The Authorizations section shows the delegate and your current browser, both marked authorized; every agent key you created is in the Agent keys list, and a key under My agent signs has its Agent signer row
- The same list, from outside the app:
https://api.stasho.xyz/api/audit/<your-address>— or on-chain via any public explorer - After a revoke + re-authorize cycle, a Redeploy completes normally
- After revoking an agent key, a call with it answers
401 key_invalid
What can go wrong
| Symptom | Cause | Fix |
|---|---|---|
| Deployment stuck at "Re-authorization required" | The delegate lacks a grant (revoked, or a newer feature needs more scope) | Settings → Authorizations → sign the re-authorize prompt → Redeploy |
| Authorizations section shows a browser you don't recognize | A session key from another device or browser profile of yours — or not | Revoke it; sessions elsewhere will just re-prompt to sign in |
| An agent key or an Agent signer row you don't recognize | A key you forgot, a key someone created in a session of yours, or a signing key you never pasted | Revoke it. A signer row's revoke stops those keys from changing site records at once; the keys themselves are in the Agent keys list |
| Creating a key fails with "Your authorizations grant the Stasho delegate the security aggregate" | A row for the Stasho delegate, written outside the app, names the security record among what the delegate may write. Stasho never widens such a row, so the key's one signature is refused (409 delegate_row_forbidden) | Rewrite that row with the tool that wrote it so it no longer names security (the app's own Re-authorize only adds to a row, never removes), then create the key again |
Working with an agent
Key management is yours alone: an agent cannot create, rotate or revoke a key, and it should never see the dashboard. Its part is to tell you which key to create and to prove it works afterwards.
What the agent hands you, in these words:
In the Stasho dashboard open Settings → Authorizations, scroll to Agent keys and click
Create key (for a key tied to one project, open that project's Settings → Agent access instead).
Name: "<name>". Projects: <All sites>. Scopes: <read, deploy, rollback,
domains>. Expires: <7 days>. Who signs the site records: <Stasho signs for me, then Sign and
create key / My agent signs, paste this public key: 0x04…>. On the Key created view, copy
the key and set it as the STASHO_AGENT_KEY environment variable where I run; do not paste it
here. Tell me when it is set.How the agent verifies it afterwards. The key itself is the proof, with one read call:
curl -s -o /dev/null -w '%{http_code}\n' -H "Authorization: Bearer $STASHO_AGENT_KEY" \
https://api.stasho.xyz/api/agent/sites200 means an All sites key with publish; a key for one site answers 403 wallet_key_required there and 200 on GET /api/agent/sites/<projectId> instead. A key with read verifies with GET /api/agent/projects (or GET /api/agent/projects/<projectId> for one project) the same way; 401 key_invalid means the key was mistyped, has expired or is revoked. A write scope is checked only by a write: a 403 scope_missing names the scope the key lacks. A key under My agent signs also has a public trace: the signing key's address (shown on the Key created view) appears in the audit endpoint's authorized senders, currently authorized, with projects among its aggregate keys:
curl -s https://api.stasho.xyz/api/audit/$ADDRESS \
| jq '.authorizedSenders.sessionKeys[] | select(.address | ascii_downcase == "<signer address>")'