ZZanoraDocs

Get started

From nothing to a verified purchase using only the API — signup, keypair, wallet, funding, policy, discover, pay. Every step is a copy-paste command.

This walkthrough uses curl and one small script, so every step is visible. For a console-based walkthrough, see the Quickstart. Steps marked 👤 need a person.

Terminal
export GW=https://api.zanora.dev
1

Request a workspace 👤

Terminal
curl -s -X POST $GW/v1/signup -H 'content-type: application/json' -d '{
  "role": "buyer",
  "email": "eng@northwind.example",
  "organizationName": "Northwind",
  "dailyBudgetMinor": "5000",
  "password": "a long passphrase for the console"
}'
# → 202 {"signupId":"sgn_…","status":"pending","expiresAt":"…","emailSent":true}

Open the emailed link. The console confirms the address and shows your root key once. Save it:

Terminal
export WKEY='zk.akey_….…'
curl -s $GW/v1/whoami -H "x-api-key: $WKEY"     # → "kind":"workspace","workspaceId":"wsp_…"

dailyBudgetMinor: "5000" caps the whole workspace at $50.00 a day. You can leave it out.

2

Generate the agent's keypair

Terminal
openssl genpkey -algorithm ed25519 -out agent-key.pem
chmod 600 agent-key.pem
openssl pkey -in agent-key.pem -pubout -out agent-key.pub.pem

agent-key.pem never leaves this machine. The platform only sees the public half.

3

Create the wallet

Terminal
curl -s -X POST $GW/v1/wallets -H "x-api-key: $WKEY" -H 'content-type: application/json' \
  -d "$(jq -n --arg pem "$(cat agent-key.pub.pem)" '{ownerType:"agent", ownerId:"invoice-bot", publicKeyPem:$pem}')"
# → {"id":"wal_f33b5618…","ownerType":"agent","ownerId":"invoice-bot","workspaceId":"wsp_…",…}
export WAL=wal_f33b5618…

You don't send workspaceId. It comes from your key.

4

Fund it 👤

Check which funding options this deployment offers:

Terminal
curl -s $GW/v1/rail/providers -H "x-api-key: $WKEY"

Then either request a top-up (topUps: true) or get a USDC deposit address (depositAddresses: true):

Terminal
curl -s -X POST $GW/v1/wallets/$WAL/topup -H "x-api-key: $WKEY" \
  -H 'content-type: application/json' -d '{"amountMinor":"2000"}'

curl -s -X POST $GW/v1/wallets/$WAL/deposit-address -H "x-api-key: $WKEY" \
  -H 'content-type: application/json' -d '{"asset":"USDC","chain":"base"}'

Money is credited when the rail confirms it. The console's Fund button does the same thing with a card form. Watch the balance:

Terminal
curl -s $GW/v1/wallets/$WAL/balance -H "x-api-key: $WKEY"
# → {"balanceMinor":"2000","availableMinor":"2000","currency":"USD"}
5

Set a policy

Terminal
curl -s -X POST $GW/v1/policies -H "x-api-key: $WKEY" -H 'content-type: application/json' \
  -d '{"document":"approval:\n  price > 5\ndeny:\n  provider.verified == false"}'

Anything over $5.00 now needs a person to approve it, and unverified sellers are refused.

6

Discover and pay

Terminal
npm install @zanora/sdk
buy.ts
import { readFileSync } from "node:fs";
import { ZanoraAgent, ZanoraPolicyRejection } from "@zanora/sdk";

const agent = new ZanoraAgent({
  apiKey: process.env.WKEY!,
  walletId: process.env.WAL!,
  agentId: "invoice-bot",
  privateKeyPem: readFileSync("agent-key.pem", "utf8"),
  maxPriceMinor: 500n,
});

const { results } = await agent.discover({ query: "extract text from invoices", protocol: "rest", maxPriceMinor: "200" });
const best = results[0];
if (!best) throw new Error("nothing matched");

try {
  const r = await agent.invoke(best.version.endpoint, { body: { imageUrl: "https://example.com/invoice.png" } });
  console.log(r.data);
  console.log("receipt", r.receipt?.id, "signed:", r.receiptVerified, "for this answer:", r.responseHashVerified);
  if (r.receipt) await agent.rateProvider(best.provider.id, r.receipt.transactionId, 5);
} catch (err) {
  if (err instanceof ZanoraPolicyRejection) console.log("refused:", err.code, err.approvalId ?? "");
  else throw err;
}
Terminal
WKEY=$WKEY WAL=$WAL npx tsx buy.ts

The balance drops by exactly the price, and GET /v1/receipts lists the purchase.

Runnable version

The platform repository has this whole flow as two scripts, with every refusal handled: starters/d-buyer-rest (onboard.ts for steps 2–5, buy.ts for step 6).