The short answer
PEPPOL-EN16931-R040 fails when a cac:AllowanceCharge carries both cbc:BaseAmount and cbc:MultiplierFactorNumeric, and cbc:Amount is more than 0.02 away from base amount x percentage / 100. Find which of the three values is wrong in the source data and correct that one.
cbc:MultiplierFactorNumeric is a percentage: 10 means ten per cent. It is not a multiplier such as 0.1.
What the rule checks
The rule runs on every cac:AllowanceCharge directly under the document root and directly under a line. Allowances and charges are treated the same way; cbc:ChargeIndicator plays no part. The allowance inside cac:Price is not covered.
If either cbc:BaseAmount or cbc:MultiplierFactorNumeric is absent, this rule has nothing to check and passes. An allowance or charge with neither element, only a fixed cbc:Amount, is fine.
When both are present, the expected amount is base amount x percentage / 100. The product is not rounded. The rule passes when cbc:Amount is within 0.02 of it, and the limit is inclusive: exactly 0.02 out passes, anything over fails.
Confirmed with the validator on an amount of 3.50 at 10 per cent: a base of 35.20 (expected 3.52, 0.02 out) passes; a base of 35.21 (expected 3.521) fails; a base of 35.30 (expected 3.53) fails. The same holds below the amount, and for a line-level allowance.
A percentage of 0 with a base amount expects an amount of 0, so a non-zero amount fails.
| Term | Meaning | UBL element |
|---|---|---|
| BG-20 | Document level allowances | cac:AllowanceCharge[cbc:ChargeIndicator = false] |
| BG-21 | Document level charges | cac:AllowanceCharge[cbc:ChargeIndicator = true] |
| BG-27 | Invoice line allowances | cac:InvoiceLine/cac:AllowanceCharge[cbc:ChargeIndicator = false] |
| BG-28 | Invoice line charges | cac:InvoiceLine/cac:AllowanceCharge[cbc:ChargeIndicator = true] |
How an integration ends up here
Possible causes, from the shape of the rule rather than from measured usage:
- The percentage is sent as a fraction, 0.1 for ten per cent, so the expected amount is a hundredth of what was intended.
- The base amount is taken from a different figure than the one the discount was calculated on, for example the gross line value instead of the value after an earlier discount.
- The amount was negotiated or edited by hand after the percentage was applied, and the percentage and base were left as they were.
- Several percentage discounts are compounded in the source system but sent as one allowance with the first percentage only.
- The amount is rounded per unit and multiplied up, which drifts more than 0.02 from a single calculation on the whole base.
How to fix it
- Take the failing
cac:AllowanceChargefrom the finding location and computecbc:BaseAmountxcbc:MultiplierFactorNumeric/ 100 with decimal arithmetic. - Decide which value is wrong by going back to the commercial terms. If the percentage or base is wrong, correct it and leave the amount alone.
- If the amount is wrong, correct it and then recalculate everything that depends on it: the line net amount for a line-level entry, or the allowance or charge total, the VAT breakdown and the document totals for a document-level entry.
- If the amount is a fixed sum that was never derived from a percentage, send
cbc:Amounton its own and drop bothcbc:BaseAmountandcbc:MultiplierFactorNumeric. Dropping only one of them failsPEPPOL-EN16931-R041orPEPPOL-EN16931-R042instead.
The recorded example is a document-level charge of 3.50 on a base of 35.00.
Failing: 35.00 x 20 / 100 = 7.00, amount sent 3.50, difference 3.50 Corrected: 35.00 x 10 / 100 = 3.50, amount sent 3.50, difference 0.00 Allowed difference: up to and including 0.02
Validate your corrected invoice
Before and after
These are fragments, not complete documents. The complete synthetic documents they come from are linked below.
Fragment of the failing invoice: 20 per cent of 35.00 is 7.00, but the charge amount is 3.50
<cac:AllowanceCharge>
<cbc:ChargeIndicator>true</cbc:ChargeIndicator>
<cbc:AllowanceChargeReasonCode>CG</cbc:AllowanceChargeReasonCode>
<cbc:AllowanceChargeReason>Example document charge</cbc:AllowanceChargeReason>
<cbc:MultiplierFactorNumeric>20</cbc:MultiplierFactorNumeric>
<cbc:Amount currencyID="GBP">3.50</cbc:Amount>
<cbc:BaseAmount currencyID="GBP">35.00</cbc:BaseAmount>
<!-- tax category omitted from this fragment -->
</cac:AllowanceCharge>Fragment of the corrected invoice: 10 per cent of 35.00 is the 3.50 that was charged
<cac:AllowanceCharge>
<cbc:ChargeIndicator>true</cbc:ChargeIndicator>
<cbc:AllowanceChargeReasonCode>CG</cbc:AllowanceChargeReasonCode>
<cbc:AllowanceChargeReason>Example document charge</cbc:AllowanceChargeReason>
<cbc:MultiplierFactorNumeric>10</cbc:MultiplierFactorNumeric>
<cbc:Amount currencyID="GBP">3.50</cbc:Amount>
<cbc:BaseAmount currencyID="GBP">35.00</cbc:BaseAmount>
<!-- tax category omitted from this fragment -->
</cac:AllowanceCharge>Only cbc:MultiplierFactorNumeric differs: 20 in the failing document, 10 in the corrected one. The failing document reports only PEPPOL-EN16931-R040, because the amount of 3.50 still agrees with the charge total and the rest of the totals. Had the amount been changed instead, the charge total would have stopped matching: with the amount at 3.53 and nothing else touched, the validator reports BR-CO-12 as well as this rule.
What the validator reported
- The failing invoice reports PEPPOL-EN16931-R040. The corrected document passes every layer with no findings.Download the failing XMLDownload the corrected XML
Recorded on phive 12.1.0 / phive-rules-peppol 4.5.6 / Saxon-HE 12.10, the engine behind the free validator, using synthetic data. A recorded result is regression evidence for these documents; it is not a certification.
Where it applies
- Applies to UBL
InvoiceandCreditNote, at document level and oncac:InvoiceLineorcac:CreditNoteLine. Confirmed on credit notes at both levels. - The allowance inside
cac:Priceis outside this rule. A percentage added there draws warningsUBL-CR-635andUBL-CR-671and no finding from this rule. - The pinned test reads a missing
cbc:Amountas 0, but the full pipeline never gets that far: acac:AllowanceChargewithoutcbc:Amountis refused by the XSD layer and the later layers are skipped. - The rule does not check that the base amount is the right base, only that the three numbers agree with each other.
Related rules
- PEPPOL-EN16931-R041 fails when a percentage is sent without a base amount
- PEPPOL-EN16931-R042 fails when a base amount is sent without a percentage
- BR-CO-12 checks the charge total once a document-level charge amount changes
- BR-CO-11 checks the allowance total once a document-level allowance amount changes
- Browse every rule in the reference
Scope and source
Written for Peppol BIS Billing 3.0.21 (May 2026), EN 16931 1.3.16, as applied to UBL 2.1 Invoice and CreditNote documents. Other profiles, syntaxes and releases can define this identifier differently. Guidance version 2026-09-20.1: source checked 2026-09-20, explanation last updated 2026-09-20.
The official definition of PEPPOL-EN16931-R040 carries the normative wording and test. This page is our explanation of it, not a copy.
Guidance does not change the engine verdict. Fixing this finding does not mean the document passes every layer, and validation does not certify legal or tax compliance or transmit a document over Peppol.
