An invoice lands in the AP inbox at 9:14 on a Tuesday. The supplier has been on the vendor master for eleven years. The line items look reasonable, the tax is calculated correctly, the remittance details match what finance has on file. And the field where a purchase order number should sit is empty.
So the clerk opens ME2N, filters by vendor, and finds thirty-one open purchase orders. Four of them are close on value. Two of them have overlapping material descriptions. One was raised by a plant that does not normally buy this category, which might be a data entry error or might be exactly the right answer. Twelve minutes later the clerk gives up, parks the document in MIR7, and sends an email asking the requester which PO this belongs to. The requester is on annual leave until the following Monday.
That single invoice will now age for six days before anyone touches it again. Multiply it by the fifteen to thirty percent of invoice volume that arrives without a usable PO reference in a typical mid-market manufacturer, and the picture gets uncomfortable. The general case for invoice automation has been made a thousand times over. What rarely gets discussed is the specific, grubby, high-volume failure mode that quietly eats most of the promised savings. Invoices that should match a purchase order but do not say which one.
Why the PO number goes missing in the first place
Before designing a matching strategy, it helps to be honest about the causes, because different causes need different recovery techniques.
The most common reason is that the supplier's billing system was never told. A buyer raises a PO in SAP, emails it to a sales rep, and the rep forwards it to whoever handles order entry. The order gets keyed into the supplier's ERP, but the customer reference field is optional in their setup, so it stays blank. Every invoice generated from that sales order for the next three years will be missing the reference. Nothing is broken on either side. The data simply never crossed the boundary.
The second cause is a format mismatch. The PO exists on the invoice, but it does not look like a PO. It appears as "Ref: 45-0012-3391" when SAP expects 4500123391. It shows up inside a free-text note that reads "as per your order dated 14 March". It is printed in the delivery address block rather than the reference block, because the supplier's template puts it there. Optical extraction finds a string, the matching engine does not recognize the shape, and the invoice falls to exceptions.
Third, and increasingly common, are consolidated and framework billing patterns. A supplier bills monthly across nine deliveries drawn from four different purchase orders. There is no single PO number to quote, so the header carries a contract number, a customer account number, or nothing at all. The real references sit at line level, or on attached delivery notes, or nowhere.
Fourth is the genuine no-PO spend. Utilities, rent, legal retainers, courier accounts, professional subscriptions, and the long tail of maverick purchasing that never went through procurement. These invoices are not missing a PO. They never had one. Trying to match them to a purchase order is not just futile, it is dangerous, because a forced match against a plausible-looking open PO creates a receipt that never happened.Â
A matching system that treats all four causes identically will fail at all four. The recovery logic has to be layered.
Two different problems hiding under one label
Most AP teams use "non-PO invoice" as a single bucket. That is the root of a lot of wasted effort. There are really two populations.
The first population is unreferenced PO spend. A purchase order exists in EKKO and EKPO, goods or services were received, the GR posted, the commitment sits in the GR/IR clearing account waiting for an invoice. The invoice arrived without naming the document. The correct outcome is a three-way match posted through MIRO logic. Every day this invoice sits unmatched, the GR/IR account carries a balance that will later need painful reconciliation.
The second population is true non-PO spend. No purchase order exists, no goods receipt was posted, no commitment was recorded. The correct outcome is a direct FI posting with GL account, cost centre or internal order, and tax code derivation, plus a workflow approval based on the coding rather than a receipt.
These need opposite treatments. Sending a true non-PO invoice into a PO matching engine produces false positives. Sending an unreferenced PO invoice into GL coding produces a duplicate cost, because the goods receipt already booked the expense and the manual posting books it a second time. The GR/IR balance then sits open forever and someone in year-end close has to unpick it.
So the first job of the cascade is not to find a PO. It is to decide, with evidence, which population the invoice belongs to. Only then does the search make sense.
Why single-shot matching fails
Most standard matching logic tries one thing. It looks for a PO number, and if it does not find one it gives up and routes to a human queue. Some systems add a second attempt using vendor and total amount, then stop.
The problem is that no single signal is strong enough on its own. Vendor plus amount sounds decisive until you deal with a supplier who ships identical pallets to three plants at the same price. Material description sounds decisive until you meet two purchase orders for the same part number raised four days apart. Delivery note references are excellent when present and absent on half of incoming documents.
What actually works is the way a good AP clerk works. They do not run one query. They run a sequence, each cheaper and more certain than the next, and they stop as soon as they have enough evidence to be confident. They start with the obvious identifiers, fall back to shipping references, then to line item content, then to amount patterns, and finally to what this supplier usually gets coded to. At each step they carry a mental sense of how sure they are.
That sequence is the cascade. The engineering work is turning it into something deterministic, auditable, and fast enough to run on ten thousand invoices a night.
Pass one. Recovering identifiers that were always there
A surprising share of "missing" PO numbers are present on the page and simply not recognised. This pass costs almost nothing and clears a large slice of volume, which is why it runs first.
The technique is pattern recovery rather than field extraction. Instead of asking "what is in the PO number field", the engine asks "does any string anywhere in this document resolve to a valid open purchase order for this vendor". That includes the body text, the line item descriptions, the email subject line the invoice arrived on, the filename of the attachment, and any text embedded in the footer.
Candidate strings get normalised before lookup. Separators are stripped, so 45-0012-3391 and 4500.123.391 both collapse to 4500123391. Common OCR confusions are expanded into variants, so a string read as 45OO123391 generates a candidate with zeros substituted for the letter O. Leading document type prefixes that suppliers add on their own, like "PO" or "ORD" or "CUST", are trimmed. Range validation then discards anything that does not fall inside the number ranges configured for purchasing documents in the client's SAP instance, which kills most noise instantly.
Every surviving candidate is checked against open purchase orders for that vendor. Not against all purchase orders, which is both slow and risky, but against the vendor-scoped open set. A match here is near certain, because the probability of a random number in an invoice body coinciding with a live PO for that exact supplier is very low.
This pass typically resolves somewhere between a third and a half of apparently unreferenced invoices, and it is worth building properly before anything more sophisticated gets attention.
Pass two. Following the delivery paper trail
When the PO number genuinely is not on the document, the next strongest signal is usually the shipment.
Suppliers who omit customer PO references very often still quote their own delivery note number, packing slip number, or advance shipping notice reference, because their warehouse needs it. That number is the thread to pull. In SAP the inbound delivery sits in LIKP and LIPS, the goods movement posts to MKPF and MSEG, and the purchase order history in EKBE links the movement straight back to the PO line.
So the lookup chain runs from the delivery reference on the invoice, through the material document, to the purchase order item. It is a join, not a guess. When the reference resolves, the confidence is as high as a direct PO quote, and it carries a bonus. It identifies the exact PO line items involved, not just the header, which is what a three-way match actually needs.
The same logic applies to bill of lading numbers on freight-adjacent invoices, and to carrier tracking references that were recorded against the inbound delivery. A well-built engine treats all of these as delivery-class identifiers and runs them through the same resolution path.
There is a useful side effect here. If a delivery reference resolves to a goods receipt that has already been fully invoiced, the engine has just detected a probable duplicate invoice before it entered the ledger. That check costs nothing extra and prevents a class of loss that is much more expensive to recover after payment.
Pass three. Fingerprinting the line items
Now the engine has to work from content rather than references, and this is where most naive implementations go wrong by comparing description strings.
Description matching is weak because supplier descriptions and buyer material texts rarely agree. "HEX BOLT M8X40 A2-70 ZINC" on the invoice and "Bolt, hexagon, M8x40, stainless" in EKPO refer to the same thing and share almost no tokens.
The stronger approach builds a fingerprint from the identifiers that actually travel between systems. The supplier part number is the best of these, because it appears on the invoice by default and is stored in the purchasing info record in EINA and EINE against the buyer's material number. That mapping is a direct bridge. Where info records are maintained, supplier part number matching is close to deterministic.
Below that sit manufacturer part numbers, UNSPSC or internal commodity codes, batch and serial references, and unit of measure with conversion factors. Each contributes to the fingerprint. Free text description similarity is included, but weighted low and computed on normalised tokens rather than raw strings, so that it breaks ties instead of driving decisions.
The candidate set matters as much as the comparison. The engine does not fingerprint against every open PO in the system. It builds a scoped candidate list from the vendor, the company code, the plant implied by the ship-to address on the invoice, the currency, and a date window derived from the invoice date and typical lead times for that supplier. A well-scoped candidate set is usually under twenty documents. Scoring twenty candidates on structured fingerprints is fast and produces a clear separation between the winner and the rest, which is the property you want.
If the top candidate does not clearly separate from the second, that is signal too. Two near-identical scores mean the engine has genuinely ambiguous evidence, and the correct behaviour is to stop rather than to pick.
Pass four. Making the numbers reconcile
Amounts and quantities are the most misused signal in invoice matching, because people expect them to agree exactly and then discard them when they do not.
They almost never agree exactly, for reasons that are perfectly legitimate. Partial deliveries mean the invoice covers three of ten ordered units. Over-delivery within tolerance means eleven units arrived against ten ordered. Freight, insurance, and packaging appear as unplanned delivery costs that were never on the PO. Cash discount terms, foreign currency translation at a different rate than the PO, price unit differences where the PO is priced per hundred and the invoice per unit, retrospective rebates, and tax treatment differences all shift the total.
So this pass does not test for equality. It tests whether a candidate PO can be reconciled to the invoice through a permitted sequence of adjustments, and it records that sequence as evidence.
The reconciliation attempts open quantity first, comparing invoice quantity against the delivered-but-not-yet-invoiced balance in the PO history. It then applies the PO's own pricing conditions to the reconciled quantity, converting price units and currency at the appropriate rate. Remaining differences are tested against configured tolerance keys, the same ones SAP uses in invoice verification, so that the engine's tolerance behaviour matches what the client's own controls already allow. Residuals that fall outside tolerance get classified by type, because a residual that exactly equals a known freight charge is a very different thing from an unexplained variance of the same size.
A candidate that reconciles cleanly through a short, explainable adjustment chain earns high confidence. A candidate that only reconciles by invoking three unlikely adjustments at once earns very little, even if the final numbers land close. The shape of the explanation matters more than the size of the gap.
Pass five. Contracts, scheduling agreements, and service entry sheets
Some spend never has a discrete purchase order to find, and the cascade needs to recognise that rather than keep searching.
Framework agreements are the clearest case. A scheduling agreement or value contract governs the relationship, and individual releases draw against it. An invoice quoting the contract number needs to resolve against the release schedule and the goods receipts posted under it, not against a standalone PO.
Services are harder and more consequential. A services invoice against a limit order does not match to goods movements at all. It matches to service entry sheets in ESSR, which are accepted separately in ML81N. So when the fingerprint suggests a services line, the engine has to switch its target from material documents to service entries, compare the invoiced services against accepted and not-yet-invoiced entries, and handle the case where the entry sheet exists but has not been approved yet. That last state is common and needs its own routing, because the invoice is correct and simply early. Parking it and notifying the service approver resolves it. Escalating it to AP exceptions does not.
Subcontracting, consignment settlement, and evaluated receipt settlement each have their own document paths, and each needs explicit handling. An engine that quietly treats them as ordinary PO matches will produce confident wrong answers.
Pass six. Learning what this supplier usually gets
The final search pass does not look for a purchase order. It looks at history.
Every previously posted invoice for a vendor is a labelled training example. It records which PO was matched, or which GL account and cost centre were used, along with the plant, the requester, the tax code, and the approver. Across a few thousand postings, strong patterns emerge. This vendor always bills company code 1000 against cost centre 4310. That vendor's invoices are always coded to the same maintenance order type. This particular supplier always references PO lines raised by the same three buyers.
Two things come out of this. For invoices that do belong to a PO, historical patterns narrow the candidate set and break ties that content alone cannot resolve. For invoices that do not, the same patterns produce a proposed GL coding with a confidence score, which is the actual answer for true non-PO spend.
The important design choice is to keep this pass advisory rather than decisive. Historical inference is excellent at ranking and terrible at certainty, because it will confidently reproduce whatever the organisation did last year, including its mistakes. Used as a tiebreaker and a coding proposer, it adds real value. Used as a primary matcher, it entrenches bad coding at machine speed.
Arbitration, or how to combine evidence without fooling yourself
Running six passes is straightforward. Deciding what to do with six partly agreeing answers is where the engineering earns its keep.
A weak design stops at the first pass that returns anything. A better one runs the passes that are cheap and independent, then arbitrates. The arbitration layer takes the candidate purchase orders surfaced by any pass, aggregates the evidence each one accumulated, and produces a single score per candidate plus an overall decision.
Two properties matter more than the scoring formula itself.
The first is evidence independence. Two signals that derive from the same underlying fact should not both be counted as confirmation. A delivery note that resolves to a PO line and a quantity that reconciles against that same delivery are not two independent proofs. They are one proof observed twice. Double counting correlated evidence is the fastest route to confident wrong answers.
The second is separation margin. The absolute score of the winning candidate matters far less than the gap between it and the runner-up. A top candidate scoring 0.91 with a second at 0.89 is a worse situation than a top candidate scoring 0.72 with a second at 0.31. In the first case the engine has found two plausible answers and has no basis for choosing. In the second it has found one. Any auto-posting threshold that ignores separation margin will eventually post an invoice against the wrong purchase order, and it will do so on a document that looked highly confident.
The output of arbitration is a three-way routing decision. High confidence with clean separation posts automatically through the standard invoice verification path. Medium confidence parks the document with the proposed match pre-populated, so the reviewer confirms rather than investigates, which is a fundamentally different and much shorter task. Low confidence, or a strong signal that no PO exists, routes to non-PO handling with a proposed GL coding attached.
That middle band is the one most teams undervalue. An invoice parked with a ranked shortlist and the supporting evidence displayed takes a reviewer forty seconds. The same invoice parked bare takes twelve minutes and an email. The volume moved from the second experience to the first is where most of the realised saving actually comes from, not from the auto-post rate alone.
Why a wrong match costs more than no match
There is a temptation, once a cascade is working, to push the auto-post threshold down and celebrate a higher touchless rate. This is worth resisting, because the cost of the two error types is wildly asymmetric.
An unmatched invoice costs a clerk's time. Annoying, measurable, recoverable.
A wrongly matched invoice consumes the open quantity on a purchase order that belongs to a different transaction. The genuine invoice for that PO then arrives and fails, because the balance is gone. The GR/IR account for both purchase orders goes out of balance. Inventory valuation absorbs a price variance against the wrong material. If the wrong PO belonged to a different cost centre or a different profit centre, the misposting travels into management reporting and stays there. Someone finds it during close, and the correction requires reversal documents, a credit memo, or a manual GR/IR clearing entry.
The recovery effort for one bad match routinely exceeds the saved effort of a hundred good ones. So the threshold should be set by measuring precision at each confidence band against a manually verified sample, not by targeting a headline automation percentage. A cascade running at seventy-eight percent auto-post with 99.7 percent precision is worth considerably more than one running at ninety-one percent with 96 percent precision, and the second one will be quietly generating a reconciliation backlog that nobody has attributed to it yet.
The edge cases that break naive implementations
Several patterns need deliberate handling, and each one will otherwise produce a category of silent errors.
Multi-PO invoices carry lines belonging to two or more purchase orders. The cascade has to run at line level, not header level, and the arbitration has to allow a split posting. An engine that forces a single PO per invoice will either fail these entirely or, worse, match the whole invoice to whichever PO covered the largest line.
Credit memos invert the reconciliation logic. They reference a prior invoice rather than a delivery, and the correct target is the original posted document in RBKP and RSEG. Matching a credit memo to an open PO balance is always wrong.
Consolidated monthly statements are not invoices at all in many cases, and they frequently duplicate documents already posted individually. Detecting statement-class documents early and diverting them prevents a whole family of duplicate payments.
Intercompany invoices carry references from the sending entity's document numbering, which will not resolve against the receiving entity's purchasing documents. These need entity-aware lookup or explicit exclusion.
Currency and rounding at line level can push a perfectly correct invoice outside tolerance when the header total is fine, or the reverse. Reconciliation has to be attempted at both levels and the results compared, because a header that reconciles while every line fails is a strong indicator that the candidate is wrong.
Measuring whether any of it is working
Touchless rate is the number everyone reports and the least useful one in isolation. Three measures give a truer picture.
First-pass resolution by cascade level shows where the volume is actually being caught. If pass one is clearing only eight percent, the identifier recovery logic is under-built and the cheapest available win is being left on the table. If pass six is carrying most of the load, the engine is leaning on inference far more than it should be.
Precision by confidence band tells you whether the thresholds are honest. This requires periodically pulling a sample of auto-posted documents and verifying them manually. It is unglamorous and it is the only way to know.
Median time from receipt to posting, split by routing outcome, exposes whether the middle band is genuinely faster. If parked-with-proposal invoices are taking as long as bare exceptions, the proposal is not being presented usefully, and the interface needs work rather than the algorithm.
Rolling it out without breaking the ledger
The safest deployment pattern runs the cascade in shadow mode first. Every incoming invoice goes through the full pass sequence and the engine records what it would have done, while humans continue to process normally. After a few weeks there is a labelled dataset comparing machine decisions against human ones, which makes threshold setting an empirical exercise rather than a guess.
From there, automation opens narrowly. One vendor group, one company code, one document type, with the threshold set conservatively high. Precision gets measured, the threshold moves, and scope expands. Each pass gets tuned against real failures rather than imagined ones.
The tuning work never fully stops, because supplier behaviour changes. A supplier upgrades their billing system and starts quoting PO numbers correctly, which shifts volume from pass three back to pass one. A new plant comes online with different receiving practices. A category moves from purchase orders to a framework contract. A cascade that was tuned once and left alone degrades slowly and quietly.
What changes when the cascade works
The visible change is that the no-PO exception queue stops being a queue. It becomes a short review list where most items arrive with an answer already attached and the reviewer's job is confirmation rather than investigation.
The less visible change is better. GR/IR balances stop accumulating unexplained residuals, because invoices reach their purchase orders while the goods receipts are still recent and the people who raised them still remember. Month-end reconciliation gets shorter. Early payment discounts that were being lost to processing delay start getting captured. And the AP team stops spending its mornings on document archaeology and starts spending it on supplier queries, disputes, and the exceptions that genuinely need judgement.
None of that comes from a single clever algorithm. It comes from accepting that finding a missing purchase order is not one problem with one answer, but a sequence of narrowing questions, each one cheaper than a human asking it, and each one knowing when to stop and hand over.
Â
Artificio builds document processing and workflow automation for finance teams running SAP. AP Studio handles the full path from invoice capture through matching, coding, and posting via standard SAP interfaces, including the no-PO cascade described here. To see how it performs against your own invoice mix, get in touch at support@artificio.ai.
