Reading the invoice is the easy part.
Every line checked against the price list that was actually agreed — the right version, the right unit, the right article — with the reason attached to every verdict.
A dozen invoices and the current price list are enough. You get every line back, checked, either way.
The model reads and proposes. Deterministic rules decide.
Units, conversion factors, which price list applies, the arithmetic, the verdict and the totals are computed, not generated. Every number is reproducible from one invoice line and one price-list row. When something is uncertain, the line says so, with the reason.
Reading the document is not the hard part. Knowing your rules is.
Any model can pull numbers off a PDF. What decides whether a line is right is everything around the number: which price-list version applies on that date, which unit the price is expressed in, whether a 5 kg pack and a 2.5 kg pack are the same article, whether frozen may ever match fresh, which discount level the customer inherits, and whether the supplier’s own printed reference can be trusted at all. That is the same engine Claro runs on supplier catalogs (decode, match, normalise, validate, write back under rules) pointed at a different document, a different reference and a different reader.
Eight cartons arrive. The invoice bills 19.2 kg at 7.85/kg. The price list agreed for that month says 7.40/kg, per kilo, for a carton of 6 × 400 g. Every one of those facts sits on a different document, and the line is only right if all of them agree.
What document reconciliation actually runs into
The price list has versions. The invoice has a date.
A line is priced against the version in force on the day it was issued, not today’s. When no version covers that date, that is the answer, not a gap to paper over with the last known price.
Delivered and billed are different quantities.
Eight cartons delivered, 19.2 kg invoiced. Both are read; the price applies to one of them, and the factor between them has to come from somewhere defensible. It is never invented.
The supplier’s own reference can’t always be trusted.
Codes get renumbered, reused, or contradicted by the label beside them. The article is resolved from the description alone, then checked against the printed code, so a disagreement surfaces instead of spreading.
Some differences are walls, not scores.
Chilled never matches frozen, however similar the labels. Pack format, temperature class and certification work as hard filters: a close match that breaks one of them is not a match.
The discount is inherited, not printed.
A buying group negotiates one rate, the central another, the delivery point a third: stacking or replacing, sometimes across a whole product family. The condition on the line is rebuilt from the agreements, which live in PDFs.
Fees, zero-value and out-of-scope lines still count.
A transport fee with no quantity, a line at zero that may hide an unrecorded free-goods agreement, a non-food line outside coverage. None are dropped; each is labelled and kept out of the totals it does not belong in.
What the engine does per line
-
01
Read every value, with its position on the page
Label, quantity, unit, unit price and printed reference, each with its page and position, so any value traces back to the document.
On line 3MOZZ FDL 6X400 FRESH · 8 CT · 19.2 kg · 7.85/kg · ref 48-2207 · p.1 row 3 -
02
Classify the line
Product, fee, equipment or out of scope. Only product lines are priced; the rest go to their own totals, labelled, never dropped.
On line 3product -
03
Identify the article in your price list
Resolved from label, pack and temperature first. The printed reference is then checked against the result, never trusted blindly. Hard filters remove candidates before anything is scored.
Line 3 reads MOZZ FDL 6X400 FRESH · ref 48-220748-2207Mozzarella fior di latte · CT 6 × 400 g · chilled0.94Chosen · printed reference agrees48-2290Mozzarella fior di latte · CT 6 × 400 g · frozenlabel 0.91Hard filter · Temperature class: chilled ≠ frozen48-2215Mozzarella fior di latte organic · CT 6 × 400 g · chilledlabel 0.89Hard filter · Certification: organic is not on the invoice line51-0420Burrata · CT 6 × 400 g · chilled0.58Rejected · Label conflict: burrata ≠ mozzarellaA close label that breaks a hard filter is not a match, whatever its similarity. Invented data. -
04
Convert the invoice unit to your price unit
The factor comes from the price-list row or a rule you validated, and its source is shown. When no factor is defensible, the line says so.
Delivered8 CTdelivery note DN-7731 · line 3× 2.4 kg per CT1 CT = 6 × 400 g · from price-list row 214, pack “CT 6×400 g”Invoiced19.2 kginvoice INV-20418 · line 3Price unitkgprice list PL 2026-02 · row 2148 × 2.4 = 19.2 kg✓ delivered and invoiced agreeThe factor is looked up, never guessed, and its source travels with the line. Invented data. -
05
Price against the version valid at the invoice date
The version is chosen by the invoice date, the discount is rebuilt from the agreements, and the arithmetic is done by rules, not generated.
A date in a gap is an answer: the line says no version was in force. Invented data. -
06
Route: two separate questions
Is the engine sure, and what must a human do? Both are answered on every line, separately.
On line 3Above price · +6.1% · engine: sure · you: dispute the price
“Needs a human” and “the engine is unsure” are not the same thing.
A line where the engine is completely certain and the price is wrong still needs a person: to contest it. That is the product working, not a doubt. So every line carries two badges.
Sure: the engine has no doubt about the line. Review: a person should look before it is used. Required: the engine cannot settle the line without one.
| Engine \ You | Dispute the price | Supply a missing grid | Query the quantity | Confirm the article | Nothing to do |
|---|---|---|---|---|---|
| Sure | 23 | 6 | 4 | – | 331 |
| Review | 3 | – | 5 | 17 | 9 |
| Required | – | 2 | 3 | 9 | – |
What goes in, what comes back
On your infrastructure or ours. Claro writes back through files and APIs rather than certified connectors, so this list is a guide, not a limit.
| Invoice · line | Read label | Article | Factor · source | Expected | Invoiced | Gap | Verdict | Conf. | Engine | You |
|---|---|---|---|---|---|---|---|---|---|---|
| 20418 · 3 | MOZZ FDL 6X400 FRESH | 48-2207 | 2.4 kg/CT · PL row 214 | 7.40/kg | 7.85/kg | +6.1% · +8.64 | Above price | 0.94 | Sure | Dispute the price |
| 20418 · 4 | PASSATA 12X700G | 30-1180 | 1 · priced per CT | 14.90/CT | 14.90/CT | 0.0% · 0.00 | Conforming | 0.97 | Sure | Nothing to do |
| 20418 · 5 | OLIVE OIL 5L | 22-0045 | 1 · priced per pc | 38.50/pc | 37.20/pc | −3.4% · −5.20 | Below price | 0.92 | Sure | Nothing to do |
| 20377 · 2 | PARMIGIANO WEDGE 1KG | 12-3301 | 1 · priced per pc | – | 21.90/pc | – | No grid at that date | 0.95 | Sure | Supply a missing grid |
| 20418 · 7 | TRUFFLE PASTE 180G | – | – | – | 9.80/pc | – | Not in the price list | 0.41 | Review | Confirm the article |
| 20418 · 8 | NAPKINS 2-PLY 40X40 | – | – | – | 3.10/pk | – | Out of scope | 0.99 | Sure | Nothing to do |
| 20418 · 9 | TRANSPORT | – | – | – | 18.00 | – | Fee | 0.99 | Sure | Nothing to do |
| 20418 · 10 | RICOTTA 6X250G | 48-3102 | 1.5 kg/CT · PL row 220 | 5.10/kg | 0.00 | – | Zero-value | 0.90 | Review | Supply a missing grid |
| 20418 · 11 | BURRATA 6X400G · ref 48-2207 | 51-0420 ? | 2.4 kg/CT | – | 8.90/kg | – | To verify | 0.52 | Required | Confirm the article |
A new layout is read, not configured.
Some vendors build a dedicated template for every supplier. That does not scale, and the day a supplier changes its layout, it breaks. The engine reads the document by its structure, not by a stored template. When it gets something wrong, a reviewer corrects it once, with no developer and no new mapping, and the correction is remembered.
It remembers, and the memory survives your next price list.
Matches are remembered against supplier, normalised label, pack and temperature, and deliberately not against the supplier’s reference, because that is the part most likely to change. When the price list is renegotiated and every code is renumbered, the decisions your team already made re-attach themselves.
Review shrinks month over month. It does not reset when the price list does.
Who it's for, and how Claro runs it.
The reader is operations, finance and purchasing, not the catalog team.
Every value, with its position on the page.
Product, fee, equipment or out of scope.
The article, from the label; the printed code is checked.
Invoice unit to price unit, factor and source shown.
Against the version valid at the invoice date.
Engine certainty and your action, as two badges.
From first call to a working pilot in ~11 business days.
We look at real documents
Bring a few genuine invoices and your price list, and we walk one line end to end, together.
No pre-cleaning
Invoices go in exactly as they arrived: scanned, skewed and multi-page is the normal case.
Checked & reviewable
Every line priced, with its verdict and reason, on your own documents, not a canned demo.
Scoped and signed
Measurable outcomes agreed, a pilot running on one real flow.
Build once. Deploy across every team.
Claro learns your rules once and applies them continuously — every run makes the next one better, and the same layer serves catalog, sales, procurement and your agents without a rebuild.
Invoice reconciliation: common questions
Do you need a template for each supplier?
No. New layouts are read without setup. When a line is read wrong, a reviewer corrects it, not a developer, and the correction is kept.
What if the supplier's reference is wrong?
The article is resolved from the label on its own, then compared with the printed reference. A disagreement is surfaced, not silently resolved.
What happens when no price is valid at the invoice date?
The line says exactly that. The nearest known price can be shown for context, but it is never used as if it applied.
Do validated matches survive a new price list?
Yes. A match is keyed on supplier, label, pack and temperature, not on the reference, which is the part that changes.
Are fees and zero-value lines dropped?
No. They are labelled, assigned where they belong, and kept out of the totals they would distort.
Who fixes a wrong conversion factor?
A reviewer, in the interface or through the API. The corrected factor is stored and reused.
Does the model decide whether a price is right?
No. The model reads the document and proposes the article. Units, conversion factors, the applicable price-list version, the arithmetic, the verdict and the totals are computed by rules, so every number can be reproduced from one invoice line and one price-list row.
Is our data used to train models?
No. Your data configures your account and nothing else. It is not pooled and not used to train shared models.
Can it run on our own infrastructure?
Yes: in your cloud, or locally with no external calls. Delivery and hosting are decided with you.
How fast is it?
It is built for scheduled batches rather than instant response. An SLA is agreed per account.