Extracting Vendor Names From Invoices When Every Invoice Formats Them Differently
9 min read · updated August 11, 2026
The reason vendor-name extraction has stubbornly poor accuracy is not that models read letterheads badly. It is that a typical invoice contains four or five entity-shaped strings, several of them are legally required to be there, and the schema field called vendor_name does not say which one it wants.
Five names, all of them real
Open any B2B invoice and count the places an organisation is named. There will usually be more than one, and they will often disagree.
- The brand on the letterhead. A trading name, a product name, or a group name. It is the largest text on the page and the thing a model reaches for first, which is precisely the problem.
- The supplying legal entity. Usually in small print in the footer with a company registration number, and usually a different string — “Northwind Logistics Ltd” trading as “Northwind”. In the EU, Article 226(5) of Directive 2006/112/EC requires the full name and address of the taxable person, which is this entity and not the brand.
- The remit-to party. Whoever is to be paid. On most invoices this equals the supplier, and on a meaningful minority it does not: shared service centres, group treasury, and factored receivables all break the equality.
- The bank account holder. Printed next to the IBAN, and sometimes a fourth string again.
- The ship-from party. A warehouse or a third-party logistics operator that has nothing to do with who invoices you.
A model asked for “the vendor” will return whichever of these is most visually prominent. That is not a hallucination and it is not a low-confidence answer — it is a correct answer to an under-specified question, which is much harder to detect.
Three layouts and where each name sits
The single-entity invoice
Brand at top left, legal entity and registration number in a three-line footer, bank details in a box above the total. All five candidates resolve to one organisation. This is the majority case and it is why a naive extractor scores well on a small sample and falls over on a large one.
The group invoice
A parent brand at the top; the invoicing subsidiary named only in the footer with its own VAT number; and a shared-service remit-to address in a different country. Here the tax identifier belongs to the subsidiary, the payment goes to the service centre, and spend reporting probably wants the parent. Three answers, one document, nothing wrong with it.
The assigned invoice
The invoice carries an assignment notice: this receivable has been sold to a finance house, so pay the assignee, not the supplier. The wording is boilerplate and it is often the only sentence on the page that changes the bank details. Extraction that takes remit_to from the footer template rather than from the assignment paragraph pays the wrong party, and this failure mode is also exactly what invoice-redirection fraud imitates. Treat any document whose payment details differ from the supplier master record as a review item regardless of extraction confidence.
Which name wins, and for what
Stop trying to extract one field. Extract four, name them for the decision each one drives, and let them be equal when they are equal:
{
"supplier_legal_name": "Northwind Logistics Ltd",
"supplier_tax_id": "GB123456789",
"supplier_trading_name": "Northwind",
"remit_to_name": "Northwind Group Services BV",
"remit_to_iban": "NL00BANK0123456789",
"assignment_present": true
}- Paying the invoice uses
remit_to_*, verified against the supplier master, never against the letterhead. - Tax reporting and input-VAT recovery use
supplier_legal_nameandsupplier_tax_id, because that is the pair the tax authority will check. - Spend analytics and vendor consolidation use the parent, which is derived from the tax identifier through your own hierarchy, not read off the page.
- Duplicate detection uses the tax identifier, for the reasons in detecting a duplicate by content.
Resolve on the identifier, not the string
Names are unstable in every direction. The same supplier writes itself “ACME GmbH”, “Acme G.m.b.H.”, “ACME Gesellschaft mit beschränkter Haftung” and “ACME DEUTSCHLAND” across four documents; two unrelated suppliers in two countries share a name; and OCR will occasionally hand you a ligature or a soft hyphen inside one. Fuzzy string matching over a supplier master with fifty thousand rows produces exactly the kind of confident near-miss that survives review.
The tax identifier is the field to match on because it is machine-checkable before you look it up. An EU VAT number is a two-letter country prefix plus a nationally defined body, and the member states publish the per-country formats; the union’s VIES service answers whether a given number is currently valid for cross-border trade. An Indian GSTIN is fifteen characters — a two-digit state code, a ten-character PAN, an entity character, a literal Z, and a check character — and the GST Network’s own portal is the authority on whether a given one is live. Validate the format locally the way you would any checksum-validated identifier field, resolve identity against the registry, and use the name only to break ties for a human.
The failures that reach production
- The customer’s own name extracted as the vendor. Self-billed invoices and consignment statements are issued by the buyer, so the buyer’s letterhead is at the top. Article 226(10a) of the VAT Directive requires the word “Self-billing” on exactly these documents; that token is a far better signal than position on the page.
- A logistics partner extracted from the ship-from block. Common on drop-shipped goods, and it produces a vendor record with no tax identifier, which is the tell.
- Suffix loss. A model normalising “Ltd” away merges two legally distinct entities in the same group. Keep the raw string alongside any normalised form; normalisation is a matching key, not a value.
- Two-page invoices where the footer is only on page two. If your pipeline sends one page at a time to save on image tokens, the legal entity is not in the context at all and the model will supply the brand instead.
None of these are caught by asking the model how sure it is. They are caught by asserting that the extracted supplier has a tax identifier, that the identifier resolves in the master, and that the remit-to bank details match the ones on file. Those assertions belong in the validation layer, as cross-field validation rules scored with per-field confidence, not in the prompt.