Go-live checklist
Test and live are fully separated — keys, webhooks, and chains. Going live is five deliberate switches, not a redeploy.
The checklist#
Verify your payout wallet
The payout wallet on your live project must be verified by signing with that wallet. Once verified, it can only be rotated through the same signed flow — a stolen dashboard login alone cannot redirect your money.
Create a live API key
Generate a
dp_live_…key in the dashboard. Live keys are shown once — store the key in your secret manager immediately. (Test keys stay re-viewable, by design.)Switch your chain ID to mainnet
Live keys refuse testnet chains, so this is enforced, not just recommended. On Polygon mainnet the default token is USDT. See Chains & tokens for what’s live.
const charge = await duckypay.charges.create({ - chainId: 80002, // Polygon Amoy testnet + chainId: 137, // Polygon mainnet fiat: { currency: 'USD', amount: '25' }, paymentMode: 'both', reference: order.id, });Register a live webhook endpoint
Webhook endpoints are mode-scoped: testnet invoices deliver only to test endpoints, mainnet invoices only to live ones. Register your production URL as a live endpoint and verify signatures with its own secret — see Webhooks.
Make one small real payment
Before announcing anything, run one real charge end-to-end: create → pay → receive the
invoice.paidwebhook → confirm the funds arrived in your payout wallet on a block explorer. That last step is the whole point of non-custodial: you can independently verify every payment.
Test vs live are separate worlds#
| Test mode | Live mode | |
|---|---|---|
| API key prefix | dp_test_ | dp_live_ |
| Allowed chains | Testnets only (Amoy) | Mainnets only |
| Webhook delivery | Test endpoints only | Live endpoints only |
| Key visibility | Re-viewable in the dashboard | Shown once at creation |
Security notes#
- Keep API keys server-side. Never ship a key in frontend code — the browser only ever needs the
checkoutUrl/invoiceId. - Always verify webhook signatures. Fulfil orders from the verified
invoice.paidevent, not from a redirect or client callback. - Client callbacks are UX, not truth. Treat
onSuccessin@duckypay/reactas a signal to update the UI; the webhook (or the on-chain event) is the source of truth for shipping goods.