A leading product engineering company, creating adaptive software solutions to improve operations, providing businesses with expert development services from across domain.
A leading product engineering company, creating adaptive software solutions to improve operations, providing businesses with expert development services from across domain.
An e-invoice can pass every totals rule and still get VAT wrong. EN 16931 validation requires document-level discounts to carry their own VAT category.

An invoice can pass every totals rule in the European e-invoicing standard and still get VAT wrong. The usual cause is not arithmetic. It is a discount that was never assigned to a VAT category. EN 16931 validation treats that as an error because, under the standard, a document-level discount must carry its own VAT category and rate — and systems that model discounts as a simple deduction from the total get it wrong in a way that looks right.
That used to be a bookkeeping quibble. Under clearance e-invoicing, where a government platform validates the invoice before it legally exists, it is a rejected invoice.
A detailed explainer from Shipmind Labs sets out the distinction clearly.
Line-level allowances and charges belong to an invoice line. They inherit that line's VAT treatment, so a 10% discount on a standard-rated item reduces the standard-rated base. Nothing extra needs declaring.
Document-level allowances and charges apply to the invoice as a whole — a loyalty discount, an early-payment reduction, a delivery charge. These must explicitly declare their own VAT category and rate. The explainer's line is the one to remember: a discount that belongs to no breakdown group does not exist.
The consequence is that a company-wide discount on a mixed invoice cannot be one number. If an invoice contains standard-rated and reduced-rated goods, a document-level discount has to be split and attributed to each VAT group it affects, or it has to be applied at line level instead.
EN 16931 includes business rules that check invoice totals reconcile, and the explainer names them: BR-CO-10 for the sum of line net amounts, BR-CO-13, BR-CO-15 and BR-CO-16 for how net, VAT and gross totals relate, and BR-CO-14 for whether the declared VAT total matches the VAT breakdown.
The trap is that these rules check consistency with what the invoice declares. If the discount has been attached to the wrong VAT group, the declared breakdown can be internally consistent and still wrong. The explainer shows an invoice that satisfies all of those rules while misstating VAT by €23 because of how the discount was applied.
The only check that catches it is rebuilding each VAT group from the ground up: take the lines in that group, apply the document-level allowances and charges attributed to it, compute the base and the VAT, and compare against what the invoice declares. Top-down reconciliation of totals will not find the error, because the error is in the attribution, not the addition.
An illustration makes the problem concrete. The figures below are ours, chosen for easy arithmetic, and use a 20% standard rate and a 5.5% reduced rate.
An invoice has €1,000 of standard-rated goods and €500 of reduced-rated goods, and the customer receives a 10% loyalty discount on the whole order: €150.
Attributed correctly, the discount is split in proportion to each group: €100 against the standard-rated goods and €50 against the reduced-rated goods. The standard-rated base becomes €900, with €180 of VAT. The reduced-rated base becomes €450, with €24.75 of VAT. Total VAT is €204.75.
Attributed to one group, which is what a system does when a discount is a single header amount with the default rate, the whole €150 comes off the standard-rated base. That base becomes €850, with €170 of VAT. The reduced-rated goods keep their full €500 base, with €27.50 of VAT. Total VAT is €197.50.
The two invoices differ by €7.25 of VAT, yet both can be internally consistent: net, VAT and gross totals all add up on each. Only a bottom-up rebuild with the correct attribution shows that the second one understates standard-rated VAT and overstates reduced-rated VAT. Scale that across thousands of invoices a month and the error is material — and under a clearance model, each one is a rejection waiting to happen.
The same logic applies to document-level charges. A delivery fee added to a mixed invoice needs a VAT category too, and treating it as outside the VAT breakdown is the mirror-image mistake.
The explainer's implementation advice matches what we see in real systems.
Store amounts as integers. Binary floating point cannot represent many decimal amounts exactly, which is how 0.1 + 0.2 becomes a rounding difference on a total. Keep amounts in minor units and convert only at the edge.
Round per VAT group, at a defined point. The approach described is half-up rounding applied per VAT group. Rounding every line and then summing produces a different answer from summing and then rounding, and the standard's tolerance is narrow: one cent of rounding difference on a total is tolerated, two is not.
Validate where the invoice is produced, not in a separate step. The explainer's implementation throws on violations at the point of serialisation to UBL. Its reasoning is blunt and correct: validation that a caller can skip under deadline is not validation.
Model discounts as data with a VAT category. The root cause in most systems is a schema where a discount is a single amount on the invoice header. Fixing the calculation without fixing the model means the next integration reintroduces the bug.
A related question worth settling early is who decides how a discount is attributed. Proportional allocation by base value is the common approach, but some commercial agreements specify that a discount applies only to certain product lines. That is a business rule, not a technical default, and it belongs with finance rather than being chosen silently by whoever writes the invoicing code.
EN 16931 is the European semantic standard for electronic invoices, and the European Commission maintains the programme around it. Formats such as UBL, CII and Factur-X express the same underlying model, so the discount rule applies whichever format your country or platform uses.
What has changed is enforcement. The explainer points to Belgium's Peppol requirement from January 2026, Poland's KSeF platform validating invoices before they count as delivered, and France's reform from September 2026 — under which every business must now be able to receive e-invoices, which turns receiving structured invoices into an integration problem for every ERP. In clearance models, a rejected invoice does not exist legally. The customer has not received it, the payment clock has not started, and the feedback arrives in seconds rather than at year-end.
That is the shift worth internalising. VAT errors used to surface in audits months later, when someone could fix them with a credit note. Now they surface at submission, and they stop the invoice.
One consequence is easy to miss. A credit note correcting an invoice has to mirror the original VAT breakdown, including how any document-level discount was attributed. If the original misattributed the discount, a correct-looking credit note can fail validation against it, or pass and compound the error. Teams usually discover this when a customer disputes an invoice and the correction itself is rejected — which is the worst possible moment to learn that the discount model is wrong.
The fix is the same in both directions: generate invoices and credit notes from one VAT-group model, so a correction is computed from the same attribution as the document it corrects, rather than from a second implementation written by a different developer.
This is the unglamorous core of most e-invoicing projects: not the connection to the platform, but whether the data model underneath can express a discount correctly. It is also the kind of logic that deserves a recorded snapshot before anyone touches it, the approach we described for characterising legacy code before refactoring. If your ERP stores discounts as a header amount, that is the place to start, and it is the most common fix in the custom ERP invoicing work we do.
Document-level allowances and charges must declare their own VAT category and rate. Line-level allowances inherit the VAT treatment of the invoice line they belong to, so only discounts applied to the whole invoice need an explicit category.
Rules such as BR-CO-10, BR-CO-13 to BR-CO-16 check that declared totals are consistent. If a discount is attributed to the wrong VAT group, the declarations can still agree with each other while the VAT amount is wrong, in one worked example by €23.
Rebuild each VAT group from the bottom up: take its lines, apply the document-level allowances and charges attributed to that group, compute the taxable base and VAT, then compare with what the invoice declares. Top-down reconciliation cannot catch misattributed discounts.
One cent of rounding difference on a total is tolerated, but two cents is not. Storing amounts as integers in minor units and applying half-up rounding per VAT group at a defined point avoids the floating-point errors that cause larger differences.
Clearance-style systems include Poland's KSeF, which validates invoices before they count as delivered. Belgium's Peppol requirement began in January 2026 and France's reform in September 2026, all using formats built on the EN 16931 model.
Build a fixture invoice with at least two VAT rates, line and document-level discounts and a document-level charge, recompute each VAT group independently, include half-cent rounding cases, and run the output through a format validator that fails the build.
Ready to take the first step towards unlocking opportunities, realizing goals, and embracing innovation? We're here and eager to connect.
11th Floor, O-Hub, Chandaka Industrial Estate, Infocity, Bhubaneswar, Odisha 751024
Level 4, 11 York Street Sydney Startup Hub Sydney, NSW – 2000
30 N. Đinh Nghệ, Phước Mỹ Sơn Trà, Đà Nẵng / Da Nang City – 550000
Level 25, AIDP Business Tower, Dubai Marina, United Arab Emirates
50 Beauchamp Street, Wellington, WGN 5028, New Zealand