>
Developer Guide

How to debug webhooks locally

March 2026 · 8 min read

Webhooks are one of those things that work perfectly until they don't, and when they don't, figuring out why is genuinely annoying. The payload arrives on the sender's side, disappears into your network, and you have no idea if it reached your handler, what it contained, or why your code didn't react to it.

This is a practical guide to setting up a webhook debugging workflow that actually works.

The core problem

Most webhook debugging problems come down to one of three things:

The fix for all three is the same: you need something that captures the raw incoming request before your application code touches it, so you can inspect exactly what arrived and replay it when needed.

Option 1: A public tunnel (Ngrok, etc.)

The most common approach is to run a tunnel like Ngrok that exposes your localhost to the public internet. This works but has real downsides:

For payment events or anything with PII, sending those payloads through a third-party tunnel should make you uncomfortable.

Option 2: Self-host a webhook inbox

A better approach for local development: run a small webhook receiver on your machine that captures everything, and configure your webhook sender to point at it during development.

Corral is a single Go binary that does exactly this. Install it, run it, create an endpoint, and you get a URL like http://localhost:8760/hook/ep_abc123 that captures every incoming request.

curl -fsSL https://stockyard.dev/corral/install.sh | sh

DATA_DIR=./data corral

# In another terminal:
curl -s -X POST http://localhost:8760/api/endpoints \
  -H 'Content-Type: application/json' \
  -d '{"name":"stripe-dev"}'
# → {"hook_url":"http://localhost:8760/hook/ep_abc123",...}

Point your webhook sender at that URL. Every request is stored in SQLite locally, inspectable via API or the dashboard at http://localhost:8760/ui.

Inspecting what arrived

Once requests are captured, you can inspect headers, body, and metadata without running your application code at all:

# List events for an endpoint
curl -s http://localhost:8760/api/endpoints/ep_abc123/events | jq .

# Get full event detail
curl -s http://localhost:8760/api/events/evt_xyz | jq .

This gives you the exact payload Stripe (or GitHub, or whoever) is actually sending — not what you think they're sending. The number of times the payload format differs from the documentation is higher than you'd expect.

Replaying failed events

This is where the workflow pays off. Once you've fixed your handler code, you don't need to re-trigger the event from the sender. Replay it directly against your local handler:

curl -s -X POST http://localhost:8760/api/events/evt_xyz/replay \
  -H 'Content-Type: application/json' \
  -d '{"target":"http://localhost:3000/webhooks/stripe"}'

The event is sent to your handler with the original headers and body. You can replay it as many times as you need while iterating on your code.

Setting up auto-forwarding

Once your handler is working, you can configure Corral to automatically forward incoming events to it — so Corral becomes a permanent capture layer in your development stack:

curl -s -X POST http://localhost:8760/api/endpoints/ep_abc123/forwards \
  -H 'Content-Type: application/json' \
  -d '{"target_url":"http://localhost:3000/webhooks/stripe","retry_count":3}'

Corral forwards every incoming webhook to your handler, retries on failure, and logs every delivery attempt. You keep the capture history for debugging without changing how your application receives events.

On production

The same binary works in production. Run it on your server, set DATA_DIR to a persistent path, and put it behind your existing reverse proxy. For teams, Corral Pro ($0.99/mo) removes the endpoint and event limits and adds 90-day retention, so you have history when a production webhook fails at 3am.

If your application is an LLM application and you need more than webhook debugging — request tracing, cost tracking across LLM providers, model routing — Stockyard is the full platform that handles all of that in one binary.

Corral overview  ·  Corral vs Hookdeck  ·  Corral vs webhook.site  ·  Corral docs

Try Corral free.

Single binary. Captures, inspects, replays. 30 seconds to install.

Install Corral Learn more