Rounding differences in UBL invoices

Prevent and handle rounding differences in UBL invoices: PayableRoundingAmount, VAT rounding and VAT-inclusive prices.

One of the most frustrating error messages when sending e-invoices is a rounding difference. The VAT totals do not match the line amounts, or the invoice total deviates by a cent from the calculated sum. The result: the invoice is rejected during validation. This article explains where rounding differences come from and how to prevent or resolve them.

Why do rounding differences occur?

Rounding differences arise from the combination of three factors: multiplication, division and rounding to two decimal places. A few examples:

Unit price with many decimals. A price of 3.333... euros per unit x 3 units = 9.999 euros. Rounded, that is 10.00 euros. But if you first round the unit price to 3.33 and then multiply: 3.33 x 3 = 9.99. A one cent difference.

VAT per line versus VAT per total. If you calculate and round VAT per invoice line and then add them up, the sum may differ from VAT calculated over the total. At 21% VAT on 33.33 euros, that is 7.00 euros (rounded). But 21% of 3 x 33.33 = 21% of 99.99 = 21.00 euros. While 3 x 7.00 = 21.00 euros as well. In this case it matches, but with other amounts it may not.

VAT-inclusive prices. Some sectors (retail, hospitality) work with prices including VAT. The net amount must then be calculated back, which introduces an additional rounding moment.

How UBL handles rounding differences
Decimal places: current and future rules

EN 16931-1:2017 (current production version) requires that all amounts are rounded to 2 decimal places, regardless of currency.

The revision EN 16931-1:2026 (CEN approval 13 March 2026, urn:cen.eu:en16931:2026) replaces this with a currency-dependent number of decimal places: the number of decimal places = the "minor unit" column of ISO 4217 for the currency used. Peppol implementation via OpenPeppol is expected as BIS Billing 4.0 (indicatively 2027). Until that version is in production, the current 2-decimal rule applies.

Exceptions in 2026 (fixed, regardless of currency):

  • BT-129 Invoiced quantity: 4 decimal places.
  • BT-146 Item net price, BT-147 Item price discount, BT-148 Item gross price: ISO 4217 minor unit + 2 extra decimal places.
  • BT-149 Item price base quantity: 2 decimal places.
  • Percentage fields (including BT-138 allowance percentage, BT-152 VAT rate): 2 decimal places.

Impact eConnect: outbound invoices are always in euros (minor unit 2) — no change. Inbound invoices may contain currencies with minor unit up to 4 — processing must handle up to 4 decimal places. See also EN 16931-1:2026 major changes for the complete overview.

PayableRoundingAmount

The UBL standard has a special element for rounding differences: PayableRoundingAmount in the LegalMonetaryTotal block. This element absorbs small rounding differences, so the PayableAmount can be a round number:

<cac:LegalMonetaryTotal>
  <cbc:LineExtensionAmount currencyID="EUR">99.99</cbc:LineExtensionAmount>
  <cbc:TaxExclusiveAmount currencyID="EUR">99.99</cbc:TaxExclusiveAmount>
  <cbc:TaxInclusiveAmount currencyID="EUR">120.99</cbc:TaxInclusiveAmount>
  <cbc:PayableRoundingAmount currencyID="EUR">0.01</cbc:PayableRoundingAmount>
  <cbc:PayableAmount currencyID="EUR">121.00</cbc:PayableAmount>
</cac:LegalMonetaryTotal>

The 0.01 euro difference is explicitly stated. Validation rules allow a PayableRoundingAmount, provided the difference is small enough (typically a maximum of 1 euro, depending on the profile).

XPath: Invoice/LegalMonetaryTotal/PayableRoundingAmount.

Example 1 (rounding up): TaxInclusiveAmount is 9.99 euro, the desired payable amount is 10.00 euro. Then PayableRoundingAmount = 0.01 euro and PayableAmount = 10.00 euro.

Example 2 (no PayableAmount change): with a 4-decimal price calculation, a sub-micro difference can arise, for example 8.2646 × 1.21 = 10.000166. In that case PayableAmount remains unchanged and no PayableRoundingAmount is needed.

VAT rounding per rate

VAT calculation in a UBL invoice works per VAT rate, not per line. All line amounts with the same VAT rate are summed to form the tax base (TaxableAmount), and VAT is calculated on that. This prevents rounding per line and subsequently getting a cumulative rounding difference.

The formula is:

TaxableAmount = sum of LineExtensionAmount per VAT category
              - AllowanceTotalAmount per VAT category
              + ChargeTotalAmount per VAT category

TaxAmount = TaxableAmount x Percent / 100 (rounded to 2 decimal places)

Important: always calculate VAT on the total tax base per rate, not per line. Per-line VAT calculation is the most common cause of rounding differences.

VAT-inclusive prices

With VAT-inclusive prices, the net amount must be calculated back. The standard approach is:

  1. Calculate the net amount per line: gross / (1 + VAT percentage/100)
  2. Round to 2 decimal places
  3. The LineExtensionAmount is this net amount
  4. The difference between the sum of all net line amounts and the gross total minus VAT may produce a rounding difference
  5. Absorb this with PayableRoundingAmount
<!-- Price including VAT: EUR 12.10 per unit, 3 units -->
<cac:InvoiceLine>
  <cbc:ID>1</cbc:ID>
  <cbc:InvoicedQuantity unitCode="EA">3</cbc:InvoicedQuantity>
  <cbc:LineExtensionAmount currencyID="EUR">30.00</cbc:LineExtensionAmount>
  <cac:Price>
    <cbc:PriceAmount currencyID="EUR">10.00</cbc:PriceAmount>
  </cac:Price>
</cac:InvoiceLine>

In this example, the VAT-inclusive price is 12.10 euros. The net amount is 10.00 euros per unit (12.10 / 1.21). Times 3 = 30.00 euros. VAT: 21% of 30.00 = 6.30 euros. Total: 36.30 euros. That matches exactly 3 x 12.10 euros. But with prices that do not divide neatly, a difference arises.

How eConnect handles this

eConnect validates every invoice for internal consistency. If there is a small rounding difference within tolerance, the invoice is accepted. For larger deviations, you receive a clear error message indicating where the difference lies.

The automatic XML repair function of eConnect can in some cases add a missing PayableRoundingAmount if the difference is smaller than the tolerance threshold. But it is always better to handle rounding correctly in your own software.

Practical rules of thumb
  1. Calculate VAT per rate, not per line. First add up all line amounts per VAT rate, then calculate VAT on that total.
  2. Round at the end. Work internally with more than two decimal places and only round when filling in the XML elements.
  3. Use PayableRoundingAmount for the last cent. If despite good rounding a small difference remains, absorb it with this element.
  4. Check the sum. TaxExclusiveAmount + TaxAmount must equal TaxInclusiveAmount. And TaxInclusiveAmount minus PrepaidAmount plus PayableRoundingAmount must equal PayableAmount.
  5. Test with the eConnect Validator. Send your invoice through the validator before sending it. It checks all calculation rules.
Frequently asked questions
How do I prevent rounding differences in my invoice?

Calculate VAT per rate (not per line), work internally with more than two decimal places and only round when filling in the XML elements. If despite good rounding a small difference remains, absorb it with the PayableRoundingAmount element.

What is PayableRoundingAmount?

It is a special UBL element that absorbs small rounding differences in invoice totals. The difference is explicitly stated, so the invoice still validates. Most profiles allow a maximum of 1 euro.

Can eConnect automatically repair rounding differences?

In some cases the automatic XML repair function can add a missing PayableRoundingAmount if the difference is within the tolerance threshold. But it is always better to handle rounding correctly in your own software.

Check your invoice