Automating e-commerce order management with n8n (Shopify, WooCommerce)
Published 21 July 2026 · 6 min read
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.
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.
Bundle FlowKit Complet
€269