The Supplier Invoice That Was Paid Twice
By Ergini, Software & AI Developer
A composite story. The company and the people in it are invented. The problem, the rules and the system are real, and the full blueprint is in the use case library.
TL;DR
A composite story: at an invented conveyor-systems maker near Paderborn, a coater's invoice arrives as a ZUGFeRD file and as a stamped paper copy, and is paid twice, because the supplier exists twice in the creditor master and the ERP only compares invoice numbers within one account. The pipeline I would build reads every invoice from the AP mailbox, resolves the supplier by VAT ID, IBAN and name, compares invoice numbers with everything that supplier sent, including invoices still in approval, and matches goods invoices to the order and receipt. Copies are held, and people approve and release every payment.
Paid twice, by the supplier's count
Suppliers do not usually call to say they have been paid too much. This one does. The bookkeeper at a powder coating company rings Frauke, who runs accounting at a maker of conveyor systems near Paderborn, and reads out two payments of €14,212.60 against the same invoice, RE-2026-00412, received two weeks apart. Should she refund the money, or set it against the next invoice?
Nobody in this story is real, and neither is the conveyor maker: 160 people, frames and drives for warehouses and parcel hubs, and around 1,200 supplier invoices a month, most of them against purchase orders. Two clerks, Kemal and Dagmar, key them into the ERP from a shared Outlook mailbox, a post room that scans paper, and whatever colleagues forward.
Frauke thanks the bookkeeper, asks for a credit note, and puts the phone down with a question that has nothing to do with the coater: how many of these did nobody call about?
Two creditors for one coater
She rebuilds the path that afternoon, and nothing on it is careless.
The coater sends its invoices as ZUGFeRD files now, a PDF with the invoice data embedded as XML. This one reaches the AP mailbox in mid-August. Kemal posts it against the coating order on the coater's creditor account, and it waits a week for Bernd, the production manager, who approves invoices between shifts on the shop floor.
The coater's office also emails every invoice to the person who ordered, as it always has. Bernd prints his copy, stamps it "sachlich richtig", the German stamp that says the work was done as ordered, signs it and sends it to accounting in the internal mail. The post room scans it into the same mailbox three weeks after the original arrived.
Dagmar picks up the scan and searches the ERP for the supplier. The coater was taken over last year and renamed, purchasing created a new creditor under the new name, and nobody blocked the old one. Her search finds the old one first. There is no open order on that account, so she posts the scan as an invoice without a PO, coded to subcontracted coating, and sends it to Bernd. He approves it within the hour. He recognizes it, and he is right to: it is his batch.
The ERP does check for duplicates. It compares invoice numbers within one creditor account, and this invoice now sits in two. Both copies go out in ordinary payment runs, fourteen days apart.
How many nobody called about
Frauke calls me with that question, and before we talk about any pipeline I ask for three exports: two years of posted supplier invoices with their payments, the creditor master with VAT IDs and IBANs, and an ordinary week of the AP mailbox. The first answer does not need a build. It needs a query.
The look-back groups every posted invoice by the supplier's VAT ID and IBAN instead of the creditor number, strips spaces, leading zeros and prefixes such as "RE-" from the invoice numbers, and compares. Amount and date come second, as a net for numbers that were typed two different ways.
The result is short: a handful of pairs worth a look, two of them real, one already settled by a credit note nobody had linked to it. What surprises me is the creditor master. Thirty-one suppliers have two or more active creditor accounts, left behind by takeovers, renamings and a habit of creating a new record whenever a search came back empty. Each one is a place the ERP's own duplicate check cannot see.
So the order of the build is settled before any model is involved: identity first, then the number, then the match.
Who sent it, before what it says
The pipeline reads the AP mailbox through Microsoft Graph, with the app restricted to that one mailbox, and stores every attachment unchanged with a hash. E-invoices are parsed directly, since XRechnung and ZUGFeRD files already carry their data. Everything else, the scans and the plain PDFs, is read by a model into a strict schema, with the page each value came from, and classified first: invoice, credit note, reminder, statement or delivery note. Only an invoice can become something to pay.
Then code decides who sent it: VAT ID first, then IBAN, then name. Two creditor accounts with one VAT ID are one supplier, and the second account goes on a list for Frauke to merge or block. The invoice number is compared with everything that supplier has sent, posted or still waiting for approval, and a goods invoice is matched against its order and goods receipt. Here are the coater's two copies, as the pipeline would see them:
| Check | The e-invoice | Bernd's stamped copy |
|---|---|---|
| Arrives | ZUGFeRD file in the AP mailbox | Scan from the post room, three weeks later |
| Read by | Code, from the embedded XML | The model, from the scanned page |
| File hash | New | Also new: the stamp and the scan make it a different file |
| Supplier | VAT ID matches creditor 70388 | Same VAT ID, so creditors 70388 and 70112 are one supplier |
| Same number seen before | No | Yes: the e-invoice, still waiting for Bernd |
| Order and goods receipt | Three lines of three matched | Receipt already fully invoiced by the e-invoice |
| Outcome | Approval card to Bernd | Duplicate hold, filed against the e-invoice |
Either the number or the receipt would have held it on its own. The copy never reaches Bernd as something to approve: it lands in the exceptions queue with the reason written on it and the original beside it. The structured copy wins, and the scan is filed against it, stamp and all. A reminder gets the same treatment. It is matched to the invoice it chases, and if that invoice is waiting for approval, the reminder goes to the approver as a nudge, never to the ledger as a second bill. The reading follows the document extraction guide, and every check in order is in the invoice processing blueprint.
The replay that missed it
Nothing posts at first. The pipeline runs in shadow beside Kemal and Dagmar, who work exactly as before, and the first thing it runs on is the past: the look-back pairs, and the coater's invoice above all.
My first version missed the coater. It looked the supplier up in the ERP the way Dagmar had, took the first creditor it found, and checked for duplicates inside that account. The replay landed on 70112, saw no earlier invoice there, and would have sent the scan to Bernd for approval, stamp and all. The rule that came out of it is the one in the table: identity comes from the VAT ID, then the IBAN, then the name, and the creditor number is only where the result gets posted.
The second problem was the opposite. Amount and date, the second net, held the freight forwarder's invoices every day: one invoice per shipment, the same flat rate, the same date, each with its own shipment number. A check that cries wolf twenty times a day is switched off by the end of the month. So a match on the invoice number holds; a match on amount and date only asks, with both documents side by side, and a different shipment reference on each is enough to let it through.
Holds, not payments
The pipeline never pays anyone. It hands the ERP an approved, posted bill, keyed on supplier and invoice number so a retry can never post it twice, and Frauke's team releases the payment run as before. What changes is what reaches each person:
- Kemal and Dagmar clear the exceptions queue: duplicates, unknown suppliers, price and quantity differences, each with its reason written on it.
- Bernd approves in Teams, on a card with the supplier, the amount, the match result and the early-payment discount deadline on top. Silence brings a reminder, then his deputy.
- Frauke owns the limits: tolerances, the approval matrix and the rules for the second net, kept in configuration, not in a prompt someone could talk around.
- Master data changes take two people: merging or blocking a creditor, and any new bank details, which are confirmed by a call to a number already on file.
Because the pipeline records how long approvals take, one more thing is settled before launch. What gets reported per approver is agreed with the works council first, since § 87(1) no. 6 BetrVG covers systems that can monitor performance.
The next stamped copy
Bernd will keep stamping invoices, and nobody needs him to stop. The next time a stamped copy comes up from the post room, it lands in Dagmar's queue as a duplicate of an e-invoice already sitting on Bernd's Teams card, the two documents side by side. She files it as a copy. Bernd approves the real one between shifts, inside the discount window, and the coater's bookkeeper has no reason to call.
Frauke works through the list of doubled creditors, two people per change, and it gets shorter every week. The question she asked when she put the phone down, how many did nobody call about, now has a query she can rerun whenever she likes.
Capture tool, or a build that sees the PO
For a company with few purchase orders, buy. Dext and Hubdoc, which comes with Xero, capture invoices into Xero and QuickBooks; Candis, Moss, Pleo and Yokoy add approval flows and work well with DATEV; NetSuite and most accounting systems now have capture built in. If your invoices are mostly utilities, subscriptions and services approved by one person, one of these costs less than any build.
A build earns its cost when the checks need data those tools cannot see: purchase orders and goods receipts in your ERP, suppliers with more than one creditor account, approval rules by plant or cost center. With PO matching it usually lands in the multi-step tier of AI workflow automation. The full blueprint has the pipeline check by check, the six invoices that break naive automation, and the rollout from shadow run to touchless, one supplier at a time, following the human-in-the-loop patterns I use elsewhere.
Frequently asked questions
How do duplicate supplier invoices get paid?
Usually through ordinary gaps rather than fraud. The same invoice arrives as an e-invoice and as a forwarded or posted copy, and two people key it. If the supplier exists twice in the vendor master, or the number is typed two ways, a duplicate check that compares exact numbers within one vendor account never sees the pair. Both copies are approved, and both are paid.
How do you catch duplicate invoices before payment?
Resolve the supplier by VAT ID, then IBAN, then name, not by vendor number, so two master records for one company count as one supplier. Normalize the invoice number by removing spaces, leading zeros and prefixes such as 'RE-', and compare it with everything that supplier sent, including invoices still waiting for approval. Use amount and date as a second net that asks a person rather than holds.
Does three-way matching prevent duplicate payments?
It helps, because the first invoice uses up the goods receipt, so a second copy finds nothing left to match and lands in the exceptions queue. It does not cover invoices without a purchase order, such as services, rent and utilities, or a copy posted to a second vendor record, so the duplicate check on supplier and invoice number still has to run on every invoice.
What does accounts payable automation cost?
When it matches invoices against purchase orders and goods receipts in your ERP, it usually lands in the multi-step tier of AI workflow automation rather than the entry tier, because the matching is where the work is. The effort moves with the ERP's interface, the number of entities sharing the inbox and the approval rules. Running costs are a few cents of model use per scanned invoice.