The idea
A lightweight reverse proxy you drop in front of any webhook receiver URL. It records every incoming request — headers, body, signature, timing — to a searchable log, forwards it to your real endpoint, and tracks the response. When a delivery fails or your endpoint was down, you replay the exact original payload (or an edited copy) from a web UI instead of asking the sender to retry or reconstructing the event by hand.
Why build this
Any team building on Stripe, GitHub, Shopify, Twilio, or a partner's custom webhook system knows the debugging loop: a webhook fails during a deploy, the provider's dashboard shows a redacted or truncated payload, and reproducing the bug means waiting for the same event type to fire again naturally. Most providers offer some replay UI, but it's provider-specific, often paywalled to higher tiers, and useless for internal or partner-to-partner webhooks that have no vendor dashboard at all. A single tool that captures raw payloads regardless of source solves this once, for every integration a company has.
Stack sketch
- Proxy/ingest: Go or Node (Fastify) service — accepts POST at
/hooks/:endpointId, streams the raw body to storage before touching it, then forwards synchronously with the original headers. - Storage: Postgres for metadata (status, timing, endpoint config) plus payload bodies stored as JSONB or in object storage (S3/MinIO) if payloads are large or binary.
- Queue: a small internal retry queue (Postgres-backed, e.g. via
pg-boss) for scheduled replays and forwarding failures, avoiding an extra Redis dependency for v1. - UI: React + Tailwind, single dashboard listing endpoints, a request timeline per endpoint, and a payload detail view with a "replay" and "edit & replay" button.
- Auth: signature verification passthrough (HMAC secret configured per endpoint) so the proxy can validate before forwarding, plus basic auth or OIDC for the dashboard itself.
- Deployment: single Docker container plus Postgres, fits the same self-hosted pattern as the rest of a small team's stack.
Scope for v1
- One proxy endpoint per configured target URL, with pass-through forwarding and full request logging.
- Manual replay of any logged request, unmodified, to the same or a different target URL (useful for testing against staging).
- Payload edit-before-replay: modify JSON body or headers in the UI, then send.
- Simple filtering/search over logged requests by endpoint, status code, and date range.
- Out of scope for v1: multi-tenant billing, per-provider signature-scheme presets beyond HMAC-SHA256, automatic retry-on-failure policies, payload diffing between two deliveries.
Where it could go
Provider-aware parsing is the natural next step — recognizing a Stripe or GitHub payload well enough to show a human-readable summary ("charge.failed for cus_123") instead of raw JSON, without needing that provider's dashboard. After that, automatic retry policies (exponential backoff on 5xx, dead-letter after N attempts) would turn the tool from a debugging aid into a reliability layer teams actually depend on in production, which opens the door to alerting integrations (Slack, PagerDuty) when an endpoint has been failing for longer than a threshold.
Watch out for
Payload bodies can contain sensitive customer data (card metadata, PII), so encryption at rest and a configurable retention/auto-purge window aren't optional polish — they're required before any real team points production webhooks at this.