Most n8n templates fail the same way: they work on the author’s store, on the author’s sample payload, on the day it was published. This page gives you one complete template you can rebuild in an afternoon, an order-exception workflow for a Shopify Plus store, plus the reasoning behind each setting so you can change it without breaking it. What it covers that gallery pages don’t: duplicate deliveries, branches that drop orders silently, and errors that nobody owns.
It’s written for operators at $3M+ revenue running Shopify Plus or a paid subscription platform, with someone technical (or an agency) who will own the instance. If you’re below that, a hosted no-code tool with support will cost you less than the time this takes.
What do n8n templates give you, and what do they not?
An n8n template is a workflow saved as JSON that you paste or import into your own instance, where it arrives with nodes and connections but no credentials. That’s all. It doesn’t include your field names, your permissions, your volumes or your rules for what happens when something goes wrong.
The gallery is useful for one thing: seeing which node settings work for a given API. It’s a poor base for a production workflow. Templates are written to be demonstrable, so they tend to show the happy path in eight nodes and stop. The 20 nodes that were cut are the ones that matter to you: verification, dedupe, fallbacks and alerts.
Treat an imported template as code from a stranger. Read every Code node and every HTTP Request node before you activate it. If you can’t say what a node does, delete it.
For how n8n compares with other platforms, see n8n versus Zapier. For the wider set of jobs worth automating, see n8n use cases. This page stays with the template itself.
What does the order-exception template do?
The template receives a Shopify order webhook, decides whether the order is an exception, and sends each exception to exactly one owner with the context they need. An exception here means an order that a person should look at: a shipping address that failed validation, a high-value order with a mismatched billing country, a payment flagged for review, or a line item with no stock at the assigned location.
Why this template? Order exceptions sit in the awkward middle. They’re frequent enough that reading them by hand costs real hours, and rare enough per order that nobody builds tooling for them. They’re also low-risk to automate, because the workflow doesn’t change anything: it reads, classifies, routes and logs. That’s the right first n8n build. A workflow that only routes can be wrong without costing money.
The flow has five stages.
| Stage | n8n node | Job | What it must never do |
|---|---|---|---|
| Receive | Webhook | Accept the order event, keep the raw body | Respond before verification finishes |
| Verify | Code | Recompute the HMAC and compare | Continue on a mismatch |
| Deduplicate | Data table or database node | Skip repeat deliveries | Check after the first side effect |
| Classify | Switch, then an optional AI step | Assign one label from a fixed list | Invent a label |
| Route | HTTP Request or helpdesk node | Deliver to one owner | Leave any label without a destination |
Take from the table that the two protective stages, verify and deduplicate, come before anything that touches another system. Most template galleries reverse that order or omit both.
How do you build an n8n template for order exceptions?
Build the workflow in five steps. Each step names the setting that matters and the mistake teams make there. The step names are the headings, so you can follow along in the editor.
Step 1: Verify the webhook before anything runs
Add a Webhook node with the HTTP method set to POST and the raw body option enabled. Shopify signs each webhook with an HMAC of the raw request body, sent in the X-Shopify-Hmac-Sha256 header. If the body is parsed and re-serialised before you compute the signature, the bytes change and every comparison fails.
Follow it with a Code node that computes the HMAC-SHA256 of the raw body using your app’s webhook secret, base64-encodes it and compares it to the header. On a mismatch, throw an error so the run stops. Store the secret as a credential or an environment variable, not inside the node.
Two things trip people up. First, n8n’s Code node only allows built-in modules such as crypto if your instance’s environment permits them, so on a self-hosted install you may need to set the allowed built-ins variable before the node works. If you’re weighing that setup, self-hosting n8n covers what you take on. Second, an unauthenticated webhook URL is guessable by design (it’s a URL). Without verification, anyone who finds it can create tickets in your helpdesk.
The step teams get wrong: leaving verification out because the test payload from Shopify’s admin worked. Test deliveries pass through the same path, but nothing forces you to notice that you never checked the signature.
Step 2: Deduplicate on the webhook ID
Shopify can deliver the same webhook more than once. Your workflow will, at some point, receive the same order event twice, and without a guard it will open two tickets and post twice in Slack.
Read the X-Shopify-Webhook-Id header and use it as the dedupe key. Before any side effect, look the key up in a store you control: an n8n data table if your version has one, or a small database table with a unique constraint. If it exists, end the run. If it doesn’t, insert it and continue.
Order matters. Insert the key first, then act. If you act first and insert afterwards, a crash between the two leaves you with a ticket and no record, and the retry creates a second ticket. If you insert first and the action fails, the error workflow tells a human and the key is already there, which is the safer failure: one missing ticket that you’ve been alerted to beats a silent duplicate.
Add a second guard where the destination allows it. Most helpdesks accept an external ID or custom field. Write the order ID there and search before creating.
A small Code node builds the key:
const id = $input.first().json.headers['x-shopify-webhook-id'];
const topic = $input.first().json.headers['x-shopify-topic'];
return [{ json: { dedupeKey: `${topic}:${id}` } }];
Header names arrive lower-cased in n8n, which is a common reason a lookup returns undefined.
Step 3: Classify the exception with rules first
Use a Switch node in rules mode with one output per exception class. Write the rules against fields you’ve confirmed exist in your own payloads, not the ones in the template. Typical rule inputs are the shipping country compared with the billing country, a total above a threshold you set, the presence of a risk-flag tag, and a line item whose inventory is zero at the assigned location.
The threshold is yours to set. There’s no standard figure, and inventing one is how a workflow ends up routing every order or none. Work it out from your own data: export a month of orders, sort by value, and pick the level at which a person would already look at the order by hand. Mark it metric to confirm in your notes until you have.
Keep the fallback output on. Switch nodes have a fallback option for anything that matches no rule, and it’s off by default in some configurations. Point it at an “unclassified” branch that goes to a human. With no fallback, an order that matches nothing leaves the workflow without a trace, and the run still shows as successful.
An AI step belongs only on that fallback branch, if anywhere. Give the model the order summary and a fixed list of allowed labels, ask for one label back, and validate the label against the list in a Code node before acting on it. If the label isn’t in the list, route to a human. A model that can return free text will eventually return something your Switch has no output for. For a fuller treatment of where agents fit, see building an n8n AI agent.
Where AI doesn’t belong in this template: the refund decision, and anything that moves money. Have the workflow gather the order, the customer’s history and a proposed action, and post it for a person to approve.
Step 4: Route each class to exactly one owner
Every label gets one destination and one named owner. “The ops channel” isn’t an owner. If two people see a message in a shared channel, each assumes the other has it.
For each branch, build the message with the fields the owner needs to act without opening Shopify: order number with a link to the admin page, customer name, the rule that fired, the line items affected and the fulfilment location. Put the rule name in the message. When an owner asks why they got this, the answer should be readable.
Destinations vary by class. Address problems can create a helpdesk ticket, so the customer-service team’s tooling stays the record; for how that connects, see helpdesk automation tools. Stock problems can go to whoever manages the 3PL. Risk flags can go to whoever handles chargebacks, which links to ecommerce chargebacks.
Set the HTTP Request node’s retry option deliberately. Retrying a create call without an idempotency guard produces duplicates, which is why Step 2 writes the key before the call. If the destination supports an idempotency key header, send one.
Finally, merge all branches into a logging node, such as an append to a sheet or a database row: order ID, class, rule, destination, timestamp. That log is how you’ll find out that most routed orders were false alarms and the threshold needs to move.
Step 5: Attach an error workflow and a heartbeat
Open the workflow settings and set an error workflow. Build it with an Error Trigger node that posts the failed workflow’s name, the failing node and the execution link to a named person, not a channel. Without one, a failing run is a red line in an execution list that nobody opens.
Then add the check people forget. An error workflow only fires on failures. It doesn’t fire when the webhook stops arriving, for example because Shopify deleted the subscription after repeated non-200 responses or because your instance was down during a burst. Build a small scheduled workflow that queries the log for the most recent entry and alerts if it’s older than your normal gap between orders. Set that gap from your own order timestamps.
That gap is the “split path” failure in miniature: one branch of the system, the one where nothing arrives, has no monitoring at all.
What breaks if you change the template?
Most edits are safe, but four aren’t. The table lists the change, what it breaks and how to notice.
| If you change | What breaks | How you’ll notice |
|---|---|---|
| Parse the body before verifying | Every signature comparison fails, or you drop verification to make it pass | Runs stop, or the workflow is open to anyone |
| Move dedupe after the ticket call | Duplicate tickets on redelivery | Two tickets per order, sporadically |
| Turn off the Switch fallback | Unmatched orders vanish | Nothing; the run is green |
| Respond 200 at the start | Shopify stops retrying real failures | Orders missing from the log with no error |
| Subscribe to more webhook topics | Execution volume rises with every update | Plan usage climbs faster than order count |
Take from the table that the dangerous edits fail quietly. Duplicates and dropped orders don’t throw errors, which is why each protection is a deliberate node rather than a default.
The webhook response deserves a note. By default the Webhook node can respond when the workflow starts or when it finishes. Responding immediately is tempting because it stops Shopify timing out, but it also hides failures from Shopify’s retry logic. A reasonable pattern: verify and write the dedupe key, respond, then do the slow work, with the error workflow covering failures after that point.
How much does the template cost to run?
Cost depends on how n8n counts usage on your plan, and that is set by n8n, so check its pricing page for the current unit before you size anything. The shape to know is this: n8n’s cloud plans have historically metered by workflow execution, while task-based tools meter each step. Those two models scale very differently for a branching workflow.
An execution-based model charges one unit for a run however many nodes fire inside it. A five-stage template with a logged branch is then one execution per webhook. Under a per-task model, the same run could consume several tasks. Self-hosting removes the per-run charge but adds servers, backups, upgrades and someone on call. The n8n versus Zapier comparison goes further on that trade-off.
Work out your own volume with a method, not a guess. Count the webhooks per month across the topics you subscribe to (orders created, orders updated, fulfilments), multiply by the number of retries and duplicates you see in your logs, and compare with your plan’s limit. Filtering early keeps that number down: subscribe to the narrowest topic that answers your question, and end runs that don’t need action at the first Switch, not the last.
A hypothetical to show the arithmetic: a store that receives 10,000 order-created events a month, each updated twice, has 30,000 events if you subscribe to both topics and 10,000 if you subscribe to one. The order-exception workflow needs only the first. That’s illustrative, not a benchmark.
Who is this template not for?
Skip it if your store is below the $3M floor and your exception volume is a handful a week. A rule in Shopify Flow or a saved admin view does this with nothing to maintain. Skip it as well if nobody on your side can own an n8n instance: the failure modes this page lists are operational, and an unowned workflow decays.
It’s also the wrong tool where a wrong answer costs more than a human minute. This template routes and never decides. Keep it that way until the log shows you where automation is reliably right.
How do you adapt it to your store?
Change four things, in this order. Put shop domain, helpdesk group, Slack destination and thresholds in a single Set node at the top, so the second store or the next edit touches one place. Replace the classification rules with ones you’ve confirmed against your own payloads, using a month of real orders. Point each branch at the owner who has agreed to receive it. Then run the test set: one payload per branch, a duplicate, a malformed body, and a payload missing a field.
Version the result. Export the JSON to a Git repository or use n8n’s source control if your plan includes it, and record why each rule exists. Rules without reasons are the first thing a new hire deletes.
Building an exception workflow that nobody has to babysit is an AI agents and automation problem, not a template-hunting problem: the value is in the verification, the dedupe, the fallbacks and the ownership, and those come from designing around your own failure modes. Pointerflow builds and runs this kind of workflow under AI agents and automation. For where this sits among other approaches, see AI workflow automation.
Sources
- No external figures are quoted. The article is written from Shopify’s documented webhook signing and redelivery behaviour and from n8n’s documented node behaviour; check n8n’s pricing page for the current billing unit.