stripe
How to Test Stripe Webhooks Locally
Use the Stripe CLI to forward webhook events to localhost, trigger test events, and verify your handler and signing secret before you ship — step by step.
Your webhook handler runs on localhost, but Stripe can only deliver to a public HTTPS URL. The
Stripe CLI closes that gap: it opens an authenticated tunnel
from Stripe to your local server and can fire test events on demand — no ngrok, no deploying to
staging just to see a payload.
1. Install and log in
# macOS
brew install stripe/stripe-cli/stripe
stripe login
stripe login opens your browser to authorize the CLI against your Stripe account.
2. Forward events to your local server
Point the CLI at wherever your handler listens:
stripe listen --forward-to localhost:4242/webhooks/stripe
The command prints a webhook signing secret that starts with whsec_. This is different from
your Dashboard endpoint’s secret — use this one in your local environment while stripe listen is
running:
export STRIPE_WEBHOOK_SECRET=whsec_...
Now any event in your account (test mode) is forwarded to your local handler with a valid signature,
so your constructEvent verification runs against real, correctly signed payloads.
3. Trigger test events
Rather than clicking around the Dashboard to make something happen, fire events directly:
stripe trigger invoice.payment_succeeded
stripe trigger customer.subscription.deleted
stripe trigger invoice.payment_failed
Each trigger creates the underlying objects in test mode and sends the matching event to your
forwarded endpoint — a fast loop for exercising every branch of your handler.
4. Confirm it worked
- The
stripe listenterminal logs each event and the HTTP status your handler returned. Anything other than2xxmeans Stripe would retry in production — fix it now. - Add a log line in your handler for
event.typeand the resource ID so you can confirm the payload parsed. - Deliberately send an unsigned request (
curla raw JSON body) and confirm your endpoint rejects it. If it doesn’t, your signature verification isn’t wired up correctly.
Common gotchas
- Wrong signing secret. The
whsec_fromstripe listenis not the same as your Dashboard endpoint’s secret. Mixing them up is the top cause of “signature verification failed” locally. - Parsed body instead of raw. Verification needs the exact raw request bytes. If your framework JSON-parses the body first, verification fails — see the webhook events guide for the fix.
- Test vs live mode.
stripe triggerfires test-mode events. Make sure your keys and the CLI are in the same mode.
Once your handler passes locally, register a real endpoint in the Dashboard and swap in its signing secret — or skip endpoint maintenance entirely and let Notipus be the verified endpoint that posts each event straight to Slack.
Skip the local setup entirely
Notipus is a verified Stripe webhook endpoint out of the box — connect it and see real events in Slack in minutes, no tunnel or CLI required.
Start free