Testing payments locally
Dodo can't reach localhost, so your plan won't unlock after a test payment on your computer. Use a tunnel to receive webhooks while developing.
On your computer, checkout works, but the plan never unlocks: Dodo sends the webhook to a public URL, and localhost isn't one. A tunnel gives your local app a temporary public address.
Start the app
npm run devStart a tunnel
In a second terminal:
npx cloudflared tunnel --url http://localhost:3000No account needed. It prints an address like https://random-words.trycloudflare.com.
Register the webhook in test mode
In Dodo, with the Live Mode switch off:
- Developer → Webhooks → Add endpoint.
- URL:
https://<tunnel-address>/api/webhooks/dodo. - Select all events, then Create endpoint.
- Copy the signing secret from the Overview tab.
Save the secret and restart
DODO_PAYMENTS_WEBHOOK_SECRET=whsec_…Stop npm run dev with Ctrl+C and start it again, so it reads the new value.
Pay with a test card
Open your site at localhost, buy a plan, and pay with a test card:
| Card | Expiry | CVV | Result |
|---|---|---|---|
4242 4242 4242 4242 | 06/32 | 123 | Success (US Visa) |
4576 2389 1277 1450 | 06/32 | 123 | Success (Indian Visa) |
4000 0000 0000 0002 | 06/32 | 123 | Declined |
4000 0000 0000 0341 | 12/34 | 123 | Pays now, fails at the next renewal |
UPI in test mode: success@upi or failure@upi. More in Dodo's testing guide.
Your npm run dev terminal shows POST /api/webhooks/dodo 200, and the dashboard unlocks the plan.
Quick tunnels change address
A free Cloudflare quick tunnel gets a new address each time you start it. Update the webhook URL in Dodo each time (the secret stays the same if you edit the endpoint), or use a named tunnel or a paid ngrok domain for a fixed address.
Testing renewals, cancellations and refunds
- Cancellation: open Manage billing on the dashboard and cancel. The dashboard shows "Cancels on [date]".
- Failed renewal: subscribe with
4000 0000 0000 0341. The next charge fails and the subscription goeson_hold. - Refund: refund the payment in the Dodo dashboard. A full refund removes access from a one-time purchase.
- Resend an event: open the endpoint in Developer → Webhooks and resend it from the delivery log. Handlers are safe to run twice.
Webhooks
How Dodo tells your app about payments, which events the kit handles, and the rules that keep billing correct.
Selling access to a GitHub repo
Sell source code, templates or a private library. Paying customers are invited to a private GitHub repository automatically, and removed after a full refund.