Replay engine
What is replay?
Replay is the ability to re-deliver any previously captured webhook to one or all destinations. Splithook re-signs the payload with a fresh timestamp before delivery, so your HMAC verifier doesn't reject it.
Common use cases:
- Your handler was down when the event arrived — replay all missed events.
- You're testing a new code path — replay a real production payload against localhost.
- You fixed a bug and need to re-process a specific event — replay without touching the provider.
- You're comparing old vs. new handler behavior — use the diff viewer.
Replaying a single event
Open any event in the feed → Replay (top right of the inspector).
By default, replay targets all active destinations on the endpoint. Use the destination picker to target a specific one.
The replay creates a new ReplayLog entry — it doesn't modify the original WebhookRequest. The original event stays in the feed unchanged.
Replaying from the Replay Log
Replay Log (sidebar) shows every delivery attempt workspace-wide, not just the current endpoint. Filter by:
- Status: success, failure, pending, dead-letter
- Endpoint
- Destination
- Date range
Click any row → Replay to re-deliver that specific attempt.
Bulk replay
From the Replay Log: select multiple rows → Replay selected. Splithook enqueues one async job per event/destination pair. Progress appears in real time via the live feed.
If a destination has a filter expression, events that don't match are skipped during bulk replay — same behavior as live fan-out.
Diff viewer
The diff viewer compares two executions of the same event side by side — useful for verifying that a bug fix changed the handler's behavior correctly.
Open an event → Diff tab → select two ReplayLog entries to compare:
- Left pane: request headers + body (what was sent)
- Right pane: response headers + body (what the handler returned)
- Changes highlighted with
diff2htmlsyntax coloring
Re-signing on replay
Replay automatically re-signs if the destination's signing mode is re_sign. The signing behavior is identical to live fan-out:
- Stripe: fresh
t=timestamp, recomputedv1= - GitHub: recomputed
x-hub-signature-256(no timestamp) - Shopify: recomputed
x-shopify-hmac-sha256 - Twilio: recomputed
x-twilio-signature - Svix: fresh
svix-timestamp, recomputedsvix-signature
See Signing & verification for the per-provider details.
Body availability
Replay requires the raw body to be in Redis. After the retention TTL (24h on Free, 30d on Pro, 90d on Team), the body is purged and replay is no longer possible. The event row shows Body expired and the replay button is disabled.
Metadata (headers, method, event type) is retained indefinitely.
ReplayLog entries
Each delivery attempt — live or replayed — produces a ReplayLog with:
| Field | Description |
|---|---|
status_code |
HTTP status returned by the destination |
duration_ms |
Round-trip latency |
response_body_excerpt |
First 4 KB of the response |
error |
Connection or timeout error message |
resigned |
Whether the payload was re-signed |
attempted_at |
Timestamp of this specific attempt |
Tunnel destinations start in pending state until the CLI sends back the ACK with the local handler's response.