ZZanoraDocs

Set up

Each agent gets a wallet and an ed25519 keypair. The wallet holds the public key and the agent holds the private key. How to create both, and how to look after them.

One wallet per agent

A wallet holds money and belongs to your workspace. An agent wallet also holds the public key that its payment proofs are checked against. Give each agent its own wallet:

  • a compromised or misbehaving agent can only spend what its own wallet holds;
  • purchase history and receipts stay separate per agent;
  • the MCP packages can find the wallet from your key automatically, but only when the workspace has exactly one agent wallet. With several, you name the one to use.

Create one in the console

Buyer → Agents → New agent. The console generates the keypair, creates the wallet, and shows the private key once as a download. It also keeps a copy in that browser, so the console can make test calls.

Create one with the API

1

Generate a keypair

openssl genpkey -algorithm ed25519 -out agent-key.pem
chmod 600 agent-key.pem
openssl pkey -in agent-key.pem -pubout          # the public half, for the next step
2

Register the wallet

Terminal
curl -s -X POST https://api.zanora.dev/v1/wallets -H "x-api-key: $WKEY" \
  -H 'content-type: application/json' \
  -d '{"ownerType":"agent","ownerId":"invoice-bot","publicKeyPem":"-----BEGIN PUBLIC KEY-----\n…\n-----END PUBLIC KEY-----\n"}'

ownerId is your label for the agent. It appears in payment proofs, so use something plain like invoice-bot. The response is the wallet, including its id (wal_…).

Looking after the private key

It's the spending authority, and it can't be recovered

Whoever has agent-key.pem can spend that wallet's balance, within your policies. Zanora never had the private key, so a lost key can't be reissued. The wallet keeps its balance but can never spend it. Treat the key like a wallet seed phrase.

  • Keep it in a file with mode 0600, or in your secrets manager. In MCP configs, point to it with ZANORA_AGENT_KEY_FILE rather than pasting it in, because config files get shared and appear in screen-shares.
  • Only fund a wallet with what you'd accept losing to that agent.
  • If a key leaks: freeze the wallet (POST /v1/wallets/:id/freeze), create a new wallet with a new key, and move future funding there.

Reading a wallet

CallReturns
GET /v1/walletsevery wallet in your workspace
GET /v1/wallets/:id/balance{ balanceMinor, availableMinor, currency }. Available excludes money on hold
GET /v1/wallets/:id/ledgerevery entry, oldest first: funding, charges, refunds
POST /v1/wallets/:id/freeze / unfreezestop or allow outgoing payments

Next: fund the wallet.