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:
- Open Stripe dashboard
- Find the event under Developers → Webhooks
- Click through 3 screens to see the payload
- Copy the JSON into a Notion doc (or a random
.txtfile on your desktop) - Stare at it
- Make a change
- Go back to Stripe, trigger another test event
- 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
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
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
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)