Self-hosted install · a few minutes
From zero to first confirmed payment
Pick your stack, paste your public keys, copy the files. No account, no fee. The listener runs on your machine — it watches the chain and pings your webhook. Private keys never leave your wallet.
100% open-source
Non-custodial
BTC · USDC · USDT on Base
Install with AI instead →
Prefer managed? Create a Cloud account →
View source on GitHub →
1
Stack
2
Keys
3
Code
4
Verify
Where will you integrate?
We’ll generate the webhook handler and invoice call for your stack. The listener itself is the same for all of them.
What will you accept?
Paste public material only. It is used to build the commands below, in your browser — nothing is sent to ZettaPay.
How this works.
Customers pay your address from any wallet they own. Your listener watches the chain, confirms the transfer, and POSTs a signed webhook to your server.
ZettaPay never holds funds and takes no per-transaction fee. If your EVM wallet can export an xpub, the listener can also derive one Base address per invoice (
--xpub-evm).
Read the listener README →
Run the listener, copy 3 files
Your public keys are already filled into the commands. The files use only your language’s standard crypto — read them before you trust them.
// We never custody. Funds flow directly to YOUR address.
1 · Install and start the listener
2 · Drop these files in your repo
Verify the install
Five checks, all against your own machine. None require an account.
CLI · built into the listener
# validate the .env without starting anything zettapay-listener verify-config # probe a running listener (exit code 0 = healthy) zettapay-listener healthcheck
Manual checklist · works today
1
Listener is up
curl http://localhost:8787/health
Should return "ok": true with ws_connected and the latest block height.2
Env vars are set in your app
MERCHANT_WEBHOOK_SECRET and ZETTAPAY_API_KEY must match the listener’s .env. Restart your dev server after editing.3
An invoice can be created
Run the generated invoice call. The response should carry an
invoice_id, a receive_address and a qr_uri. A 401 means the API key does not match.4
Webhook endpoint reachable
The URL you passed to
--webhook-url must be HTTPS and reachable from the machine running the listener (plain http://localhost is accepted for development).5
Signature verification works
POST any body to your webhook with a wrong
X-ZettaPay-Signature — your handler should reject it with 401. That’s the HMAC doing its job. Your webhook secret never leaves your servers.
★
Ready for a first payment.
Create a small invoice and pay it from any wallet. Once the transfer confirms on-chain, your listener POSTs
invoice.confirmed to your webhook and retries until your server answers 2xx.
ZettaPay is 100% open-source.
Every endpoint, every signature, every line of code is on GitHub. We never custody — payments flow directly between your customer’s wallet and your address. Self-hosted is free; the managed Cloud is a flat subscription (pricing).