No protocol fee. No custodian. No handing your keys to anyone. Self-host in 30 seconds, or let us host it for you. The funds are always yours — ZettaPay only ever sees a public key.
The hard problem in crypto checkout isn’t taking the payment — it’s knowing it landed. ZettaPay watches the chain and resolves “did they pay?” without ever holding a single satoshi. Self-hosted or cloud, the flow is identical.
Call the SDK to create an invoice. ZettaPay derives a fresh receiving address from your public key (xpub), or uses your fixed address with a unique amount nonce. No wallet connect, no keys to share.
The customer sends the transaction straight from their own wallet to your address — Bitcoin, USDC on Base, or USDT on Base. ZettaPay never touches the funds. The chain is the settlement layer.
The listener cross-checks confirmations across multiple RPCs and posts a HMAC-signed webhook with verified amount, token, chain, and tx hash. Exactly what your backend already expects from a payment processor.
Watch-only via your xpub (BIP-84). One fresh address per invoice, tiered confirmations by amount.
Two modes: derived address per invoice (xpub) or a fixed address with a per-invoice decimal nonce.
Fixed address with a per-invoice decimal nonce. Independent token tracking on the same listener.
Same protocol, same SDK, same webhooks. Pick control or convenience — both are non-custodial, and the funds land directly in your wallet either way.
Install the listener, point it at your public key, and run it wherever you want. Total control, zero third parties, MIT-licensed code you can read and fork.
$ npm install -g @zettapay/listener
$ zettapay-listener init
$ zettapay-listener start
# watching the chain for your addresses
On serverless (Vercel and friends) and don’t want to run infra? We host the listener for you — zero setup. Still fully non-custodial: we watch the chain, but the funds go straight to your wallet. We never touch them.
| Self-hosted | Cloud | |
|---|---|---|
| Setup | npm install, run your own infra | Zero setup, we host it |
| Control | Full — it’s your process | We operate it for you |
| Best for | Teams running their own backend | Serverless / no-ops merchants |
| Cost | Free, open-source | Free to start (early access) |
| Custody | Non-custodial | Non-custodial |
| Where funds land | Directly in your wallet | Directly in your wallet |
ZettaPay is built so there’s nothing for us to lose, leak, or freeze. Every property below is live today.
ZettaPay only ever holds a public key (xpub) or an address — never a private key, never your funds. Payments move directly from payer to your wallet on-chain. We can’t freeze, claw back, or lose what we never had.
In xpub mode every invoice gets a fresh address, so payments aren’t trivially linkable. Zero telemetry, zero identity checks, zero third party. We don’t profile your customers because we never see them.
Webhooks are HMAC-SHA256 signed with replay protection. Confirmations are cross-checked across multiple RPCs (quorum) so a single bad node can’t spoof a payment. Rate-limiting and TLS by default.
The protocol and SDKs are MIT-licensed on GitHub — read the listener, audit the webhook signing, run a fork. Every payment is a transaction you can verify on-chain yourself. The threat model is documented.
Agents can accept crypto in one tool call. ZettaPay ships a Model Context Protocol server and a faithful OpenAPI spec — both pointed at your local listener, so the agent never touches a key or a coin.
Drop @zettapay/mcp into Claude Desktop or any MCP client. Tools: create_invoice, get_invoice_status, list_supported_assets.
The full listener API is published at /openapi.json and described for crawlers at /llms.txt.
The MCP server talks only to your local listener at localhost:8787. No keys, no funds, no third party — ever.
{
"mcpServers": {
"zettapay": {
"command": "npx",
"args": ["-y", "@zettapay/mcp"],
"env": {
"LISTENER_URL": "http://localhost:8787",
"ZETTAPAY_API_KEY": "sk_live_..."
}
}
}
}
Install the SDK, put your public key in env vars, create invoices. We watch the chain from there — whether you self-host the listener or let us run it.
$ npm install @zettapay/sdk
# .env — stays on your servers, never on ours
ZETTAPAY_API_KEY=sk_live_...
ZETTAPAY_WEBHOOK_SECRET=whsec_xxx
MERCHANT_XPUB=zpub6q... # BTC, BIP-84
MERCHANT_XPUB_EVM=xpub6C... # USDC/USDT on Base
import { ZettaPay } from '@zettapay/sdk';
const zp = new ZettaPay({
apiKey: process.env.ZETTAPAY_API_KEY,
webhookSecret: process.env.ZETTAPAY_WEBHOOK_SECRET,
webhookUrl: 'https://my-app.com/zp/webhook',
});
const invoice = await zp.invoices.create({
amount: 42.00,
currency: 'USDC',
chain: 'base', // 'btc' | 'base'
});
// invoice.address is a fresh receiving address derived from your xpub.
// When the customer pays, ZettaPay posts an HMAC-signed webhook the
// moment the transaction confirms. The funds were always yours.
Non-custodial. Open source. Bitcoin + USDC/USDT on Base. Self-host it, or let us host it for you.