How to Test Stripe Webhooks Without Deploying to Production

Published: (February 8, 2026 at 01:37 PM EST)
3 min read
Source: Dev.to

Source: Dev.to

Approach 1: Stripe CLI

The official way is to install the Stripe CLI, log in, and forward events to your local server:

stripe login
stripe trigger payment_intent.succeeded

Pros

  • Quick setup.

Cons

  • Mock events contain generic data (placeholder customer IDs, amounts).
  • The tunnel dies when you close the terminal.
  • Each restart generates a new signing secret, breaking signature verification until you update your .env.
  • If your handler returns a 500, the CLI output doesn’t clearly show the error.

Approach 2: ngrok

Expose your local server directly with ngrok:

ngrok http 3000
  • Paste the generated public URL into Stripe’s webhook settings.
  • You receive real events from test‑mode payments, which is better than mock data.

Drawbacks

  • The free URL changes each session, requiring you to update Stripe’s dashboard repeatedly.
  • If your handler crashes mid‑request, the webhook is lost; you must wait for Stripe’s exponential backoff retries or manually reconstruct the payload.
  • Closing ngrok erases the request history.

Approach 3: Capture First, Process Later

Instead of pointing Stripe at your local server, point it at a persistent endpoint that captures and stores every webhook. Then replay the captured payloads to your localhost when you’re ready.

Create an endpoint

curl -X POST https://hooklab-webhook-testing-and-debugging.p.rapidapi.com/api/v1/endpoints

The response includes a public URL, e.g.:

https://hooklab-webhook-testing-and-debugging.p.rapidapi.com/hook/ep_V1StGXR8_Z5j

Paste this URL into Stripe’s webhook settings.

Send a test payment

Use the Stripe Dashboard with the test card 4242 4242 4242 4242. Stripe sends the webhook, and HookLab captures it.

Inspect the captured request

curl https://hooklab-webhook-testing-and-debugging.p.rapidapi.com/api/v1/endpoints/ep_V1StGXR8_Z5j/requests

The response shows full headers, body, Stripe-Signature, timestamp, etc., eliminating the need for console‑log debugging.

Replay to your local server

curl -X POST https://hooklab-webhook-testing-and-debugging.p.rapidapi.com/api/v1/replay \
     -d '{"url":"http://localhost:3000/api/webhooks/stripe"}'

The replay uses the same headers, body, and HTTP method, sending the request straight to your handler. If it crashes, fix the bug and replay again—no waiting for Stripe’s retry logic.

Why Capture‑and‑Replay Is Worth It

The three most common Stripe webhook bugs become easier to spot:

  1. Wrong event types – You might handle charge.succeeded while Stripe sends payment_intent.succeeded. Capturing a checkout flow reveals every event Stripe fires, in order.
  2. Data‑structure surprises – Accessing event.data.object.customer.email fails if customer is a string ID rather than an expanded object. Real captured payloads show the exact structure before you write the handler.
  3. Unexpected fields – Occasionally Stripe adds new fields; having the real payload lets you adapt quickly.

Gotchas Everyone Encounters

  • Return 200 OK immediately. Stripe expects a response within 5–10 seconds. Perform heavy processing asynchronously; otherwise Stripe treats the delivery as failed and retries, causing duplicate events.
  • Test with real test‑mode transactions. The stripe trigger command is fine for checking endpoint reachability, but your integration isn’t truly tested until you process webhooks from actual test checkouts, as the payloads differ in subtle but important ways.

Getting Started with HookLab

HookLab offers a free tier on RapidAPI (100 calls/day and 3 endpoints), which is sufficient for most Stripe integration testing.

What’s your webhook testing setup? Feel free to share your approach in the comments.

0 views
Back to Blog

Related posts

Read more »

A Beginner’s Guide to Testing in Go

Tests Enforce Contracts Now right off the bat, you don’t want to get this wrong. When writing tests, the key thing to keep in mind is that we should treat what...