❝

❝ In June a warehouse counted 340 enamel kettles off a purchase order for 400. The supplier invoiced for 400, and the bookkeeper paid it in full in July, because nothing in QuickBooks disagreed with the invoice. The business is a composite: a direct-to-consumer camp cookware brand in Denver turning over about $11M a year with 19 staff, selling through Shopify, with its stock at a ShipBob fulfilment centre. Modelled across a year of its 236 supplier invoices, 41 fail the match, worth $27,940. The design below compares every invoice with the purchase order and the warehouse's own count before anything is paid, and starts the supplier's claim clock on the day the stock is counted. It costs about $100 a month to run.

The kettles came in on a Wednesday.

The purchase order said 400. The supplier's packing list said 17 cartons of 20. ShipBob's receiving team counted 17 cartons, scanned 340 enamel kettles into stock on 3 June and marked the receiving order complete. Shopify's stock levels updated the same day. Everything the warehouse was responsible for went right.

The invoice arrived on 11 June: 400 enamel kettles at $14.20, $5,680.00, net 30. Dale, the brand's part-time bookkeeper, opened the purchase order in QuickBooks, saw 400 kettles at $14.20, turned it into a bill and scheduled it for the payment run on Friday 10 July. The purchase order agreed with the invoice. Nothing else in QuickBooks had an opinion.

From then on, the 60 kettles that never arrived existed in exactly one place: the balance sheet.

The brand, Dale and Marisol are a composite, built from the patterns we see in e-commerce brands of this size, and the figures attached to them are design projections. The software capabilities, the published contract terms, the law and the benchmark figure are real, and linked to their sources.

Purchase order for 400 kettles, warehouse receipt for 340, supplier invoice for 400, paid in full on 10 July

The business

A direct-to-consumer brand in Denver selling enamel camp cookware, cast iron and drinkware. Around $11M a year in revenue and 19 staff, with almost every sale going through its Shopify store. Stock lives at a ShipBob fulfilment centre rather than a warehouse of its own. It buys from 14 suppliers, 8 overseas factories and 6 domestic, and in the last 12 months it processed 236 supplier invoices.

Purchase orders are raised in QuickBooks Online, which only offers them on its Plus and Advanced plans; the brand is on Plus. Dale enters and pays bills three days a week. Marisol, the operations manager, owns the suppliers and the ShipBob relationship. An outside accountant closes the books each quarter, though nobody had ever asked her to check stock against ShipBob.

What is actually going wrong

Every person in this story did their job properly. The money left through the gaps between three records, each of which held a third of the answer.

The count and the bill live in different systems. ShipBob knew on 3 June that 340 kettles had arrived. Its receiving API records an expected quantity and a received quantity for every SKU on every receiving order. QuickBooks knew what had been ordered and, from 11 June, what had been invoiced. Neither system knows the other exists. Inside QuickBooks Online, the way you record goods arriving against a purchase order is to turn it into a bill; a reply on Intuit's own community forum confirms that marking items received on a purchase order without creating a bill is not available. So the bill becomes the record of what arrived, and the bill was typed from the supplier's invoice.

A two-way match passes a short delivery every time. Dale did check. She compared the invoice with the purchase order, line by line, which is what most small businesses mean by checking an invoice. Quantity 400, price $14.20: both documents agree. That test answers whether the supplier billed what you ordered. It has no way of answering whether the supplier delivered what they billed, because the only record that knows is in a different system. It is why purchasing departments such as Rockefeller University's require a three-way match for goods: order, receiving record and invoice, all three.

The supplier's clock started before the invoice existed. The kettle supplier, one of the six domestic ones, had terms allowing 15 days from receipt to claim a shortage. That is a common shape of clause; Behr's standard sales terms, for example, set the same 15 days. The window opened on 3 June, when the cartons were counted, and closed on 18 June. The invoice arrived on 11 June and was paid on 10 July. Even if Dale had spotted the shortage on the day she paid, she would have been more than three weeks too late to claim under the contract. Had she compared the invoice with the warehouse count on the day it arrived, she would have had seven days left. Nothing in her systems showed her the count.

June and July 2026 calendar: received 3 June, invoice 11 June, claim window closes 18 June, paid 10 July

The law was on the brand's side about the 60 kettles. Under the Uniform Commercial Code a buyer pays at the contract rate for goods accepted, which here means 340 kettles. It also has to notify the seller within a reasonable time after it discovers, or should have discovered, the breach, or lose any remedy. With the warehouse's count on record from 3 June, a supplier could fairly argue the brand should have known that day. The contract's 15-day window, and the calendar, were on the supplier's side. (We are not lawyers, and contract terms vary. The point is what the brand could prove, and when.) UK readers: the Sale of Goods Act takes a similar line on short deliveries, and this week's article covers it.

What it costs

In late August the accountant reconciled QuickBooks inventory against ShipBob's stock report, the first time anyone had compared the two in a year. QuickBooks held 1,140 more units than the warehouse did. Tracing them took her most of three weeks, and most of the trail led back to 23 supplier invoices paid in full for deliveries that had arrived short, worth $19,480.

Marisol wrote to every supplier involved. Six issued credits, totalling $4,870, mostly as goodwill. The rest pointed to their claim windows.

Run through the matching logic described below, the year's 236 supplier invoices produce 41 variances: the 23 short shipments; 11 invoices priced above the purchase order, worth $4,370; 2 duplicate invoices paid twice, worth $3,160; and 5 carrying freight or handling charges that were never on the purchase order, worth $930. $27,940 in all.

Treemap of $27,940 in unmatched charges over 12 months: short shipments $19,480, price above PO $4,370, duplicates $3,160, charges not on PO $930

41 of 236 is 17.4%. For comparison, Ardent Partners' Accounts Payable Metrics that Matter in 2026 puts the industry average invoice exception rate, the share of invoices that need a person to sort out, at 19.9%. By that rough measure this brand is ordinary. The difference is that an AP team with a matching process sees its exceptions, and this brand had nothing that could.

The design

The part that needs a model is reading the invoice. Fourteen suppliers send fourteen layouts: clean PDFs, scanned PDFs, a spreadsheet from one domestic supplier, cartons on one line and units on the next. The part that must never be a model is the match. Whether 400 is more than 340 has one correct answer, and it has to be the same answer every time.

The other decision is where the process starts. The shortage was visible on 3 June and the invoice arrived on 11 June, so the agent starts at the warehouse, and the invoice joins it later.

Invoice matching agent workflow: receipt and invoice triggers, invoice read, three-way match, claim clock, ops review, supplier claim, payment list, supplier ledger

Trigger, receipt. ShipBob sends webhooks as a receiving order's boxes are scanned and when the order completes. The agent pulls the expected and received quantity for each SKU, and checks daily for any receiving order still showing as partially arrived after 48 hours, because a short delivery can sit in that state instead of completing.

Stage 1, receipt check. If any SKU arrived short of the purchase order and no further delivery is due against it, the agent looks up that supplier's claim window, sets the deadline, and drafts a shortage notice the same day, before any invoice exists. Marisol gets it in Slack with the deadline in the first line.

Trigger, invoice. Supplier invoices go to a dedicated accounts payable inbox. Suppliers who email Dale directly are asked to switch; until they do, she forwards.

Stage 2, invoice read. A language model extracts the supplier, invoice number, PO number, and each line's SKU, quantity, unit of measure, unit price and any extra charges, with a confidence score on every field. Anything below the threshold goes to Dale with the PDF beside the extracted fields.

Stage 3, three-way match. Deterministic code joins three records: the purchase order from the QuickBooks Online API, the received quantities from ShipBob, and the extracted invoice. It converts units first, because one supplier bills in cartons of 20 and ShipBob counts single units. Then it runs four tests: quantity billed against quantity received, with zero tolerance; unit price against the purchase order, within 2%; a duplicate check on supplier plus invoice number, and on supplier plus amount within 60 days; and any charge that does not appear on the purchase order.

Checkpoint, ops review. Any variance goes to Marisol with the three documents side by side and the money at stake. She approves the claim, overrides it with a reason (a price rise agreed on the phone, say), or asks ShipBob for a recount.

Stage 4, supplier claim. The agent drafts the shortage or pricing claim with the receiving order, the carton count and the purchase order line attached, and asks for a credit memo. Marisol sends it. The agent tracks the reply and chases after 7 days.

Stage 5, payment list. Every Thursday the agent builds Friday's payment list for Dale: matched bills at the received quantity, with any disputed amount held back and noted for the supplier. Dale still presses the button. The agent never pays anything.

Supplier ledger. Every variance, claim and outcome is stored against the supplier, along with each supplier's claim window taken from their terms. Once a quarter it produces a scorecard: short-ship rate, credits won, days to credit. That is the document Marisol takes into the next price negotiation.

The Monday morning test

The first week should produce variances. With 17% of the year's invoices failing the match, a week of four or five invoices with no variance at all is more likely to mean the PO numbers on invoices are failing to join to ShipBob's receiving orders than that every supplier has suddenly become perfect. Have Marisol run the first ten matches by hand alongside the agent, and check the join before celebrating.

Before and after

Measure

Before

After

When a short delivery is seen

At reconciliation, weeks or months later

The day the warehouse counts it

Invoices checked against the warehouse count

0 of 236

All of them

Shortage claims inside the supplier's window

None

Drafted on receipt day

Unmatched charges paid in 12 months

$27,940

Projected under $3,000

How money comes back

Goodwill credits, $4,870

Credit memo, or held back before payment

Bookkeeper time on supplier bills

About 3 hours a week

About 1 hour a week

The after column is a projection. The $3,000 allows for price rises agreed by phone and approved on override, and for claims a supplier refuses even inside its window.

The build guide

Recommended stack. n8n for orchestration, a language model API that accepts PDFs and returns structured output, Postgres for the match records and the supplier ledger, the QuickBooks Online Accounting API for purchase orders and bills, the ShipBob API for receiving orders, Slack for Marisol's reviews and Gmail for the supplier inbox and claims.

Architecture pattern. Count, read, match, claim, pay. The model reads; code decides; a person pays.

The n8n nodes, in order. Webhook node for ShipBob's receiving events, plus a daily Schedule Trigger for orders stuck part-arrived, then HTTP Request to ShipBob for the receiving order's quantities. Gmail Trigger on the accounts payable inbox, then Extract from File to pull the PDF's text (scanned PDFs need an OCR step, or an HTTP Request to a model that reads PDFs directly), feeding an Information Extractor node (or a Basic LLM Chain with a Structured Output Parser) that returns the invoice lines as fields. HTTP Request to the QuickBooks Online API for the purchase order. Code node for unit conversion and the four match tests. Postgres node to store every match and update the supplier ledger. Slack node using Send and Wait for Response with a short form for Marisol: approve, override with a reason, or recount. Gmail node to create claim drafts. A Schedule Trigger on Thursday afternoon to build Dale's payment list, and a second on the first of each quarter for the supplier scorecard.

Build steps. Week one, collect every supplier's terms and pull out two things for each: the shortage claim window and the units they bill in. That becomes the supplier table and the unit conversion table, and it takes longer than anyone expects. Week two, the invoice reader, tested against the last six months of invoices, about 120 PDFs, with the confidence threshold set where the misreads stop. Week three, the match logic and a back-test against the whole year of invoices. In this design that run is modelled, and it produces the $27,940. Week four, claims and the payment list. Run alongside Dale's existing process for a month.

Estimated build time. 45 to 60 hours. The invoice reader is the impressive part and the easy part. The supplier table is the dull part and the one that pays.

What it costs to run

Component

Monthly

n8n cloud

$50

Language model API, about 20 invoices a month

$5

Postgres instance

$25

Monitoring and error alerting

$20

Total

$100

Year one, with an outsourced build at the upper end, lands around $9,000. The year before it was built paid $27,940 in charges that did not match, $23,070 after the goodwill credits.

Failure modes and edge cases

Units of measure. Mismatched units either invent a huge shortage (invoice in units, count in cartons) or, worse, hide a real one (invoice in cartons, count in units). Keep a conversion table per supplier SKU, version it, and send any variance above 50% to review as a probable unit error before anyone writes to a supplier.

The warehouse can miscount. If the count is wrong, the claim is wrong, and a supplier relationship pays for it. Above a set amount, say $500, ask ShipBob for a recount before the claim goes out, and attach the box-level receiving record as evidence.

Short at the factory, or short in transit. Cartons missing against the packing list may be a carrier problem, and a carrier claim runs on a different clock. Whole cartons missing should be noted on the carrier's delivery receipt at the dock. Interstate US motor carriers cannot set a claim-filing period shorter than nine months, but shortages found later inside intact cartons usually have to be reported within days; TForce Freight asks for 5 business days. An ocean leg on imported stock runs under different rules again. The agent compares the carton count with the packing list as well as the purchase order: cartons the supplier never packed go to the supplier claim, cartons that were packed and never arrived go to the freight claim.

Split deliveries. One purchase order can arrive as two receiving orders weeks apart, with the invoice landing after the first. Sum receipts per purchase order line, and hold the invoice until either the second delivery arrives or Marisol closes the order short.

Invoices with no PO number. Domestic suppliers often leave it off. Match on supplier plus SKU against open purchase orders, send anything ambiguous to Dale, and ask the supplier to quote the PO number from then on.

Agreed changes that never reach the purchase order. Marisol agrees a price rise on the phone and the agent flags it on every invoice until somebody updates the order. The override reason is stored, so the ledger can tell an agreed rise from a creeping one.

Take this with you: the matching rules table

These are the rules the Denver design started from. Copy them into a spreadsheet, hand them to whoever pays your supplier bills, and argue about the tolerances before you build anything.

Test

Compare

Starting tolerance

When it fails

Quantity

Billed against received, after unit conversion

Zero

Hold the difference and start the claim

Price

Invoice unit price against purchase order

Hold the difference and ask ops

Duplicate

Supplier plus invoice number; supplier plus amount within 60 days

Exact

Invoice number match: hold the whole invoice. Amount match only: Dale confirms

Charges not ordered

Any invoice line with no purchase order line

None without approval

Ops approves or disputes

Claim window

Receipt date plus the supplier's terms

Per supplier

Claim drafted on receipt day

To test the idea on your own bills first, export them to one tab and your warehouse receipts to another. Bills: PO number in column A, SKU in B, quantity billed in C, unit price in D. Receipts: PO number in A, SKU in B, quantity received in C. In the Bills tab, column E:

=SUMIFS(C$2:C2,A$2:A2,A2,B$2:B2,B2)-SUMIFS(Receipts!C:C,Receipts!A:A,A2,Receipts!B:B,B2)

Put the invoice date in column G and sort the Bills tab by it, oldest first, with headers in row 1. That compares everything billed so far on each PO line with everything received against it, so split deliveries, a supplier who invoices each delivery separately, and a duplicate bill all show up. In column F:

=IF(OR(A2="",B2=""),"CHECK ROW",IF(E2>0,"SHORT "&MIN(E2,C2)&" = $"&TEXT(MIN(E2,C2)*D2,"#,##0.00"),""))

Rows with a missing PO number or SKU are flagged instead of passed. A bill with no receipt at all shows its full quantity as short, which is correct: it was billed and nothing was counted in. We ran both formulas in a spreadsheet against each of those cases before printing them. Convert units before you paste, or a supplier who bills in cartons will never show a shortage, because 20 cartons billed is a smaller number than 340 units received.

The arithmetic

The brand had every number it needed on 3 June. ShipBob had counted the cartons. QuickBooks had the order. The invoice arrived eight days later with a different number on it. The only missing piece was a subtraction, 400 minus 340, done before the payment run rather than at a reconciliation in August.

The agent costs $100 a month. Most of what it does is that subtraction, about 20 times a month, on the day the stock arrives.

One question

The design holds back any invoice billed above the received quantity with zero tolerance, and allows 2% on price. Zero is strict: it will stop an invoice over one missing mug. What quantity tolerance do you run, or would you, before an invoice needs a person to look at it? A percentage and what you sell is plenty. Leave it in the comments below, or reply to Thursday's newsletter if that is easier. The most useful answers will be quoted, with permission, in next week's issue, and if the number is better than ours we will change the Blueprint.

If someone else in your business pays the supplier bills, send them this. Ideally with last month's warehouse receipts attached.

If your version of this problem is stranger than this one, say so in the comments and we will design it in public.

Your industry is probably already in the back catalogue. One bottleneck, mapped end to end, every week, free to read and precise enough to build from. Subscribe here.

Do you know anyone who would find this Blueprint interesting? Share it with them:

Follow AdAI News on LinkedIn and X.

Reply

Avatar

or to participate

Keep Reading

View more