WP Webhooks / Blog / Integrations

Sending WooCommerce Orders to n8n Without Losing the Ones That Fail

WooCommerce to n8n: why the WooCommerce Trigger makes one attempt, answers 200 before the workflow runs, and fires on every order save, and what to use instead.

8 min 2026-10-17
#n8n#woocommerce#webhooks

TL;DR: n8n's WooCommerce Trigger node is a thin wrapper around WooCommerce's own webhooks, and inherits all of their delivery behaviour.

  • WooCommerce makes one delivery attempt per event. There is no retry.
  • The trigger answers 200 before your workflow runs, so a failure in a later node never reaches WooCommerce.
  • There is no "order completed" event, only order.updated, which fires on every order save.
  • A 301 or 302 from the n8n URL is counted as a successful delivery, and the redirect is not followed.
  • For orders that must arrive, post a queued webhook to a Webhook node that responds when the last node finishes. A failed workflow then returns 500 and the delivery is retried.

/ Trigger node

How does the n8n WooCommerce Trigger node work?

It registers a webhook in your store and listens on it. The node's credential is a WooCommerce REST API consumer key and secret with Read/Write permission. When you publish the workflow, the node calls POST /webhooks on your store with three values: the workflow's production URL as delivery_url, the event you picked as topic, and a generated secret. Unpublish the workflow and it deletes that webhook again. You can see it under WooCommerce → Settings → Advanced → Webhooks while the workflow is live.

The node offers twelve events: created, updated and deleted for coupons, customers, orders and products. On every request it checks the X-WC-Webhook-Signature header, an HMAC-SHA256 of the raw body keyed with that secret and base64-encoded. A request with a wrong signature gets 401 Unauthorized and never starts the workflow.¹

Everything after that is WooCommerce's delivery code, not n8n's, and that is where the surprises are.

/ Events

Why is there no "order completed" event in the n8n trigger?

Because WooCommerce has none. Its webhook topics are resource-level. In class-wc-webhook.php, order.updated is wired to three hooks: woocommerce_update_order, woocommerce_order_refunded and woocommerce_order_refund_deleted. The first one fires every time the order object is saved.

An order is saved many times in its life. The payment gateway saves it, the status change saves it, a shipping plugin adding a tracking number saves it, an admin editing the address saves it. Each save is a separate delivery and a separate n8n execution. If the workflow should run when an order is completed, you add an IF node on status === 'completed', and it still runs again for every later save of that completed order. The tracking-number update next week sends the thank-you email a second time.

So a workflow on order.updated needs its own record of which orders it has already handled. The trigger cannot give you that.

FIG 01 — Two ways into n8n: one attempt and a 200 before the workflow runs, or a queue that sees the workflow fail

/ Downtime

What happens to WooCommerce webhooks when n8n is down?

The order is delivered once and lost. WooCommerce collects webhooks during the request and hands them to Action Scheduler as a woocommerce_deliver_webhook_async job, so the shopper does not wait. The job makes a single POST with a 60-second timeout. If n8n is restarting, the request fails, the failure counter goes up, and that is the end of that order's delivery. Nothing schedules a second attempt.

The counter decides when WooCommerce gives up on the webhook entirely. The check runs before the increment and compares against woocommerce_max_webhook_delivery_failures, which defaults to 5:

  • Failures 1 to 6 raise the counter from 0 to 6, because each check sees 0, 1, 2, 3, 4 and then 5, and 5 is not greater than 5.
  • Failure 7 sees 6 > 5 and sets the webhook's status to disabled.

So seven failed orders in a row, a busy hour during a long n8n outage, switch the integration off. A single successful delivery resets the counter to zero. There is an action for the disable, woocommerce_webhook_disabled_due_delivery_failures, but nobody is notified unless you hook it. Republishing the workflow registers a fresh webhook, because the node only looks for active ones, and leaves the disabled one behind in the list.

/ Redirects

Why does a redirect count as a successful WooCommerce webhook delivery?

Because the success check is >= 200 && < 303, a 2xx, 301 or 302, and the request is sent with redirection set to 0. WooCommerce gets the 301, does not follow it, counts the delivery as a success and resets the failure counter.

This bites when the n8n instance sits behind a proxy that redirects http to https, or adds a trailing slash, and WEBHOOK_URL was set to the other form. n8n registers that URL with WooCommerce, every order "succeeds", and no execution ever appears. Open the webhook in WooCommerce and check that the delivery URL is exactly the one n8n's Webhook panel shows.

/ Response

Does a 200 from n8n mean the workflow ran?

Not with the WooCommerce Trigger. The node is hard-wired to respond on receipt: once the signature checks out, n8n answers 200 and then starts the workflow. If the CRM node three steps later fails, WooCommerce has already logged a success. The only record of that order is a failed execution in n8n's list, which n8n keeps according to its execution pruning settings.

The core Webhook node lets you choose. Set Respond to When Last Node Finishes and the response waits for the workflow. In n8n's webhook handler, a run that ends in an error returns 500 with the message Error in workflow.² Now the sender can tell a delivered order from a lost one, provided the sender retries.

ConcernWooCommerce Trigger nodeWebhook Actions + Webhook node
Setup inside n8nPick an event, add a REST key. Nothing to configure in WordPressMore work: a webhook in wp-admin, a trigger hook, field mapping
Which eventorder.updated on every save, filtered in n8nOne hook, such as woocommerce_order_status_completed, so the workflow runs once per transition
n8n down or restartingOne attempt, then the order is lostRetried with exponential backoff, five attempts by default
Workflow fails after receiptWooCommerce already saw 200The 500 from When Last Node Finishes is retried
Repeated failuresWebhook disabled on the seventh, silentlyEach delivery fails on its own; failure notifications by email, Slack and more
Finding a lost orderWooCommerce logs, if anyDelivery log with request, response and every attempt; replay after the fix
Duplicate protectionBuild it in n8nA UUID in event.id that stays the same across retries
try_it

Seeing it run beats reading about it. The live preview boots a throwaway WordPress with Webhook Actions already installed and demo deliveries sitting in the log — no signup, nothing left on your machine afterwards.

/ Timeouts

How long can the n8n workflow take before the sender gives up?

As long as the sender's timeout, which is the one setting this pattern depends on. With When Last Node Finishes, the HTTP request stays open for the whole workflow. If the workflow calls three APIs at about 1.5 seconds each, that is 3 × 1.5 = 4.5 seconds, close to a 5-second client timeout. A timeout counts as a failure and is retried, but n8n did not stop: the workflow finishes, and the retry runs it a second time.

Two ways out. Raise the timeout to cover the slowest realistic run; fswa_http_timeout is a one-line filter. Or keep the workflow short and hand the slow part to a second workflow. Either way, plan for the duplicate, because a retry after a timeout is the normal case, not an edge case.

PHP — raise the delivery timeout for slow workflows

add_filter( 'fswa_http_timeout', function ( $seconds ) {
    return 30;   // the workflow's slowest run, plus headroom
} );

/ Duplicates

How do you stop an n8n workflow from processing the same order twice?

Check for the result, not the delivery. n8n's Remove Duplicates node has a Remove Items Processed in Previous Executions operation, and an event id looks like the natural key. The catch is in the node's source: it calls checkProcessedAndRecord, so the id is recorded when the node checks it, not when the workflow succeeds. Put it at the start, let a later node fail, and the retry of that order is dropped as a duplicate. The retry you set up to recover the order is the one thing that never gets through.

Use it only right before a step that cannot fail halfway, or skip it and look up the effect instead. Before creating an invoice, search for one carrying the order number. Before sending an email, check a sent flag you wrote back to the order. A lookup sees what actually happened, so it gives the right answer on the first run and on the fifth.

The n8n WordPress trigger article covers the polling alternative and when it is the better fit. For WooCommerce specifically, the same delivery pattern feeds accounting: the WooCommerce to Xero article builds an invoice workflow on it.

/ Exposure

What does n8n not protect you from?

A public URL. A Webhook node with no authentication runs for anyone who finds the address. Set Authentication to Header Auth and send the same header from WordPress. It costs one credential on each side, and the WooCommerce Trigger's signature check gave you the equivalent for free, which is easy to forget when you switch.

Test URLs in production. The test URL works only while the editor is listening. A store pointed at it delivers into nothing as soon as the tab closes. Use the production URL, which is registered when the workflow is published.

The 16 MB ceiling. The Webhook node rejects payloads over 16 MB by default. A WooCommerce order is far below that, but an order with hundreds of line items and their full meta can grow, so send the fields you use rather than the whole object.

A forgotten REST key. The trigger's key has write access to the whole store. If you move to a pushed webhook, revoke it under WooCommerce → Settings → Advanced → REST API.

/Footnotes
¹ Node behaviour from the source of WooCommerceTrigger.node.ts, read 2026-10-22. WooCommerce delivery, retry and disable logic from class-wc-webhook.php and wc-webhook-functions.php on trunk, read the same day.
² Response handling in n8n's webhook-helpers.ts, read 2026-10-22.
FAQ

Things engineers always ask.

Don't see yours? Open an issue on GitHub or check the full reference in the API docs.

How does the n8n WooCommerce Trigger node connect to my store? +
It uses a WooCommerce REST API key with Read/Write permission. When you publish the workflow, the node creates a webhook in WooCommerce with the workflow URL, the chosen topic and a generated secret, and deletes it when you unpublish. Incoming requests are checked against the X-WC-Webhook-Signature header.
Does WooCommerce retry a failed webhook delivery? +
No. WooCommerce sends each webhook once, in the background through Action Scheduler, with a 60 second timeout. A failure only increases a counter. With the default threshold of 5, the webhook is set to disabled on the seventh consecutive failure, and one success resets the counter.
Why is there no order completed event in the n8n WooCommerce Trigger? +
WooCommerce webhook topics are per resource. order.updated fires on woocommerce_update_order, which runs every time the order is saved, plus refunds. To act on completed orders you filter on the status in n8n, and the workflow still runs again for later saves of the same order.
Why does my WooCommerce webhook show success but n8n never runs? +
WooCommerce counts 2xx, 301 and 302 as success and does not follow redirects. If the delivery URL redirects, for example from http to https or to a trailing slash, every delivery is marked successful and nothing reaches n8n. Make the URL in WooCommerce exactly match the one n8n shows.
How do I make n8n return an error when the workflow fails? +
Use the Webhook node and set Respond to When Last Node Finishes. If the run ends in an error, n8n answers 500 with Error in workflow, so a sender that retries will try again. The WooCommerce Trigger node always answers on receipt, before the workflow runs.
Ready

Your next automation is
one sentence away.

$ wp plugin install flowsystems-webhook-actions --activate