Home / Webhook Testing

To test webhooks locally: (1) install the Stripe CLI or use ngrok to expose your local server, (2) forward events to your local endpoint, (3) use the platform's test event trigger to send a real event. For production testing, use the platform's redeliver feature in the delivery log. After testing, set up monitoring so you know immediately when production deliveries fail.

How to Test Webhooks Locally (Stripe CLI, ngrok, smee.io)

· 8 min read

Webhooks are hard to test because they require a publicly reachable HTTPS endpoint. Your localhost:3000 isn't accessible to Stripe or Shopify. This guide covers the fastest way to get real webhook events hitting your local server for each platform, and what to do after go-live.

Why Is Testing Webhooks Difficult?

Three things make webhook testing awkward compared to testing regular code:

The tools below solve all three by creating an authenticated tunnel and forwarding real platform events to your local server.

Also review the webhook best practices guide before testing — knowing what to test (signature verification, idempotency, response time) makes your tests more meaningful.

How Do You Test Stripe Webhooks Locally?

The Stripe CLI is the best tool for this. It's official, handles signature forwarding automatically, and lets you trigger specific event types on demand.

Step 1: Install the Stripe CLI

# macOS
brew install stripe/stripe-cli/stripe

# Linux
curl -s https://packages.stripe.dev/api/security/keypair/stripe-cli-gpg/public | gpg --dearmor | sudo tee /usr/share/keyrings/stripe.gpg
echo "deb [signed-by=/usr/share/keyrings/stripe.gpg] https://packages.stripe.dev/stripe-cli-debian-local stable main" | sudo tee -a /etc/apt/sources.list.d/stripe.list
sudo apt update && sudo apt install stripe

Step 2: Log in and start forwarding

stripe login
stripe listen --forward-to localhost:3000/webhook

The CLI prints a webhook signing secret (whsec_xxx) — copy this into your local .env as STRIPE_WEBHOOK_SECRET. This is different from your production webhook secret. The CLI generates a session-specific secret that matches the signatures on forwarded events.

Step 3: Trigger a test event

# In a second terminal
stripe trigger payment_intent.succeeded
stripe trigger invoice.payment_failed
stripe trigger customer.subscription.deleted

The CLI sends a real Stripe event to your local endpoint with a valid signature. Your handler runs exactly as it would in production. See the Stripe integration guide for the full list of events worth testing.

How Do You Test Shopify Webhooks Locally?

Shopify doesn't have an official CLI equivalent for webhook forwarding. Use ngrok to expose your local server.

Step 1: Install and start ngrok

brew install ngrok
ngrok http 3000

ngrok prints a public HTTPS URL like https://a1b2c3d4.ngrok.io. This URL proxies to your localhost:3000.

Step 2: Register the ngrok URL as a Shopify webhook

Go to Shopify Admin → Settings → Notifications → Webhooks. Create a new webhook pointing at https://a1b2c3d4.ngrok.io/webhook. Copy the signing secret from the same screen into your local .env.

Step 3: Send a test notification

Shopify has a "Send test notification" button next to each registered webhook. Click it — Shopify sends a real (test-mode) payload to your ngrok URL, which forwards it to your local server. The X-Shopify-Hmac-Sha256 header is populated with a valid signature.

ngrok free tier limitation: the public URL changes every time you restart ngrok. You'll need to update the Shopify webhook URL each session. ngrok paid plans give you a stable subdomain.

See the Shopify integration guide for the events most worth testing.

How Do You Test GitHub Webhooks Locally?

Use ngrok (same as Shopify) or smee.io — a free event forwarding service from GitHub's own tooling team.

Option A: smee.io (no install required)

npx smee-client --url https://smee.io/your-channel-id --target http://localhost:3000/webhook

Go to smee.io, click "Start a new channel", copy the URL. Use that URL as your GitHub webhook endpoint. Run the smee client locally — it forwards events from smee.io to your local server.

Option B: ngrok

ngrok http 3000

Paste the ngrok URL directly into GitHub repository or organization webhook settings (Settings → Webhooks → Add webhook). GitHub sends events directly to the ngrok URL, which proxies to your local server.

GitHub provides a "Recent Deliveries" panel in webhook settings — you can see each delivery attempt and use "Redeliver" to resend any event. This is useful for testing your handler against real payloads after initial setup.

See the GitHub integration guide for delivery log details.

What Should You Test in Your Webhook Handler?

Beyond "does the event arrive and get processed", test these specific scenarios:

What Does Testing Miss? Why You Still Need Production Monitoring?

Local testing validates your implementation under controlled conditions. It does not catch:

Webhook Guardian monitors your production delivery logs every 5 minutes via read-only OAuth and sends a Slack or email alert within 5 minutes of any failure — covering the gap between "works in testing" and "works in production".

FAQ: Webhook Testing

How do you test webhooks locally?
Use the Stripe CLI (stripe listen --forward-to localhost:3000/webhook) for Stripe — it handles signature forwarding automatically. For Shopify or GitHub, use ngrok (ngrok http 3000) to get a public HTTPS URL, paste it into the platform's webhook settings, then use the platform's test notification button. Both approaches deliver real platform payloads with valid signatures to your local server.
What is the Stripe CLI webhook command?
stripe listen --forward-to localhost:3000/webhook — this forwards all Stripe webhook events to your local endpoint. The CLI prints a signing secret (whsec_xxx) — use this as your STRIPE_WEBHOOK_SECRET env var for local testing. In a second terminal, run stripe trigger payment_intent.succeeded to fire a specific event type.
Does testing replace webhook monitoring?
No. Testing validates your implementation works under conditions you controlled and anticipated. Production monitoring catches failures caused by things testing cannot predict: bad deploys, database outages, upstream API changes, traffic spikes. Shopify also silently deletes webhook subscriptions after 19 consecutive failures — monitoring is the only way to catch this before the subscription is gone. You need both testing before go-live and monitoring after.

Testing done. Now monitor production. Start a free 14-day trial of Webhook Guardian — connect Stripe, Shopify, or GitHub via read-only OAuth and get alerted within 5 minutes of any production failure. See also: how webhook monitoring works and webhook glossary.