Skip to main content
Webhook senders are at-least-once: on a network blip or a non-2xx response they retry, so the same event can arrive more than once. Deduplication collapses those repeats into the one event you already captured — per endpoint, keyed however you choose — so a retry doesn’t show up (and count) twice. It’s off by default; turn on a mode when a sender’s retries get noisy.
Deduplication is best-effort load reduction, not an exactly-once guarantee. Keep your own handler idempotent — dedup reduces duplicates, it doesn’t promise their absence. Which mode keyed an event is recorded on the event object as dedupStrategy, alongside the derived dedupKey.

The default

Every endpoint starts with deduplication off — we capture every request as a distinct event, and nothing is collapsed. That’s the safe default for an inspection tool: you see exactly what a sender sends, retries and all. Deduplication is opt-in; turn on a mode per endpoint once you trust a sender’s shape and want its retries folded away. For where dedup sits in the pipeline, see how webhook.co works.
With dedup off, every request is a distinct, counted event — including retries and any non-webhook traffic (uptime checks, link previews) that reaches the URL. Enable a mode to collapse retries; the soft cap pauses ingestion before a runaway sender runs away with your usage.

Modes

Set a per-endpoint dedupConfig to turn deduplication on and choose how the key is derived: Every mode except off takes a windowSeconds (60–604800, i.e. 60s–7d), the window within which repeats collapse. off takes no window — it never collapses.
Collapsing is scoped to the window on purpose: a repeat that arrives in a later window is treated as a new event, so a legitimately-repeated payload days later is still captured rather than silently dropped. One consequence — a retry that lands right around a window boundary can be captured as two events, because the copies fall in different windows. If your sender supplies a stable id, prefer identifier: its key is that id and carries no window, so a retry collapses no matter when it arrives. content and fields keys include the window, so those are the modes where a boundary-straddling retry can double up. Widening windowSeconds makes a straddle rarer.

Field paths

fields mode keys on values you select with field paths. A path starts with a root — headers, body, query, or path — and addresses into it with dot notation and array accessors:
  • body.data.id — a nested body value
  • headers.x-event-id — a header value
  • query.id — a query parameter
  • body.items[*].sku — every element of an array ([*] wildcard, or [0] for one index)
Provide include paths (the values that make up the key) and, optionally, exclude paths (volatile fields to drop, like a per-delivery timestamp). If a configured field is missing from a request, that request is treated as distinct rather than collapsed — webhook.co never silently drops an event it can’t key.

Configure it

Deduplication is configured identically across every surface — set it on create, or update it any time. --dedup-reset (CLI) or a null dedupConfig (API) returns an endpoint to the default.
Config changes take effect within the cache-propagation window (about five minutes), not instantly — and a change never claims exactly-once across the transition. Every change is recorded in your endpoint’s tamper-evident audit trail.