Debug webhooks without triggering the same event again.
Capture webhooks once, forward them to multiple destinations, replay failures locally, test edge cases, and turn fixes into regression tests.
Free plan, no card. Anonymous endpoints work without an account.
POSTpayment.completed
500184 msevt_8f21
Production delivery failed
HookWatcher
- Captureexact bytes, headers, signature
- Inspect500 · customer.email missing
- Replayto localhost via hwcli
localhost:3000your code
Inspect webhooks locally
Expose your local application through a public HTTPS URL and inspect incoming webhook requests without deploying.
- External requestStripe, GitHub, any HTTP client
- Public HookWatcher URLacme.hookwatcher.com
- HookWatcher serverroutes it to your tunnel
- hwcli tunneloutbound, encrypted connection
- Your local applocalhost:3000
- hwcli opens the connection from your machine, so there is no port forwarding and no deploy for each test.
- Your app answers each request, and the caller gets its real response.
- hwcli records every request in its local inspector on
127.0.0.1; HookWatcher doesn't keep tunnel requests. - How tunnels work
Content-Type: application/json · Stripe-Signature: t=…,v1=…
{
"type": "payment_intent.succeeded",
"data": {
"object": {
"id": "pi_example123",
"amount": 2499,
"status": "succeeded"
}
}
}One webhook in. Every destination gets it.
HookWatcher receives your webhook once and forwards it to production, staging, local development, QA or any configured endpoint, while tracking each delivery independently.
- Production
- Staging
- QA
- Local Development
- Microservice
- Backup Processor
Incoming · Stripe
POSTpayment.completed
evt_8f21
HookWatcher
1 event received
stored once, unchanged
4 deliveries
Production API200 ✓82 ms
api.example.com/webhooks
Staging API200 ✓312 ms
staging.example.com/webhooks#1 500#2 500#3 200
Local DevelopmentCLI200 ✓43 ms
hwcli · localhost:3000/webhooks
QA Environment202 ✓103 ms
qa.example.com/hooks
4 destinations4 delivered1 retried
- 1 incoming event
- 1 stored event, never changed
- 1 delivery per destination
- independent attempts
- Production APIhttps://api.example.com/webhooksActive
- Staginghttps://staging.example.com/webhooksActive
- Local DevelopmenthwcliCLI session · MacBook Pro → localhost:3000/webhooksOnline
- QA Servicehttps://qa.example.com/hooksActive
| Production | 200 | 82 ms | |
|---|---|---|---|
| Staging | 200 | 312 ms | 3 attempts |
| Localhost | 200 | 41 ms | |
| QA | 202 | 103 ms |
Send again to one destination — the others are not resent
- Production
- Staging
- Localhost(selected)
- QA
Send again to Localhost
Stop configuring the same provider webhook four times.
Point the provider at HookWatcher once, then route the event to every service and environment you need. One public webhook URL, multiple destinations behind it.
- Independent delivery status
- Automatic retries
- Per-destination history
- Local CLI forwarding
- Send again to any destination
- Centralized debugging
Forwarding destination limits vary by plan. See pricing
Without HookWatcher
Provider ├── webhook → Production ├── webhook → Staging ├── webhook → QA └── webhook → Local tunnel
- A provider configuration per environment
- A different signing secret for each
- The tunnel URL changes
- Deliveries are hard to trace
With HookWatcher
Provider ↓ HookWatcher ├── Production ├── Staging ├── QA └── Localhost (hwcli)
- One webhook configuration
- Independent delivery tracking and retries
- Central history for every destination
- Local development without a tunnel
From a failed webhook to a permanent test, in six steps.
Every step happens on the event your provider already sent. Nothing is triggered twice.
The exact request, stored once.
Delivered to every destination.
See what each destination answered.
Send it to your machine again.
Change code and replay until it passes.
The fix becomes a regression test.
Stop re-triggering the provider to reproduce a bug.
Reproducing a webhook bug usually means making the provider send it again. With HookWatcher you keep the real request and replay it whenever you need.
Without HookWatcher
- 1Trigger the event in the provider
- 2Wait for it to arrive
- 3Search the logs
- 4Copy the payload
- 5Change code
- 6Trigger the provider again
Repeat for every attempt, waiting on the provider each time.
With HookWatcher
- 1Capture once
- 2Replay instantly
- 3Fix locally
- 4Replay again
- 5Save as a test
The provider sends the event once. Everything after happens on your machine.
Try it with a real endpoint
Send any HTTP request to the URL below, or press Send test, and watch it arrive. No account needed; anonymous endpoints keep their last 100 requests for 2 days.
A development environment for webhook integrations.
Capture once. Replay whenever you need.
Send a captured production event to your local server as often as you like: same method, path, headers, signature and raw body. Replay Locally reaches the machine running hwcli; Replay to URL reaches staging.
- Byte-exact by default; no headers added
- Replays to production-looking hosts ask first
Production eventevt_8f21Replay Locallylocalhost:3000/webhooks200 OKChange one field and replay the edge case.
Modify & Replay changes JSON fields, headers, query or method, shows original and modified side by side, and sends the result. The captured event stays exactly as it was.
- hwcli replay --set amount=null --header 'X-Test:1'
- Re-sign the modified body with your stored secret
Modify & Replayoriginal stays unchanged OriginalModifiedamount: 2999amount: nullcurrency: "USD"currency: "INR"customer.email: "[email protected]"customer.email: "[email protected]"2 fields changedReplay422 · amount is required
Replay until it passes. Keep the proof.
A Debug Session records every attempt against your local code. When the handler returns 2xx, save that request and response as a regression test.
- hwcli debug evt_8f21 --forward :3000/webhooks
- Attempts appear in the terminal and the dashboard
Debug Sessionevt_8f21 → localhost:3000 - Replay #1500
- Replay #2500
- Replay #3200 ✓
Save as Regression Test
Test what providers really do.
Replay Lab turns one event into duplicates, concurrent deliveries, delays, bursts, invalid signatures and malformed bodies, so idempotency and validation bugs show up before production does.
- Every Lab delivery is marked synthetic
- Limits follow your plan
Replay Labmarked synthetic - Duplicate
- ×10
- Concurrent
- ×20
- Delay
- 5s
- Burst
- 100
- Invalid signature
X-HookWatcher-Synthetic: replay-lab
See why one event failed and the other didn't.
Compare a failed event with the most similar successful one: missing fields, changed values and type changes first, volatile IDs and timestamps hidden.
- hwcli diff evt_123 evt_456
- Credential values are never shown
Event Diffvolatile fields hidden Turn real events into regression tests.
Tests store the exact request and the response your handler should give. Run them from the dashboard, your terminal or CI.
- Status, latency, JSON subset and path assertions
- YAML definitions you can keep in your repo
$ hwcli test run✓ payment-success✓ subscription-renewal✓ refund-created3 passed
See what broke in production, then fix it locally.
The Failures inbox collects failed deliveries, replays and tests across a workspace. Every event keeps its full timeline: what arrived, what your server answered, and every replay after it.
- payment.failed50012 min ago
- checkout.completedtimeout1 h ago
- order.created429retrying
Timeline for evt_8f21
11:42:01
Webhook received
11:42:01
Forward attempt #1
11:42:02
500 Internal Server Error
11:43:18
Replay locally
11:43:18
500
11:45:04
Replay locally
11:45:04
200 ✓
11:45:10
Regression test created
The original event remains unchanged.
Replays, modified replays, debug sessions, diffs and tests are derived records linked to the captured event. You can always go back to exactly what the provider sent.
- Delivery
- Attempt #1
- Attempt #2
- Replay
- Modified Replay
- Debug Session
- Event Diff
- Regression Test
Byte for byte
Bodies are stored exactly as received, with headers in their original order and a SHA-256 fingerprint.
Changes are deltas
A modified replay stores what you changed, not a second copy of the payload.
Every action is attributed
Who replayed what, when and to where, from the dashboard, hwcli or CI.
Built for your terminal.
hwcli is one self-contained binary. Sign in once in the browser; then listen, replay, diff and test from wherever your code runs, including CI with an API key, and open tunnels to services on your machine.
A public HTTPS URL for localhost
When a caller needs your local app's real answer (OAuth callbacks, URL verification, demos), run a tunnel. hwcli opens an outbound connection to HookWatcher, so there is no port forwarding, and requests are recorded only in hwcli's local panel.
How tunnels work$ hwcli tunnel http 3000 --name payment-test Status ● Connected Public URL https://payment-test.hookwatcher.com Local target http://127.0.0.1:3000
Install with Homebrew or Scoop, or download the latest version for your platform. CLI documentation
A fixed bug stays fixed.
Save the event that broke as a test with the response your handler should give. hwcli test run sends each one to your app in CI and fails the build when a webhook regresses.
- ✗ payment-successExpected: 200
Received: 500 - ✓ refund-created
- ✓ order-created
- ✓ subscription-renewal
23 passed1 failedexit 1
- Tests come from real captured events, or YAML files in your repository.
- Assert status, latency, JSON fields and signature handling.
- JUnit output and clear exit codes for GitHub Actions, GitLab CI, Jenkins and Bitbucket.
More than a webhook catcher.
Seeing a request arrive is where HookWatcher starts. The rest of the loop is what fixes the bug.
A basic webhook catcher
- Capture
- Inspect
HookWatcher
- Capture
- Inspect
- Replay
- Debug
- Test
- CI
Know when providers change their payloads.
Secondary to debugging, but it saves days: HookWatcher learns each event's structure and tells you when a field changes type or disappears. Secrets stay masked everywhere, including links you share.
customer.phone
Previously
string | null
Now
object
Compare PayloadsAccept ChangeIgnore Field
- Authorization:
- ••••••••••••••••
- access_token:
- ••••••••••
What a shared link shows: secrets redacted
Share debugging context without exposing secrets.
How HookWatcher handles your dataFrom local debugging to team-wide reliability.
Invite your team to a workspace. Developers replay and debug, viewers inspect, admins manage endpoints and settings, and every action is in the activity log.
- Shared workspaces
- Event lineage
- Audit trail
- Redaction
- Role-based access
- Longer retention
- Failure visibility
- Enterprise custom limits
Works with any service that sends webhooks.
These providers are recognized automatically from their headers and payloads; signatures are verified for Stripe and GitHub. Anything that can send an HTTP request works.
- Stripe
- GitHub
- Shopify
- Twilio
- Razorpay
- PayPal
- Slack
- Discord
- Any HTTP sender
Start free. Upgrade for more history and limits.
Compare every limitFree
$0
Try it and debug on your own
10 days request retention
2 forwarding destinations
Developer
$5/mo
For side projects and one integration
30 days request retention
3 forwarding destinations
ProRecommended
$12/mo
For individual developers
60 days request retention
5 forwarding destinations
Team
$39/mo
For engineering teams
90 days request retention
10 forwarding destinations
Enterprise
Custom
Custom scale, security and support
Custom request retention
Custom forwarding destinations
Contact Sales
Stop triggering the same webhook again and again.
Capture it once. Replay it locally. Fix the bug. Turn the fix into a test.
- CapturedPOST payment.completed
- Replayed locally500 → 200 OK
- Saved as test✓ payment-success