All segments

n8n Webhook Setup: Verify, Dedupe, and Handle Retries

n8n webhook nodes fire on every delivery, so a payment retry creates a second order unless you add signature checks and an idempotency key.

  • Published
  • Reading time 11 min read
  • Author Nafiul Hasan
n8n Webhook Setup: Verify, Dedupe, and Handle Retries. Diagram: attempts, spaced. RUN n8n Webhook Setup: Verify, Dedupe,and Handle Retries WIDENING INTERVALS pointerflow.com

Short answer

An n8n webhook setup for store and payment events needs three checks before it fires downstream logic: signature verification so a forged call fails immediately, an idempotency key so a retried delivery never creates a second order, and a failure path that requeues an event instead of dropping it silently.

What an n8n webhook actually receives

An n8n webhook node opens a public HTTP endpoint and waits. When a store platform or payment processor has something to report — an order paid, a subscription cancelled, a chargeback opened — it sends an HTTP request to that URL, and the webhook node starts a workflow execution with the request body and headers as its input. That’s the whole contract. n8n does not know who sent the request, does not check whether it’s genuine, and does not know whether it has seen this exact event before. Those three gaps are where a demo workflow and a production one part ways.

Signature checks and duplicate handling matter more for payment and order events than almost anything else you’d wire into n8n, because the cost of getting it wrong isn’t a missing Slack message — it’s a duplicate order, a refund that never fires, or a fulfilment that runs on data nobody checked was genuine. This article covers the three failure modes specific to receiving a webhook in n8n for store and payment platforms: an unverified signature, a retried delivery, and a failed execution with nowhere to go. None of the platform docs for n8n or for the sending side cover all three in one place, because each side only owns part of the problem.

What a webhook node does not do for you

It’s worth being blunt about the gap between “the webhook node works” and “the webhook is production-ready,” because the node itself gives no signal that anything is missing.

The webhook node does not verify that the request came from the platform it claims to be from. Anyone who has your endpoint URL — and URLs leak, through logs, through browser history on a shared machine, through a support ticket pasted somewhere it shouldn’t be — can send a request that looks identical to a genuine event, unless you check a signature.

The webhook node does not deduplicate. If the sending platform retries a delivery because your endpoint was slow, timed out, or returned a non-2xx response, n8n starts a fresh execution for the retry with no memory of the first one. The two executions are, from n8n’s side, unrelated.

The webhook node does not persist a failed execution anywhere useful by default. A node throwing an error partway through a run leaves that execution marked as failed in the executions list, and unless you’ve attached an Error Workflow, nothing else happens — no alert, no retry, no record anyone will see without going and looking.

Each of these gaps has a specific fix, and they’re worth building in that order: verify first, because an unverified request can act on the system at all; dedupe second, because a genuine but repeated request can act on the system twice; failure handling third, because it’s the safety net for everything upstream of it.

How to set up an n8n webhook trigger that survives retries

Step 1: Verify the signature before you touch the payload

Most platforms that send store or payment webhooks sign each request: they compute a hash of the body using a secret only you and the platform know, and send it in a header. Your job is to compute the same hash on your side and compare it before any other node in the workflow reads the payload.

Do this with a Code node immediately after the Webhook node, using the raw body — not a version n8n has already parsed into JSON, because signature schemes typically hash the exact bytes that were sent, and re-serialising JSON can change whitespace and break the comparison. If the signature doesn’t match, stop the workflow with an IF node branch that ends the execution rather than continuing into whatever comes next.

Exact header names and hashing algorithms vary by platform and change over time as platforms rotate signing methods, so don’t hardcode one from memory into a build — pull the current header name and algorithm from the sending platform’s own developer documentation at the time you build the integration, and re-check it if the platform announces a webhook change. What doesn’t vary is the pattern: compute independently, compare, reject on mismatch, before any other logic runs.

Step 2: Build an idempotency key and check it before writing

Every event from a genuine sender should carry something you can use to recognise it if it arrives twice — usually an event ID in the payload, sometimes a combination of fields you hash yourself if no single ID is offered. Before the workflow does anything that changes state (creates an order record, adjusts inventory, sends a notification), look that key up in a store you control: a database table, a key-value store, even a spreadsheet row for a low-volume integration.

If the key is already there, branch to a no-op and end the execution. If it isn’t, write the key first — not last — so that a slow second execution triggered by a near-simultaneous retry sees the key already written rather than racing the first execution to the finish line. The order matters: check, write, then process. A workflow that processes first and records the key last has a window where two executions can both pass the check.

Step 3: Return a fast response and queue the slow work

Sending platforms generally expect a response within a short window — the exact figure varies by platform and is documented on their side, but the practical effect is the same everywhere: if your endpoint is still running a workflow when the timeout hits, the platform records the delivery as failed and, depending on its retry policy, may send it again. A workflow that does everything inline — verify, dedupe, call three downstream APIs, write to two databases — risks timing out on its own thoroughness.

Split it. The workflow the webhook node triggers should do only the fast, essential checks — signature and idempotency — then hand the payload to a queue, a second n8n workflow triggered internally, or a lightweight execution node, and respond with a 200 immediately. The slower work — calling a fulfilment API, updating a CRM, sending a confirmation — runs in that second stage, where a timeout on its side doesn’t make the sending platform think the delivery failed and retry it.

Step 4: Catch and requeue a failed execution instead of losing it

Attach an Error Workflow to the webhook-receiving workflow, or wrap risky nodes in an Error Trigger path. When something downstream fails — a credential expired, an API returned a 500, a field was missing from a malformed payload — the error workflow should do two things: write the failed payload somewhere durable, and alert a human or a channel that watches for it.

Writing the payload durably matters because n8n’s own execution log is not a queue — it’s a record, and whether a failed execution is even visible depends on your execution-saving settings. Don’t rely on scrolling the executions list to catch a failure. Give yourself an explicit table or store of “events that failed processing,” and a way to replay them once the underlying cause — the expired credential, the missing field, the downstream outage — is fixed.

The three things that break in production

An unverified webhook n8n accepts as genuine

Trust without a check is the first failure mode. A workflow that reads a payload and acts on it — creating a fulfilment task, updating a customer record, issuing a refund — without confirming the request was signed by the platform it claims to come from will act on anything sent to that URL. This is the failure mode that’s easiest to skip during a proof of concept, because the demo works identically whether the check is there or not; it only shows up once the endpoint is public and something other than the intended sender finds it.

Verify before you parse, reject on mismatch, and treat a missing or malformed signature header the same as a bad one: don’t fall back to processing the request anyway because the header wasn’t there.

A retried delivery double-processes the same order

A retried delivery that gets processed twice is the failure mode that turns a routine retry into a real incident. Store and payment platforms retry webhook deliveries deliberately, because a network blip or a slow endpoint shouldn’t mean the event is lost. That’s the correct behaviour on the sending side. The problem is entirely on the receiving side: if the workflow has no memory of what it’s already processed, a retry looks exactly like a new event, and a “payment succeeded” webhook that fires a fulfilment step twice creates two shipments for one order.

Double-processing a retry doesn’t show up in testing, because a manual test sends one request. It shows up at volume, when a slow API response or a brief outage causes a batch of genuine retries, and every one of them re-runs the full workflow. The fix is Step 2: an idempotency key checked and written before any state-changing action, not logged afterwards as an audit trail nobody reads until the duplicate order has already shipped.

A failed execution vanishes instead of retrying

A silently dropped failure is the quiet failure mode. A node fails — a downstream API times out, a mapping expects a field the payload didn’t include this time — and the execution ends in a failed state that nobody is watching for. The sending platform may retry on its own schedule, or it may consider the delivery attempted and move on, depending on how it interprets your endpoint’s response. Either way, if your workflow has no error handling, the event that failed is simply gone from your side, and the first sign anything went wrong is a customer asking where their order confirmation is.

The fix is Step 4: an explicit error path that captures the failure, stores the payload, and gives someone a way to see it and replay it, rather than a workflow that either always retries correctly or never surfaces its own failures.

The execution-vs-task economics worth knowing before you scale this

n8n’s pricing on its self-hosted and cloud tiers is built around how many workflow executions or tasks you run, not around how many webhook nodes you’ve built — so a webhook that fires once per order behaves very differently on your bill than one that fires once per line item, or one that retries three times because Step 2 wasn’t built. Splitting the fast validation workflow from the slow processing workflow, as in Step 3, also splits how those runs count, and the exact units and thresholds are worth checking on n8n’s current pricing page before you commit to an architecture at volume rather than assuming they match whatever plan you’re already on.

Who this pattern is not for

If you’re sending fewer than a handful of webhook events a day — a single small store testing an integration before launch, well under the level where a duplicate order is a real operational cost — the full pattern here is more infrastructure than the risk justifies, and a simpler workflow with basic error logging is a reasonable place to start. This article is written for brands running $3M or more in revenue on Shopify Plus or a comparable paid subscription platform, where order volume is high enough that “it happened twice out of ten thousand” is still a support ticket, a refund, and a customer who noticed. At that volume, skipping signature verification or idempotency isn’t a shortcut — it’s a standing liability that shows up on a bad day, usually during a sale when webhook volume is highest and a human is least available to catch it by hand.

Where this sits in a wider automation build

Receiving a webhook reliably is one piece of a larger AI agents and automation problem: the moment an event crosses from a store or payment platform into your own systems is exactly where an automated workflow either holds up under real traffic or quietly loses data under it. Getting the receiving end right — verified, deduplicated, with a failure path that doesn’t drop events — is the foundation any agent or automation built on top of that data depends on. Pointerflow’s AI agents and automation work starts at that foundation, not past it.

Sources

  • No external figures are quoted in this article. It is written from n8n’s documented node behaviour (webhook triggers, error workflows, execution handling) and general webhook patterns common to store and payment platforms; vendor-specific header names, signature schemes, and pricing units should be checked against each platform’s current developer documentation before implementation.

Frequently asked

What's the difference between a webhook and a polling trigger in n8n?

A webhook trigger opens an HTTP endpoint and waits: the sending platform pushes an event the moment it happens. A polling trigger runs on a schedule and asks an API what changed since last time. Webhooks are faster and cheaper on API calls; polling is easier to debug because you control when it runs and can replay a window.

Does n8n webhook data expire or get deleted?

n8n does not hold webhook payloads once a workflow finishes running; what happens to the data depends entirely on what your workflow writes and where. If you don't persist the payload to a database, a file, or a downstream system yourself, it's gone the moment the execution ends unless you've turned on execution data saving.

Does n8n verify webhook signatures automatically?

No. The Webhook node hands you the raw body and headers; it does not know which vendor sent the request or how that vendor signs it. Verification is a Function or Code node you add yourself, comparing a header value against a signature you compute from the payload and a shared secret.

What happens if two webhook deliveries arrive for the same order?

Whatever your workflow does happens twice, unless you've built a check for it. If the workflow creates a fulfilment record, sends a confirmation email, or adjusts inventory, both of those actions run a second time on the retry. The fix is an idempotency check before the first write, not after.

Should the webhook node respond before or after processing?

Before, for anything that isn't instant. Most sending platforms time out a webhook delivery within several seconds and treat a timeout as a failure, which triggers a retry. Respond with a 200 as soon as you've validated the signature and queued the payload, then do the slow work in a separate execution.

How do I stop a payment webhook from creating duplicate orders?

Store a record of every event ID or idempotency key you've already processed, and check it before the workflow writes anything. If the key exists, stop the workflow with a no-op branch instead of continuing. The check has to run before the write, not as cleanup afterwards.

What causes an n8n webhook execution to fail silently?

Usually a node throws an error partway through — a downstream API is down, a field is missing, a rate limit is hit — and without an error workflow attached, the execution just shows as failed in the executions list. Nobody sees it unless someone checks. The sending platform may or may not retry, depending on its own rules.

Can I replay a failed n8n webhook execution?

Yes, from the executions list you can open a failed run and retrigger it, provided n8n saved the execution data. That only works if you haven't turned off failed-execution saving and the underlying issue (a bad credential, a down API) has been fixed since. For anything you can't afford to lose, write the raw payload somewhere durable as the first step.

Is a webhook safer than polling an API for order updates?

Neither is inherently safer; they fail differently. A webhook can be missed if your endpoint is down when it fires and the sender doesn't retry, or duplicated if it does retry. Polling can miss an update between two poll windows if the API doesn't expose a reliable changed-since filter. Production setups often use a webhook for speed and a periodic poll as a backstop.

What's an idempotency key and where do I get one?

It's a value that uniquely identifies one occurrence of one event, so processing it twice is safe to detect. Many platforms send an event ID in the payload or a header you can use directly; if not, build one by hashing a stable combination of fields, such as order ID plus event type plus timestamp truncated to the second.

Next step

Is this your ai agents & automation problem, or a symptom of another one?

Bring your numbers — the churn split, the decline rate, whatever your flows are earning — and we will tell you which of them is the expensive one.

Book a call →