Every vendor is another setup
Each paid API is another account, bill and key. Set up Zanora once and agents can buy from any verified seller.
Pay-per-call for APIs and MCP tools
Price any HTTP endpoint or MCP tool per call. Agents find it, pay within rules you set and get a signed receipt.
Buying? Paste this into your agent:
Fetch https://zanora.dev/skill.md and follow the setup instructionsOr, follow the Buyer Quickstart.
The problem
Agents can already pay. Businesses need what surrounds the payment.
Each paid API is another account, bill and key. Set up Zanora once and agents can buy from any verified seller.
A cap can't say “verified sellers only” or “ask me above $5”. Zanora's rules can, before money moves.
A statement shows money moved, not what came back. Zanora signs each receipt over the exact response.
How it works
The handshake follows x402 over HTTP and MCP. Payments settle on Zanora's ledger, so a call can cost $0.001.
Search the registry by task, price and latency.
An unpaid call returns a price signed by Zanora.
Zanora checks your rules, budget and balance.
The agent signs a proof. Zanora verifies it and reserves the price.
Only now does the seller's code run. A failure refunds the buyer.
The answer returns with a signed receipt. The seller is credited moments later.
Platform
Registry, wallets, policies and ledger behind one gateway. Neither side builds billing.
Listings ranked by relevance, price, latency and reputation. Only verified sellers appear.
CapabilitiesOne per agent. Only the agent holds its signing key. Fund by card or USDC on Base.
WalletsHTTP endpoints and MCP tools share one handshake, receipts and refunds.
The protocolDeny, require approval or allow-list, under a daily budget. Rules run on the server, so a model can't talk its way past them.
Policiesdeny:
provider.verified == false
approval:
price > 5
allow:
category == "OCR"
Wrap a handler you already run. No billing code. Earnings pay out in USDC.
For sellersBound to the response's hash, so it proves what was bought and what came back.
ReceiptsFailed calls are refunded. Three seller failures in a row pause that seller for the wallet.
How it worksDevelopers
Six TypeScript packages on npm, plus a plain HTTPS + JSON API.
import { zanoraSeller } from "@zanora/middleware-mcp";
const seller = zanoraSeller(); // ZANORA_API_KEY — a provider key
const paid = await seller.sell({
tool: "extract_invoice",
description: "Extract text and line items from scanned invoices",
category: "OCR",
price: "$1.00",
url: "https://acme.example/mcp",
});
server.tool("extract_invoice", "Costs $1.00.", { imageUrl: z.string() },
paid(async (args) => {
const answer = await extractInvoice(String(args.imageUrl));
return { content: [{ type: "text", text: JSON.stringify(answer) }] };
}),
);
npm install @zanora/middleware-mcpsell() publishes the listing and returns a wrapper.import express from "express";
import { HttpBackend, zanora } from "@zanora/middleware-express";
const app = express().use(express.json());
const backend = new HttpBackend({ apiKey: process.env.ZANORA_API_KEY! });
app.post("/ocr", zanora({ backend, capabilityId: "cap_d2383f37…" }), (req, res) => {
// Only reached once the call is paid for.
// req.zanora = { transactionId, walletId, agentId }
res.json(runOcr(req.body.imageUrl));
});
npm install @zanora/middleware-express402 with a signed price.{
"mcpServers": {
"zanora": {
"command": "npx",
"args": ["-y", "@zanora/mcp"],
"env": { "ZANORA_MAX_PRICE_MICROS": "5000000" }
}
}
}
npx -y @zanora/mcp setup --email you@example.com --org "Acme"setup signs you up and keeps keys in ~/.zanora, not the config.zanora_discover, zanora_invoke and nine more tools.ZANORA_MAX_PRICE_MICROS caps what the client will sign.import { ZanoraAgent } from "@zanora/sdk";
const agent = new ZanoraAgent({
apiKey: process.env.ZANORA_API_KEY!, // workspace key
walletId: "wal_f33b5618…", // this agent's wallet
agentId: "invoice-bot",
privateKeyPem: readFileSync("agent-key.pem", "utf8"),
maxPriceMicros: 5_000_000n, // never sign above $5.00 (micro-dollars)
});
const { results } = await agent.discover({ query: "extract text from invoices", maxPriceMicros: "2000000" });
const result = await agent.invoke(results[0].version.endpoint, {
body: { imageUrl: "https://example.com/invoice.png" },
});
npm install @zanora/sdkinvoke() runs the whole handshake. invokeMcp() does the same for MCP tools.Architecture
Agents call sellers directly. Seller middleware checks with Zanora first.
Buyers' agents
@zanora/mcp@zanora/sdk@zanora/mcp-proxySellers
@zanora/middleware-express@zanora/middleware-mcpUse cases
Buyers
An invoice agent needs OCR. It finds a verified seller and pays for one call, with no vendor account.
Buy your first callSellers
Price every tool at once or leave some free. Prices show in tools/list.
Teams running agents
A wallet each, a daily cap and approval above a set price. No agent can spend more than its wallet holds.
ApprovalsFinance and audit
Every purchase has a signed receipt. Every movement is in an append-only ledger.
Purchase historyPricing
No subscription. Fee increases are announced at least 30 days ahead.
Balances aren't bank deposits. Regulated payment partners hold the funds. Terms
Money and feesSign up, give an agent a wallet and buy a free call from the demo seller. No card needed.