On this page
The short answer
BR-O-07 fails when a charge, a cac:AllowanceCharge with cbc:ChargeIndicator true, has cbc:Percent in a cac:TaxCategory whose cbc:ID is O. The recorded Delivery charge of 4.00 says 20. Remove the element, so the category holds only cbc:ID and cac:TaxScheme.
A rate of 20 on an O charge also raises a question about the charge itself: either it is outside the scope of VAT and has no rate, or it is taxed at 20% and O is the wrong category for it.
What the rule checks
Each charge tax category with cbc:ID O under the VAT scheme is checked separately and reported at that cac:TaxCategory. A line-level charge qualifies as well: when tried, one in O with a rate of 20 inside the first line reported this rule there, together with the warning UBL-CR-558.
The value is never read. When tried, a rate of 0 on the delivery charge failed exactly as the recorded 20 does.
Recoding the charge to S at 20 instead of removing the rate trades one finding for several. When tried, that change reported BR-O-14, BR-S-01, BR-S-04 and, because the O taxable amount of 29.00 still counted the charge, BR-O-08.
Allowances and lines are left to their own rules: an O allowance with a rate is BR-O-06, an O line with one is BR-O-05.
| Term | Meaning | UBL element |
|---|---|---|
| BT-102 | Document level charge VAT category code | cac:AllowanceCharge[cbc:ChargeIndicator = true]/cac:TaxCategory/cbc:ID |
| BT-103 | Document level charge VAT rate | cac:AllowanceCharge[cbc:ChargeIndicator = true]/cac:TaxCategory/cbc:Percent |
How an integration ends up here
Possible causes, from the shape of the rule rather than from measured usage:
- Charges are created from a template that carries the Standard rate, and a document-level switch to
Ochanges the code but not the rate. - The serialiser always emits
cbc:Percentfor charges, using whatever rate the charge record holds. - A delivery charge priced with VAT in a web shop is exported to an out-of-scope invoice with only its category changed.
How to fix it
- Find out whether the delivery charge is really outside the scope of VAT. If it is taxed at 20%, it needs category
S; the invoice then mixes categories and has to be split, asBR-O-14explains. - If it is not subject to VAT, delete
cbc:Percentfrom the charge'scac:TaxCategory. - Leave the 4.00 charge amount, the
Otaxable amount of 29.00 and the totals as they are; the rate element plays no part in any of them. - Stop the charge template from forcing a rate onto charges whose category is
O.
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: the O delivery charge states a rate of 20
<cac:AllowanceCharge>
<cbc:ChargeIndicator>true</cbc:ChargeIndicator>
<cbc:AllowanceChargeReasonCode>FC</cbc:AllowanceChargeReasonCode>
<cbc:AllowanceChargeReason>Delivery</cbc:AllowanceChargeReason>
<cbc:Amount currencyID="GBP">4.00</cbc:Amount>
<cac:TaxCategory>
<cbc:ID>O</cbc:ID>
<cbc:Percent>20</cbc:Percent>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:TaxCategory>
</cac:AllowanceCharge>Fragment of the corrected invoice: the O delivery charge without a rate
<cac:AllowanceCharge>
<cbc:ChargeIndicator>true</cbc:ChargeIndicator>
<cbc:AllowanceChargeReasonCode>FC</cbc:AllowanceChargeReasonCode>
<cbc:AllowanceChargeReason>Delivery</cbc:AllowanceChargeReason>
<cbc:Amount currencyID="GBP">4.00</cbc:Amount>
<cac:TaxCategory>
<cbc:ID>O</cbc:ID>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:TaxCategory>
</cac:AllowanceCharge>The only difference is the cbc:Percent of 20 in the tax category of the failing invoice's Delivery charge, which the corrected invoice leaves out. The failing document reports only BR-O-07; the charge is still in O, and its 4.00 is still inside the O taxable amount of 29.00, so no other rule is disturbed.
What the validator reported
- The failing invoice reports BR-O-07. 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. The failing invoice turned into a credit note reported this rule alone when tried. - Lines and allowances in
Oare held to the same standard byBR-O-05andBR-O-06. The breakdown differs:BR-48excuses anObreakdown from having a rate, but does not forbid one. - While the charge is in
O, the document may carry no VAT identifiers either, underBR-O-04.
Related rules
- BR-O-06 is the same rule for a document level allowance in category O
- BR-O-14 applies if the charge is really taxed and is moved out of category O
- BR-O-04 forbids VAT identifiers on a document with a not subject to VAT charge
- BR-48 lets an O breakdown go without a rate, unlike the breakdown of any other category
- Browse every rule in the reference
- Background: Understanding EN 16931 validation errors
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-28.1: source checked 2026-09-28, explanation last updated 2026-09-28.
The official definition of BR-O-07 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.

