ZanoraBetaDocs

Core concepts

Tenants, API keys, scopes and console logins. Everything that authenticates you to Zanora, and how to keep it narrow.

Tenants

Everything you own on Zanora belongs to a tenant. The type depends on your role:

RoleTenantId prefixCreated with
Buyerworkspace: the unit of budget and policy, holding agent walletswsp_…POST /v1/signup with role: "buyer"
Sellerprovider: the unit of listings and earnings, with one settlement walletprv_…POST /v1/signup with role: "seller"

A tenant's id comes from its credential. You almost never send workspaceId or providerId in a request body. If you do, it is ignored for anything except an admin key. This means a leaked request can't be replayed against someone else's tenant.

API keys

An API key looks like zk.akey_3652ec9e….<secret> and goes in the x-api-key header on every call:

Terminal
curl -s https://api.zanora.dev/v1/whoami -H "x-api-key: $ZANORA_API_KEY"
JSON
{
  "principal": "workspace(wsp_91c2…)",
  "kind": "workspace",
  "workspaceId": "wsp_91c2…",
  "scopes": ["wallets:read", "wallets:write", "policies:write", "…"],
  "keyId": "akey_3652ec9e…"
}

Make /v1/whoami your first call with any new key. It tells you whether the key works and what it's allowed to do.

Keys are shown once

Zanora stores only sha256(token). A lost key can't be recovered, only replaced: mint a new one from another key, or from the console (Settings → API keys) after signing in with your password. Buyers choose the kind there: an agent key, which can buy but can't approve, or full access.

Your root key and the keys you mint from it

Signup gives you a root key with every scope your role can use. Use it to set up, not to run production. Mint a narrower key for each service or agent:

Terminal
curl -s -X POST https://api.zanora.dev/v1/auth/keys -H "x-api-key: $ROOT_KEY" \
  -H 'content-type: application/json' \
  -d '{"label":"invoice-agent","scopes":["discovery:read","wallets:read","receipts:read","ratings:write"],"expiresInSeconds":2592000}'

The rules:

  • Delegation only narrows. A new key's scopes must be a subset of the scopes on the key that minted it, and it can't outlive that key.
  • A key's scopes are fixed when it's minted. If a release adds a new scope, existing keys don't get it. Mint a replacement if you need it.
  • Rotation doesn't need downtime. POST /v1/auth/keys/:id/rotate with {"graceSeconds":300} keeps the old secret working for five minutes while you redeploy.
  • Revoking takes effect on the next request. DELETE /v1/auth/keys/:id?cascade=true also revokes every key minted from it. Use that when a key has leaked.

Scopes

A scope decides which routes a key can call. Ownership decides which records it can reach. These are separate checks, and you need both. A provider key with wallets:read still can't read a buyer's wallet.

ScopeBuyer root keySeller root keyAllows
discovery:read✓✓search the marketplace
capabilities:read✓✓read capabilities; sellers list their own
capabilities:write✓publish, edit and deprecate capabilities
providers:read✓✓read provider profiles; request verification
workspaces:read✓read your workspace
wallets:read / wallets:write✓✓read balances and ledgers; create and fund wallets
funding:request✓create a one-time card payment link a person pays. Agent keys have it; it can't move money on its own
policies:read / policies:write✓read and change spending rules
approvals:read / approvals:write✓see held spends; approve or deny them
ratings:write✓rate a seller you bought from
receipts:read✓✓read receipts: purchases for buyers, sales for sellers
payments:write✓the x402 routes a seller's middleware calls
payments:external✓pay an x402 seller outside Zanora (preview). Agent keys minted from now on have it; it does nothing until your workspace turns outside sellers on
payouts:write✓set a payout destination; request payouts
rail:read✓✓what funding and payout rails exist; your rail transactions
keys:read / keys:write✓✓list, mint, rotate and revoke keys

GET /v1/auth/scopes returns the full list. When a key is missing a scope, the 403 names the scope it needed:

Output
403 {"error":{"code":"FORBIDDEN","message":"GET /v1/metrics requires the \"metrics:read\" scope (key ci-publish holds: capabilities:write)"}}

Give an agent a key without approvals:write

If an agent's key can't record approvals, the model can't approve its own held spend, even if you've set up in-client approval prompts. See Approvals.

Console logins

The console↗ uses an email and password. Signing in creates a session, which is an ordinary API key of kind session, held in an httpOnly cookie. It has exactly your tenant's permissions and no more.

  • Resetting a password revokes every console session but no API keys, so your production agents keep working.
  • Signing out revokes that session only. You can't use it to revoke an agent's API key by accident.
  • Keys you create in the console belong to your account, not to the login you made them from. They keep working after you sign out, reset your password, or your session expires. Settings → API keys shows when each one expires ("never" unless your deployment sets a lifetime). To stop one, revoke it there.
  • If you sign up through the API rather than the console, include password in the signup request if you want to be able to sign in to the console. The password only takes effect once the email is confirmed.

Frozen accounts

Zanora may freeze an account while it looks into something, such as a disputed card payment (Terms §13). While an account is frozen:

  • every key and console session can still read: balances, history, receipts;
  • every write is refused with ACCOUNT_FROZEN (403), and so is every purchase from its wallets, whichever seller is charging;
  • a frozen seller is hidden from discovery;
  • money that arrives, such as a USDC deposit, is still credited.

The console shows the reason at the top of every page. When the freeze is lifted everything works again; a seller returns to discovery only if it was verified.

Closing your account

Close it from Settings → Close account in the console (or POST /v1/accounts/close from a console session). You type your email address and your password to confirm. Closing is permanent:

  • every API key and console session stops working at once, and you can no longer sign in;
  • a seller's listings are deprecated, so buyers can't find or buy them;
  • money is not lost. A buyer's remaining balance is refunded to the card that funded it, or sent as USDC to an address you've verified as yours, less anything you owe. A seller's cleared earnings that aren't held for a dispute are paid out to the registered payout address; earnings still clearing follow once they clear. Zanora's team does this after the closure and emails you about it;
  • your account details (email, password, organisation name, signup records and API key records) are deleted within 90 days. The email confirming the closure gives the date. Ledger entries, transaction records, receipts and other financial records may be kept as long as legal, accounting, fraud-prevention, dispute-resolution and compliance requirements need them, de-linked from your name and email. Zanora may keep a cryptographic hash of your email address to prevent fraud and enforce platform restrictions; the address itself is deleted (Privacy Policy: Account deletion). An address whose account Zanora closed can't be used to sign up again; one whose holder closed it can.

To have your details deleted sooner, email support@zanora.dev from the address on the account once it's closed.