Why Webhook Watchtower
Every team receiving webhooks ends up building the same thing: an ingest endpoint, a log, retries, signature checks. Here's the case for not building it yourself.
Every team that consumes webhooks eventually builds the same pile of plumbing. An endpoint to receive them. A table to log what arrived. Some retry logic when your own service is down. A signature check so you're not processing forged events. Then a way to replay the one that failed at 2am.
None of it is hard. All of it is fiddly, easy to get subtly wrong, and never the thing you actually wanted to be working on. I built Webhook Watchtower so you don't have to build it again.
What "just add an endpoint" actually costs
"We'll just add a webhook endpoint" sounds like an afternoon. It turns into a quarter, because the endpoint is the easy ten percent.
Your endpoint has to store the payload before it does anything else, then return a 2xx fast. Providers give up quicker than you'd expect, so if you process the event inline and your database has a slow second, the event is gone and the provider's dashboard still says delivered. Now you're forwarding it to your own service, which will sometimes be down, so you need a real queue with retries and backoff behind it, not a setTimeout. Botch the backoff and a two-minute outage becomes a thundering herd the moment you recover.
Then there's verification, and every provider signs differently. Stripe, GitHub and Shopify each have their own scheme, and if you rush the raw-body handling you'll start bouncing legitimate traffic. Skip it and anyone who finds the URL can post whatever they like.
You need a log you can actually search, because "did this event arrive?" should take five seconds, not a grep across two services and a timeline that never quite lines up. And you need replay, because when something fails at 2am the honest answer can't be "email the provider and hope." Re-sending safely means not double-processing what already went through, which is its own small problem to solve.
None of this is hard, which is why it always gets waved through in planning. The bill comes later. You own it, you monitor it, you carry the pager for it, and it never shows up as anything a customer can see.
What you get instead
Point your provider at a Watchtower ingest URL and every one of those pieces is already there, in production, tested.
Nothing gets lost, nothing gets processed twice
Every event is captured in full (headers, raw body up to 10 MB, method, timestamp) the instant it lands, before any forwarding happens. Re-deliveries are detected automatically: exact event-ID match for Stripe, GitHub and Shopify, body-hash matching for custom sources. Duplicates are stored but never forwarded, and never counted against your usage. The idempotency problem that bites everyone building this themselves is just handled.
Delivery that survives your endpoint being down
Forwarding runs through a real queue with per-plan retries and fixed waits of 1 minute, 5 minutes, 30 minutes, and 2 hours. If your service is having a bad five minutes, deliveries retry on a sensible schedule instead of hammering you the second you're back.
| Plan | Attempts | Schedule |
|---|---|---|
| Scout | 1 | Manual replay only |
| Guard | 3 | 1 min, 2 min |
| Sentinel | 5 | 1 min, 2 min, 4 min, 8 min |
| Bastion | 5 | 1 min, 2 min, 4 min, 8 min |
When every attempt is exhausted you get an email and an in-app notification, and the event stays stored so you can replay it whenever you're ready. A separate reconciler sweeps every five minutes for anything accepted but never picked up, and re-enqueues it, so an event can't quietly fall through the gap between "received" and "delivered."
Signature verification you didn't have to write
Stripe, GitHub, and Shopify signatures are handled natively; anything else uses custom HMAC-SHA256. Every event is stamped Verified, Failed, or Skipped, with the reason recorded. Turn on quarantine mode and events that fail verification are stored for inspection but never forwarded to your endpoint. Pick your provider from a card grid when you create a source and the signing config is filled in for you.
Replay: one event or a whole backlog
Any event replays in one click from its detail view. After an outage, select a range and replay every failed delivery at once. Every replay records who triggered it, so there's never any ambiguity about what got re-sent.
A timeline instead of a grep
Events stream into the dashboard live as they arrive, with no polling and no refresh, which makes setting up a new integration genuinely pleasant. Every delivery attempt is recorded with its exact response code, body, timing, and a structured error category (connection error, timeout, HTTP 4xx, HTTP 5xx). Diagnosing a failure pattern takes seconds.
The operational things you'd never get around to building
- Audit log - every create, delete, token rotation, and replay recorded with who did it and a before/after diff.
- Soft delete - sources and destinations are recoverable, not gone on the first click.
- SSRF protection - destination URLs are validated at save and delivery time, redirects re-checked at every hop, connections pinned to the validated IP. A webhook can't be tricked into hitting your internal network.
- Outgoing signatures - every forwarded request carries an HMAC signature and timestamp so your endpoint can trust what Watchtower sends.
- Sensitive-data masking - hide auth headers and payload fields in the viewer while the raw data is preserved for forwarding.
- Usage alerts, team workspaces with roles, in-app notifications - the rest of the things a real product needs.
Any one of these is a ticket you'd keep pushing down the backlog. All of them ship on day one.
Why I made it
I kept rebuilding this. Every job, the same rough ingest route, the same basic logging, the same "we should really add retries" note that never got picked up. It was always the last thing prioritised and the first thing to break silently: no exception in the logs, just a customer emailing to say something didn't happen, and an hour lost reconstructing what went wrong.
At some point the honest move was to build it properly, once, as a product you could point anything at. That's what this is. It's the tool I wanted every time a webhook failed and I had nothing to look at.
What it costs
Four tiers, monthly or annual, no surprises.
| Plan | Price | Events/month | Retention |
|---|---|---|---|
| Scout | Free | 10,000 | 1 day |
| Guard | £19/mo | 100,000 | 7 days |
| Sentinel | £59/mo | 500,000 | 30 days |
| Bastion | £149/mo | 2,000,000 | 90 days |
Scout is free forever, no card required. It's enough to run the product against a real integration and see the difference before you decide anything. Set against even a single engineer-day of building and maintaining your own ingest-and-replay stack, Guard pays for itself the first time a webhook fails and you already know exactly what happened.
Try it
Stop rebuilding the plumbing. Point one source at Watchtower and watch your webhooks arrive in real time.
Questions first? Email hello@webhookwatchtower.co.uk. I read every one.
Share this post
Webhook Watchtower
Stop debugging webhooks in logs.
Capture every event, replay failures, and get alerted when deliveries fail, without changing your existing setup.
Try it free →