Duplicate delivery protection
Most systems retry a webhook when they do not get a fast reply. If the first attempt actually arrived, your Shopify Flow workflow runs twice for one event - a second email, a duplicate tag, a repeated order note.
Duplicate delivery protection stops that. It is off by default on every webhook.
How it works
If your sending system includes a unique id per event, name the header that carries it under Advanced Settings -> Duplicate delivery.
| Behaviour | |
|---|---|
| First request with a given id | Processed normally, fires Flow |
| Repeat within 24 hours | 200 OK with duplicate: true - not sent to Flow |
| A different id | Processed normally |
| Request without that header | Processed normally |
| Field left empty | Every request processed - nothing changes |
Common header names: Event-Id, Idempotency-Key, X-Request-Id. Matching is
case-insensitive.
# Same Event-Id twice - the second is accepted but not re-sent to Flow
curl -X POST https://your-app-url/webhook/ab12cd34 \
-H "Content-Type: application/json" \
-H "X-Api-Key: your-token" \
-H "Event-Id: evt_12345" \
-d '{"orderId":"1001"}'
Why the repeat still returns 200
A non-2xx response is exactly what makes a sender retry harder. Answering 200 tells it
the event is safely handled, so it stops - while duplicate: true in the body lets you
distinguish the two outcomes if you log responses.
Where duplicates show up
A suppressed duplicate:
- creates no invocation-history entry, so it does not count toward your plan
- does appear in the Live Request Inspector while you are editing the webhook, labelled as a suppressed duplicate
That combination is deliberate: your history and quota stay clean, but a call never looks like it silently vanished.
Picking the right header
The id must be stable across the retry and unique per event - that is the whole mechanism.
Good: an event id or idempotency key generated once by the sender when the event happens.
Bad, and rejected at save time: proxy-controlled headers such as X-Forwarded-For, CF-*
or X-Signature. Their value changes per request or per hop, so they would never match a
repeat - failing silently instead of loudly.
[!NOTE] If your sender does not send any unique id, there is nothing to match on. Most platforms can add a custom header - in n8n, Make and Zapier it is one line in the HTTP request step.
If the dedup store is briefly unavailable
The delivery is processed rather than dropped. A duplicate workflow run is a much smaller problem than a lost event, so the feature fails open by design.

