pealdevDOCS
Back to peal.dev

STRIPE STARTER · LOCAL WEBHOOK TESTING

Local webhook testing

Stripe CLI forwards real events from your test account to localhost. The CLI prints a webhook signing secret — paste it into .env.local. Trigger events from the CLI to debug handlers without making real payments.

Step 1: Install the CLI

Terminal
# macOS
brew install stripe/stripe-cli/stripe

# Anywhere else: https://stripe.com/docs/stripe-cli

Step 2: Log in

Terminal
stripe login
# Opens a browser, confirms the device, links the CLI to your test account.

Step 3: Forward to localhost

Terminal
stripe listen --forward-to localhost:3000/api/webhooks/stripe
# > Ready! Your webhook signing secret is whsec_xxx (^C to quit)
# Copy that whsec_ into .env.local as STRIPE_WEBHOOK_SECRET.

Step 4: Trigger events

Terminal
stripe trigger checkout.session.completed
stripe trigger invoice.paid
stripe trigger customer.subscription.updated
stripe trigger customer.subscription.deleted

Each `trigger` creates the fixtures Stripe needs and fires the event. The CLI prints the dispatch result. Your server logs the handler call. If you see 200 OK in the CLI, your handler returned normally.

Or just pay a test card

Open /pricing, click a CTA, you're on Stripe Checkout. Use card 4242 4242 4242 4242, any future expiry, any CVC, any zip. The real event flow fires — much more realistic than `stripe trigger`.

The CLI's webhook secret rotates each session

Every time you re-run `stripe listen`, you get a new whsec_. Re-paste it into .env.local and restart dev. If signature verification suddenly starts failing during a session that was working, that's why.

Production uses a different webhook secret

The whsec_ from `stripe listen` is for local dev only. When you create the production webhook endpoint in the Stripe dashboard (Developers → Webhooks → Add endpoint), Stripe gives you a SEPARATE whsec_ for it. That goes in your prod env vars. Mixing them up means prod verification fails silently.

Replay an event from the dashboard

If a handler throws and you've fixed the bug, you don't need to redo the checkout flow. Open Developers → Events in the Stripe dashboard, find the event, click "Resend". Stripe POSTs it again to your webhook URL. Test mode events can be resent at any time.