Early access — use code HOOKSENSEWELCOME for 1 month free
9 min read

How to Debug Stripe Webhooks in 2026

Master Stripe webhook debugging with practical techniques. Learn to trace failures, inspect payloads, handle retries, and use HookSense for real-time webhook inspection.

StripeDebuggingWebhooks
O

Ozer

Developer & Founder of HookSense

Stripe webhooks are the nervous system of any payment integration. They tell your application when a charge succeeds, a subscription renews, a dispute is filed, or a payout lands. But when something goes wrong — and it will — debugging webhooks can feel like chasing ghosts. The request arrived, something failed, and you have no idea what the payload looked like or why your handler choked.

This guide covers practical, battle-tested techniques for debugging Stripe webhooks in 2026. Whether you are building your first checkout flow or maintaining a mature billing system, these strategies will save you hours of frustration.

Understanding the Stripe Webhook Lifecycle

Before diving into debugging, it helps to understand exactly what happens when Stripe sends a webhook:

  1. An event occurs in your Stripe account (e.g., a payment succeeds).
  2. Stripe creates an Event object with a unique ID, type, and nested data.object containing the relevant resource.
  3. Stripe sends an HTTP POST to each registered endpoint URL with the Event as JSON in the body.
  4. Your server has 20 seconds to respond with a 2xx status code. If it does not, Stripe marks the delivery as failed.
  5. Stripe retries failed deliveries with exponential backoff — up to 3 days for live mode and 3 hours for test mode.

Most debugging problems fall into one of four categories: the webhook never arrives, the signature verification fails, the handler throws an error, or the response times out.

Problem 1: Webhooks Not Arriving

If your endpoint is not receiving any events at all, check these items first:

  • Endpoint URL: Open the Stripe Dashboard, navigate to Developers → Webhooks, and verify the URL is correct. A trailing slash mismatch (/webhooks vs /webhooks/) can cause a 404.
  • Event selection: Make sure you have subscribed to the specific events you expect. If you only selected checkout.session.completed, you will not receive payment_intent.succeeded.
  • Endpoint status: Stripe disables endpoints that fail consistently. Check if your endpoint shows a red "Disabled" badge in the dashboard.
  • Firewall rules: If your server sits behind a WAF or CDN, Stripe's IP ranges might be blocked. Stripe publishes their webhook IP ranges in their documentation.

Problem 2: Signature Verification Failures

Stripe signs every webhook with a secret unique to each endpoint. The most common signature verification mistakes are:

// WRONG: Using parsed JSON body
app.post('/webhooks', express.json(), (req, res) => {
  // req.body is already parsed — signature check will FAIL
  stripe.webhooks.constructEvent(JSON.stringify(req.body), sig, secret);
});

// CORRECT: Using raw body
app.post('/webhooks', express.raw({ type: 'application/json' }), (req, res) => {
  // req.body is a Buffer — signature check will pass
  stripe.webhooks.constructEvent(req.body, sig, secret);
});

Key takeaway: The signature is computed against the exact bytes Stripe sent. If your framework parses the body before your verification code runs, the bytes change, and the signature no longer matches. Always verify against the raw body.

Other common causes include using the wrong endpoint secret (each endpoint has its own whsec_... key) and clock skew beyond the 5-minute tolerance window.

Problem 3: Handler Errors

Your endpoint receives the webhook, verifies the signature, but then your business logic throws an error. These are the hardest bugs to catch because Stripe considers the delivery successful as long as you return a 2xx — even if your handler crashes afterwards in an async process.

Best practices for handler debugging:

  • Return 200 immediately, then process: Acknowledge receipt before running business logic. This prevents timeouts and gives you time to process.
  • Log the full event: Store the raw JSON payload in your database or logging system before processing. If something fails later, you have the original data.
  • Use idempotency keys: Stripe may send the same event multiple times during retries. Use the event ID (evt_...) to deduplicate and avoid processing the same charge twice.
  • Handle event types explicitly: Use a switch statement and log unhandled types. A catch-all that silently ignores unknown events will hide bugs.

Problem 4: Timeouts

If your handler takes more than 20 seconds, Stripe considers the delivery failed and schedules a retry. This commonly happens when your handler makes slow external API calls, runs heavy database queries, or sends emails synchronously.

The fix: acknowledge the webhook immediately and move heavy processing to a background job queue (Bull, SQS, Celery, etc.).

Using the Stripe Dashboard for Debugging

The Stripe Dashboard provides built-in webhook debugging under Developers → Webhooks → [Your Endpoint]:

  • Event deliveries: Shows every attempt with status code, response body, and timing.
  • Resend: You can manually resend any event from the dashboard — useful for retesting after a fix.
  • Event data: Click any event to see the full JSON payload.

This is useful but limited. You cannot search across events, compare payloads side by side, or forward events to your local machine.

Debugging with HookSense

HookSense fills the gaps that the Stripe Dashboard leaves open. Here is a workflow that has saved us countless hours:

Step 1: Create a HookSense Endpoint

Sign up at hooksense.com and create a new endpoint. Copy the URL (e.g., https://hooksense.com/w/abc123).

Step 2: Add It as a Stripe Webhook

In your Stripe Dashboard, add the HookSense URL as a new webhook endpoint. Select the events you want to debug. You can keep your production endpoint active — Stripe sends events to all registered endpoints.

Step 3: Inspect in Real Time

Open HookSense in your browser. Every webhook from Stripe appears instantly via WebSocket — no refreshing required. You see headers, the full JSON body with syntax highlighting, and the response status.

Step 4: Forward to Localhost

Run the HookSense CLI to forward every captured webhook to your local development server:

npx hooksense listen -p 3000

Now you can set breakpoints in your IDE, step through your handler code, and see exactly where things go wrong — all with real Stripe payloads.

Step 5: Replay After Fixes

Found and fixed the bug? Click the replay button on any captured webhook to send it again. No need to trigger a new Stripe event or ask a colleague to make a test purchase.

Stripe Webhook Debugging Checklist

CheckWhat to verify
Endpoint URLCorrect URL, no trailing slash mismatch
Event selectionSubscribed to the right event types
Raw bodySignature verification uses raw bytes, not parsed JSON
Endpoint secretUsing the correct whsec_... for this specific endpoint
Response timeHandler responds within 20 seconds
IdempotencyDeduplicating by event ID to handle retries safely
Error handlingCatching exceptions and logging before returning 200
Endpoint statusNot disabled in Stripe Dashboard due to repeated failures

Conclusion

Webhook debugging does not have to be painful. Most issues come down to a handful of common mistakes: wrong URL, parsed body, missing event types, or slow handlers. With structured logging, a solid checklist, and a tool like HookSense that gives you real-time inspection and replay, you can diagnose and fix webhook issues in minutes instead of hours.

Related

Try HookSense Free

Inspect, debug, and replay webhooks in real-time. No credit card required.

Get Started Free