Non-custodial · Open source · Self-host or cloud

Get paid in crypto, straight to your wallet
secure and private

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.

Start free View on GitHub npm i -g @zettapay/listener
0%
Protocol fee
100%
Non-custodial
BTC·USDC·USDT
Bitcoin + Base
MIT
Open source
Bitcoin·USDC on Base·USDT on Base·Non-custodial·xpub BIP-84·HMAC webhooks·RPC quorum·Self-hosted·Open source·TypeScript SDK· Bitcoin·USDC on Base·USDT on Base·Non-custodial·xpub BIP-84·HMAC webhooks·RPC quorum·Self-hosted·Open source·TypeScript SDK·
How it works

Three steps. Same for everyone.

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.

01
Create an invoice

One address per invoice

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.

02
Customer pays on-chain

Direct to your wallet

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.

03
Webhook confirms

Signed, replay-safe events

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.

What you can accept today
Bitcoin
BTC · mainnet

Watch-only via your xpub (BIP-84). One fresh address per invoice, tiered confirmations by amount.

USDC
on Base

Two modes: derived address per invoice (xpub) or a fixed address with a per-invoice decimal nonce.

USDT
on Base

Fixed address with a per-invoice decimal nonce. Independent token tracking on the same listener.

Two ways to run it

Self-host it, or let us host it

Same protocol, same SDK, same webhooks. Pick control or convenience — both are non-custodial, and the funds land directly in your wallet either way.

Self-hosted · open source Free

Run it on your own infra

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
Cloud · managed Early access

Let us host the listener

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.

SetupZero — paste your pubkey
InfraWe run it
CustodyNone — direct to you
Start free cloud signup — join the waitlist
Self-hosted Cloud
Setupnpm install, run your own infraZero setup, we host it
ControlFull — it’s your processWe operate it for you
Best forTeams running their own backendServerless / no-ops merchants
CostFree, open-sourceFree to start (early access)
CustodyNon-custodialNon-custodial
Where funds landDirectly in your walletDirectly in your wallet
Security & privacy at the center

Your funds. Your keys. Your privacy.

ZettaPay is built so there’s nothing for us to lose, leak, or freeze. Every property below is live today.

Non-custodial

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.

Private

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.

Secure

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.

Auditable

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.

Agent-native

Built for AI agents

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.

MCP server

One tool call to get paid

Drop @zettapay/mcp into Claude Desktop or any MCP client. Tools: create_invoice, get_invoice_status, list_supported_assets.

OpenAPI 3.1

A spec agents can read

The full listener API is published at /openapi.json and described for crawlers at /llms.txt.

Non-custodial

Runs on your machine

The MCP server talks only to your local listener at localhost:8787. No keys, no funds, no third party — ever.

Add it to Claude Desktop — claude_desktop_config.json
{
  "mcpServers": {
    "zettapay": {
      "command": "npx",
      "args": ["-y", "@zettapay/mcp"],
      "env": {
        "LISTENER_URL": "http://localhost:8787",
        "ZETTAPAY_API_KEY": "sk_live_..."
      }
    }
  }
}
Quickstart

Your public key. Your code.

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.

1. Install the SDK
$ npm install @zettapay/sdk
2. Your public keys live in your env vars
# .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
3. Create an invoice — ZettaPay watches the chain and fires your webhook
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.

Start accepting crypto.
Keep your keys.

Non-custodial. Open source. Bitcoin + USDC/USDT on Base. Self-host it, or let us host it for you.