DEV Community

Ben Nguyen
Ben Nguyen

Posted on

How I debug Stripe webhooks locally without losing my mind

Every developer who has integrated Stripe payments has been here:

You're building a subscription feature. Stripe fires a customer.subscription.updated event. Your handler isn't working. And you have absolutely no idea why.

So you start the ritual:

  1. Open Stripe dashboard
  2. Find the event under Developers → Webhooks
  3. Click through 3 screens to see the payload
  4. Copy the JSON into a Notion doc (or a random .txt file on your desktop)
  5. Stare at it
  6. Make a change
  7. Go back to Stripe, trigger another test event
  8. Repeat

If you've done this more than twice, you know how painful it is. And the worst part? You can't easily replay that event to your localhost.


The real problem with debugging webhooks locally

Stripe CLI helps — stripe listen --forward-to localhost:3000/webhook is genuinely useful. But it has real limitations:

  • You lose all history the moment you close the terminal
  • You can't replay a specific past event without digging through Stripe dashboard again
  • If something breaks at 3am in production, good luck reconstructing what payload came in

The feedback loop is just too slow. Trigger event → dig through dashboard → copy payload → fix code → repeat. Every cycle takes 2–3 minutes.

Over time, this adds up. And it's completely unnecessary friction.


What I wanted instead

I wanted something simple:

  • A URL I can paste into Stripe in 20 seconds
  • Events show up live the moment they arrive — no refresh, no polling
  • I can click replay and that exact payload hits my localhost
  • History is saved so I can debug yesterday's 3am anomaly today

I looked around. Hookdeck and Svix exist, but they're focused on webhook infrastructure and reliability — queuing, retries, fan-out. That's great, but overkill when I just want to see what the hell is coming in and replay it.

So I built PeekAt.


How PeekAt works

The flow is dead simple:

1. Get your endpoint

Sign up, copy your unique URL:

https://peekat.dev/wh/a7f2k9
Enter fullscreen mode Exit fullscreen mode

2. Paste it into Stripe

Go to Stripe Dashboard → Developers → Webhooks → Add endpoint. Takes 20 seconds.

3. Trigger an event

Make a test payment, or use Stripe CLI:

stripe trigger payment_intent.succeeded
Enter fullscreen mode Exit fullscreen mode

4. See it live

The event streams instantly to your PeekAt dashboard — full headers, body, timestamp, signature. No refresh needed.

5. Replay to localhost

Click replay. The exact same payload hits your local dev server:

→ localhost:3000/webhook
Enter fullscreen mode Exit fullscreen mode

Fix your handler. Replay again. Done.


The part that saves the most time

The replay feature sounds simple but it changes the workflow completely.

Before: fix code → go back to Stripe → trigger new test event → wait → check result.

After: fix code → click replay in PeekAt → check result immediately.

You're iterating on the same payload every time. No new test payments, no new Stripe events, no hunting through dashboards. Just fix and replay.

This is especially useful for edge cases — payment_intent.payment_failed with a specific decline code, or customer.subscription.deleted with a particular metadata structure. You don't want to keep triggering those manually.


What's coming next

PeekAt is in early access right now. The core flow (receive → inspect → replay) is working. Coming soon:

  • Smart event detection — auto-detect Stripe event type, show the handler code skeleton you need
  • CLI tool — route webhooks to localhost without any tunnel setup
  • Team workspaces — shared endpoint for your whole team
  • Slack/email alerts — get notified when your endpoint returns non-2xx

Try it

If you've felt this pain, I'd genuinely love your feedback.

👉 peekat.dev — free tier available, no credit card needed.

What webhook debugging pain points am I missing? Drop a comment — building this in public and all feedback directly shapes what gets built next.


Built with Node.js + Fastify + PostgreSQL + WebSockets. Deployed on Railway.

Top comments (0)