How to Turn Supplier Invoices into Shopify Product Listings with n8n and AI
Published on October 13, 2026·By Stijn Scheltinga Koopman
Every supplier invoice hides a chore: turning each new line item into a complete, correctly categorised Shopify listing. We built an n8n system for a specialist spirits retailer that does this for them. An invoice goes into Slack, and the team gets back researched, described and properly tagged products, ready to approve with one click.
This post walks through how it works: the architecture, the design decisions behind it, and the parts that turned out harder than expected. It isn't a click-by-click tutorial, because the full system spans four workflows. Instead, it's the blueprint you'd need to build your own version, whether you run a store and know your way around n8n or you're a developer weighing up the approach.
The problem: an invoice is not a product listing
An invoice tells you what arrived: a product name, a code, a quantity and a price. A good listing needs far more. For a whisky that means the distillery, bottler, country, region, cask type and a description that actually sells it.
Before automation, someone had to research every new product by hand, copy the details into Shopify and pick the right values for each attribute. For a specialist shop with a large, detailed catalogue, that adds up fast, and small inconsistencies creep in along the way.
The obvious shortcut is to paste the product name into ChatGPT and ask for a listing. In practice that breaks down in three ways:
- It invents facts. A language model will confidently fill in a cask type or age statement it doesn't actually know.
- It ignores your catalogue. It might write "Speyside, Scotland" when your shop uses "Speyside", or create a new spelling of a distillery you already stock. Every inconsistency quietly breaks a filter or a collection.
- It doesn't know what you already sell. Restocked products need a stock update, not a duplicate listing.
The system below is designed around those three problems. It researches real sources, forces every answer into the shop's existing values, checks the catalogue first, and keeps a human in the loop before anything goes live.
The architecture: four workflows, each with one job
The system is split into four n8n workflows. Invoice Parsing reads the invoice and checks it against the catalogue, Products Sync keeps that catalogue current, Creation Flow handles every button click in Slack, and Error Workflow watches over the rest.

Restocked products skip the AI entirely and only get their inventory updated. New products go through research and matching, and every result lands in Shopify as a draft that the team checks before publishing.
Step 1: Turn the invoice PDF into structured line items
The first workflow starts when someone uploads an invoice to a dedicated Slack channel. A Slack Trigger fires, an If node checks that the message actually contains a file, and the bot replies straight away so the team knows the invoice was picked up.
From there the workflow downloads the PDF through Slack's API and runs it through n8n's Extract from File node to get the raw text. That text goes to an AI Agent with a Structured Output Parser attached. The parser is what makes this reliable: instead of free text, the agent must return a JSON array of line items with fixed fields such as name, product code and quantity.
A Split Out node then turns that array into one item per product, so every later step works on a single product at a time.
Check what you already sell
In parallel, the workflow calls a sub-workflow that syncs the Shopify catalogue into an n8n data table, then reads it back. A Code node compares each invoice line against that catalogue, and an If node splits the results:
- Already in Shopify: the product gets a Slack message with an option to add the invoiced quantity to stock.
- Not in Shopify yet: the product gets a Slack message with an option to create it.
Both paths build their messages with Slack's Block Kit, are merged back together, and are posted to the channel as one overview of the invoice. Nothing has changed in Shopify at this point. The team decides what happens next.
Step 2: Research the product on the web
When someone clicks to create a product, Slack sends the click to a webhook in the second workflow. The first thing that workflow does is research: two web searches run in parallel through the Tavily search API, and a Merge node combines the results.
We use a search API built for AI rather than scraping Google, because it returns clean page content instead of HTML. That keeps the prompts short and the costs predictable.
A relevance gate before the expensive part
Search results aren't always about the right product. A limited edition might share a name with a standard bottling, or a small producer might barely show up online. So before anything else, a Relevance Agent reads the results and decides whether they actually describe the product on the invoice.

If they don't, the workflow stops and tells the team in Slack. This one check prevents the most damaging failure: a confident, well-written listing about the wrong whisky.
Extract the facts
If the results pass, an Extraction Agent pulls out the raw facts: producer, bottler, country, region, cask type and so on. Like every agent in this system, it returns structured output, so later steps always receive the same fields. At this stage the values are still in whatever form the sources used. Turning them into the shop's own values is the next step.
Step 3: Match every attribute to your own catalogue
This is the part that makes the output usable in a real shop. Instead of letting the AI decide what to write in each field, every attribute gets its own small matcher that can only choose from values the shop already uses.
After extraction, the workflow fans out into parallel branches, one per attribute: country, region, distillery, bottler and cask type. Each branch follows the same four-node pattern:

- If: did the extraction find a value for this attribute at all? If not, the branch is skipped rather than guessing.
- Get row(s): load the allowed values for this attribute from an n8n data table, each stored together with its Shopify ID.
- Code: format that list together with the extracted value into a compact prompt.
- Matcher Agent: pick the closest existing value and return its Shopify ID, through a structured output parser.
So if a source says "Speyside region, Scotland", the region matcher returns exactly "Speyside", because that's the option in the shop's list. If a source spells a distillery slightly differently, the distillery matcher maps it to the spelling already used on the shop's other products.
Set it once, reuse it on every bottle
Each row in those tables holds a value and the ID of the matching entry in Shopify. So the region matcher doesn't just return the text "Speyside". It returns the ID of the Speyside entry that already exists in the shop, and the new product is linked to it.
That makes the shop's richer content reusable. A distillery's background or a bottler's story is written once in Shopify, and every new bottle linked to it shows that content automatically. The AI never has to rewrite it, and it can't drift out of sync between products.
Why separate agents instead of one?
We could have asked a single agent to fill in every field at once. We split it up for two reasons. Each matcher only sees the reference list it needs, which keeps prompts short and focused, and a narrower task tends to produce fewer mistakes. The trade-off is more model calls per product, which we'll come back to in the lessons below.
Writing the description and tasting notes
Alongside the matchers, a Description Agent writes the content of the product page. It runs in parallel, so it adds no extra waiting time. Next to the description it also returns an title in the house style and flavour notes. Every field may be an empty string when the sources don't say, which gives the agent an explicit way to admit it doesn't know instead of inventing notes.
Finally, a Merge node collects every branch, and a Code node assembles the complete product for Shopify.
Step 4: Decide in Slack, verify in Shopify
People stay in control at two moments: before a product is created, and before it goes live.
- In Slack, before creation. Each new product in the invoice overview has three buttons. Accept starts the research and creation, Reject skips the product, and Edit opens a Slack modal to correct its details first.
- In Shopify, before publishing. Every generated product is created as a draft and never published automatically. The team checks it in Shopify, the way it will appear in the shop, and publishes it when it looks right.
This is what makes store owners comfortable with AI touching their catalogue. The automation does the slow research and data entry, but a person who knows the products has the final say, in the tool they already use to run the shop.
One webhook, many buttons
Slack sends every interaction from your app (button clicks, modal submissions) to a single URL. So the creation workflow starts with a Webhook node, a Code node that unpacks Slack's payload, and a Switch node that routes each action to its own branch: accept, reject, edit, save edit, and add stock.
Respect Slack's three-second rule
Slack expects your app to acknowledge an interaction within three seconds, or the user sees an error. Researching a product takes far longer than that. So in most branches the very first node is Respond to Webhook, which acknowledges the click immediately, and the real work continues afterwards.
The modal is the exception. When someone saves an edit, the response you send back controls what happens to the modal, so that branch does its work first and responds at the end.
Native nodes vs. HTTP requests
You'll notice several Slack and Shopify steps use HTTP Request nodes instead of n8n's built-in nodes. That's deliberate. Opening and updating modals and sending rich Block Kit messages need Slack API methods the built-in node doesn't fully cover, and Shopify's inventory updates are easier to control through its API directly. Store your tokens in n8n credentials rather than in the request headers, so they never end up in an exported workflow.
Step 5: Keep it reliable
Two supporting workflows don't do anything visible, but the system wouldn't hold up in daily use without them.
Products Sync keeps a copy of the Shopify catalogue in an n8n data table. Checking an invoice against a local table is faster and simpler than paging through the Shopify API for every line item. The invoice workflow calls it as a sub-workflow before matching, so the comparison always runs against current data.
Error Workflow is set as the error handler for the other workflows in their n8n settings. When any node fails, whether it's a timeout, an expired token or an unexpected PDF layout, it alerts the team instead of failing silently. With a system that runs on its own, a silent failure is the worst kind: invoices pile up and nobody notices until a product is missing from the shop.
Lessons learned
The system runs in production, but a few things only became clear once it did. If you're building something similar, these are worth knowing up front.
Structured output is not optional. Every agent in this system has a Structured Output Parser. Without it, one oddly formatted answer breaks every node downstream. With it, each agent behaves like a predictable function.
Plan for products the internet doesn't know. Small independent bottlings sometimes have almost no information online. Right now the workflow creates a placeholder product in Shopify and notifies the team when the relevance check fails.
Know your cost per product. Splitting the work across one agent per attribute improves accuracy, but it means many model calls for each product. Measure what one product creation costs and how long it takes, so you can judge whether a smaller model or a merged agent makes sense for some fields.
Split big workflows early. The creation workflow handles both the Slack interactions and the whole enrichment pipeline. If we built it again, we'd move the enrichment into its own sub-workflow, so it can be tested on its own and reused elsewhere.
Wrapping up

The final result: click on publish and the bottle is live.
The real value here isn't any single AI call. It's the structure around them: check what you already sell, research real sources, refuse to guess when the sources are wrong, force every answer into your own catalogue's values, and let a person check the result before it goes live. That pattern works for any shop with detailed product data, whether you sell spirits, wine, coffee, books or spare parts.
Want to see what this changed for the retailer in practice? Read the case study. And if you'd like a system like this built around your own catalogue and suppliers, get in touch.
