Automating e-commerce order management with n8n (Shopify, WooCommerce)
By Clément Lacaille (Tech-Bharat) · Published 21 July 2026 · updated 22 September 2026 · 7 min read · how we build and test
Complete FlowKit Bundle — €269
12 ready-to-import n8n workflows, setup guide in French, 14-day guarantee
A Shopify or WooCommerce store running without automation relies on humans checking stock, copying orders into an ERP by hand, sending confirmation emails, and tracking shipments manually. That works at low volume. The moment orders come in bursts — a product launch, a sale period — things get missed and duplicated. n8n lets you build a pipeline that receives the order, checks stock, pushes it into your billing tool, notifies the customer, and tracks delivery, with no manual step on the happy path.
This point reaches far beyond Shopify or WooCommerce: back in 1990, Davenport and Short laid the groundwork for what would later be called BPM (business process management) in a foundational Sloan Management Review study, showing that the real payoff of computerizing a process doesn't come from automating one isolated task, but from redesigning the entire process around what the information system makes possible (Davenport & Short, 1990, Sloan Management Review). That's exactly what a well-designed n8n pipeline does here: it doesn't just automate sending the confirmation email, it rethinks the whole chain — receiving, checking, writing, notifying, tracking — as one coherent process instead of five isolated tasks wired together by hand.
The trigger: a Shopify or WooCommerce webhook
Shopify offers native webhooks, configurable from the admin (Settings > Notifications > Webhooks) or via the Admin API, on the orders/create event. Point it at an n8n Webhook node in POST mode; WooCommerce works similarly through its own webhooks (Order created), configurable under WooCommerce > Settings > Advanced > Webhooks.
The payload arrives with everything you need: ordered items, quantities, shipping address, total, customer email. A Set node at the start of the workflow normalizes these fields into a common shape (order_id, items, customer_email, total) — useful if you're running multiple stores or platforms and want the rest of the workflow to stay identical regardless of the source.
{{ $json.body.id }}
{{ $json.body.line_items[0].sku }}
{{ $json.body.customer.email }}
Idempotence: never process the same order twice
Shopify and WooCommerce webhooks don't guarantee exactly-once delivery: a network timeout or a 5xx error on the n8n side triggers an automatic retry from the platform, with the same order_id. Without a guard, this can create a duplicate order in the ERP or send the customer two confirmation emails.
The fix: a table (Supabase or Postgres) with a UNIQUE constraint on order_id, checked right at the start of the workflow.
- HTTP Request node (or Supabase) — look up the
order_idin theprocessed_orderstable. - IF node — if found, respond to the webhook immediately (
200 OK) and stop there, without replaying the business logic. - Otherwise, insert the
order_idright at the beginning of processing (before the workflow even finishes), so that even a retry mid-execution won't replay the same order.
This mirrors the pattern covered in our guide on securing an n8n webhook: validating the source and neutralizing replays are the two baseline reflexes before letting a webhook drive business actions.
Checking stock before confirming anything
Before confirming anything to the customer, query the source of truth for stock — Shopify's own inventory, or an external ERP if stock is centralized there.
- HTTP Request node to the inventory API (Shopify's
inventory_levelsor the ERP's endpoint). - Code node to compare, item by item, available quantity against ordered quantity:
const items = $input.first().json.items;
const stock = $('Get Inventory').first().json.levels;
const shortages = items.filter((item) => {
const available = stock.find((s) => s.sku === item.sku)?.available ?? 0;
return available < item.quantity;
});
return [{ json: { hasShortage: shortages.length > 0, shortages } }];
- IF node on
hasShortage: the "true" branch heads to shortage handling (internal notification + customer email + order status update), the "false" branch continues on to ERP creation.
Creating the order automatically in the ERP or billing tool
Once stock is validated, an HTTP Request node pushes the order to the ERP or billing tool (QuickBooks, Sage, an in-house ERP, or even a Supabase table feeding accounting). For integrations exposing a standard REST API, an HTTP Request node with header or OAuth2 authentication covers most cases; some tools have a dedicated n8n node that simplifies auth.
Things to watch for:
- Map fields explicitly (SKU, quantity, unit price, tax) rather than forwarding Shopify's raw payload — the two systems almost never share the same structure.
- Store the ID returned by the ERP (
erp_order_id) in your tracking table, so you can link back and forth later (status updates, refunds).
Customer notification: a personalized confirmation email
A Set node prepares the variables (name, items, total, estimated delivery), then either a static template with n8n expressions, or an AI Agent or LLM Chain node generates a more natural confirmation from that structured data.
The important part: don't let the model invent the numbers. Inject amount, items, and order number via expressions ({{ $json.total }}, {{ $json.order_id }}) into the final template, and reserve AI generation for tone and supporting copy — a warmer message than a generic email, tailored for instance to the type of product purchased. An Email Send node (or your transactional provider's integration) closes the loop.
Syncing shipment status
Once an order ships, the carrier (a national postal service, a courier, or an aggregation platform like AfterShip) typically sends its own tracking webhooks. The pattern mirrors the order webhook:
- A dedicated n8n Webhook for carrier events (
shipped,in_transit,delivered,exception). - A Switch node on the event type, routing to the right action: ERP status update, customer tracking email, or an internal alert on a delivery exception.
- Updating the tracking table to keep one central record of each order's real state.
Handling refunds and cancellations
A cancellation can come from either side: the customer (via a form or an email) or the store itself (a shortage discovered late, suspected fraud). Either way, the workflow should:
- Check the order's current state (already shipped or not) before allowing an automatic refund — an IF node on status is enough to separate simple cases from ones needing manual review.
- Call the Shopify/WooCommerce refund API or your payment provider's.
- Update the ERP and notify the customer, reusing the same building blocks (Set + email) as the initial confirmation.
For ambiguous cases (a partially shipped order, a dispute), routing to human approval beats automating everything — see our article on human approval with Wait and Slack for the exact pattern.
Handling Shopify API rate limits (429)
The Shopify API caps request throughput (a leaky-bucket limit, typically 2 requests per second on the standard REST API plan). During an order spike or a bulk sync, 429s show up fast. The fix: a Loop Over Items node to process orders in batches instead of in parallel, paired with a Wait node between batches. For the full mechanics (Retry On Fail, reading the retry-after header, sizing batches), our guide on AI API rate limits in n8n applies almost verbatim to the Shopify API — only the provider changes.
Platform specifics and what happens after the order
Shopify: authentication and limits
Create a custom app (Settings → Apps → Develop apps): it provides a permanent Admin API token with precise scopes, without an OAuth2 flow to maintain. The Shopify Trigger is a real webhook registered by n8n on activation (orders/create, orders/paid, products/update…), which requires an instance reachable over HTTPS. The node mainly covers orders and products; customers, inventory, metafields or draft orders go through the GraphQL Admin API with an HTTP Request and the X-Shopify-Access-Token header.
Amazon Seller: orders and stock through SP-API
Since 2 October 2023, an LWA (Login with Amazon) token is enough: no more AWS signing or IAM role. There is no official node; an HTTP Request exchanges the refresh token for a one-hour token at the start of each run, then queries orders and FBA stock to alert before a stock-out. The buyer's address requires a Restricted Data Token: only fetch it if the workflow really needs it.
Returns and refunds
Automate full refunds for low-risk returns (clear reason, small amount, within the legal window) and send ambiguous or high-value cases to human approval before the API call. The Shopify and WooCommerce nodes do not handle refunds: use Shopify's GraphQL Return/Refund API or /wp-json/wc/v3/orders/<id>/refunds with the existing credential. Below a confidence threshold, the classifier should return "to review" instead of forcing a category.
Delivery tracking and parcel alerts
When the carrier offers a webhook (Colissimo, Chronopost, DHL…), it is the most responsive option; otherwise a Schedule Trigger every 30 to 60 minutes checks parcels in transit. Carriers often resend the same event: log the IDs already processed. "Shipped" or "delivered" messages can go out on their own; an incident (wrong address, damaged parcel, repeated failed delivery) goes through human approval before sending.
Wrapping up
A solid e-commerce order pipeline in n8n rests on five pieces: a reliable, idempotent webhook at the entry point, a stock check before any confirmation, structured ERP creation, a well-crafted customer notification, and shipment status syncing that closes the loop. Handle shortages and refunds explicitly instead of treating them as unplanned exceptions, and the workflow holds up during a product launch with no constant human oversight. If you're starting from scratch on the AI side (generated emails, dispute classification), our guide to getting started with AI nodes covers the basics before you go further.
FAQ
Frequently asked questions
Should I use the native Shopify node or an HTTP Request node to fetch orders?
For real-time order capture, a Shopify webhook (fired on orders/create) is far more responsive than polling with the native Shopify node. Use the native Shopify node for one-off actions (updating a status, looking up a product), and a dedicated n8n Webhook for the orders/create event, which pushes the data the moment it exists instead of waiting for the next sync cycle.
How do I avoid processing the same order twice if Shopify resends the webhook?
Shopify and WooCommerce can re-fire a webhook after a timeout or network failure, with no exactly-once delivery guarantee. The fix is to store already-processed order_id values in a table (Supabase or Postgres with a unique constraint) and check that table right at the start of the workflow with an IF node before any write action: if the ID already exists, respond 200 immediately without replaying the business logic.
How do I handle a stock shortage discovered after the order comes in?
The HTTP Request node that queries the ERP or Shopify inventory returns the available quantity; an IF node compares it against the ordered quantity. If it falls short, the workflow branches off: an internal notification (Slack or email), an automatic customer email offering a partial refund or a delay, and an order status update — instead of leaving the order in an ambiguous state.
Are AI-generated order confirmation emails reliable enough for customer-facing use?
Yes, as long as you constrain the prompt: feed the AI Agent or LLM Chain node structured order data (items, price, delivery estimate) rather than free text, and limit its freedom to tone and phrasing, not to the numbers. For sensitive data (amount, order number, delivery date), it's safer to inject it directly into the template via n8n expressions rather than let the model generate it.