On this page
The short answer
BR-O-03 fails when a root-level cac:AllowanceCharge with cbc:ChargeIndicator false has a cac:TaxCategory of O and the document also carries a VAT identifier: a cbc:CompanyID in a VAT cac:PartyTaxScheme of the seller, the buyer or the tax representative. In the recorded example it is the buyer identifier GB987654321 beside a Loyalty discount of 5.00. Take the VAT cac:PartyTaxScheme out of every party.
The finding normally arrives together with BR-O-02, because a document with an O allowance has O lines as well; the two rules test the same identifiers from different starting points, and removing the identifiers clears both.
What the rule checks
The trigger is limited to allowances directly under the document root whose cac:TaxCategory is O under the VAT scheme. Line-level allowances and charges are outside it, and so are the lines, which BR-O-02 covers.
Three places are searched, each only under a cac:PartyTaxScheme whose scheme is VAT: the seller, the buyer and cac:TaxRepresentativeParty. When tried on the corrected invoice, the seller identifier GB123456789 and a tax representative with GB987654321 each reported this rule together with BR-O-02.
Without an O line the rule stands on its own. When tried, the same 5.00 allowance in category O on a Standard rated invoice whose seller has GB123456789 reported this rule and BR-O-01, but not BR-O-02, since no line was in O.
A seller registration under the TAX scheme is not a VAT identifier for this rule: added to the corrected invoice as 1234567890, it left the allowance document valid when tried.
| Term | Meaning | UBL element |
|---|---|---|
| BT-95 | Document level allowance VAT category code | cac:AllowanceCharge[cbc:ChargeIndicator = false]/cac:TaxCategory/cbc:ID |
| BT-31 | Seller VAT identifier | cac:AccountingSupplierParty/cac:Party/cac:PartyTaxScheme/cbc:CompanyID |
| BT-48 | Buyer VAT identifier | cac:AccountingCustomerParty/cac:Party/cac:PartyTaxScheme/cbc:CompanyID |
| BT-63 | Seller tax representative VAT identifier | cac:TaxRepresentativeParty/cac:PartyTaxScheme/cbc:CompanyID |
How an integration ends up here
Possible causes, from the shape of the rule rather than from measured usage:
- The customer record supplies the buyer VAT number to every document, including one where the lines and the discount are all outside the scope of VAT.
- A discount is marked
Obecause it carries no tax of its own, on the invoice of a VAT-registered seller whose VAT numbers are written as usual. - The allowance takes
Ofrom the document while the party block is built separately from company and customer settings, and nothing compares the two.
How to fix it
- Check that the allowance really is outside the scope of VAT. A discount normally follows the VAT treatment of what it reduces, so if the lines are taxable the allowance should carry their category, not
O. - If the document is genuinely not subject to VAT, delete every
cac:PartyTaxSchemewhosecac:TaxScheme/cbc:IDisVATfrom the buyer, the seller andcac:TaxRepresentativeParty. In the recorded example that is the buyer block holdingGB987654321. - Keep both parties identified by other means, such as
cac:PartyLegalEntity/cbc:CompanyID, which they already have in the recorded example (12345678and87654321). - Make the mapping suppress VAT identifiers whenever any line, allowance or charge is
O, rather than testing the lines alone.
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: a buyer VAT identifier on a document whose loyalty discount is in category O
<cac:AccountingCustomerParty>
<cac:Party>
<cbc:EndpointID schemeID="0088">7300010000001</cbc:EndpointID>
<!-- postal address omitted from this fragment -->
<cac:PartyTaxScheme>
<cbc:CompanyID>GB987654321</cbc:CompanyID>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:PartyTaxScheme>
<cac:PartyLegalEntity>
<cbc:RegistrationName>Example Buyer Ltd</cbc:RegistrationName>
<cbc:CompanyID>87654321</cbc:CompanyID>
</cac:PartyLegalEntity>
</cac:Party>
</cac:AccountingCustomerParty>
<cac:AllowanceCharge>
<cbc:ChargeIndicator>false</cbc:ChargeIndicator>
<cbc:AllowanceChargeReasonCode>95</cbc:AllowanceChargeReasonCode>
<cbc:AllowanceChargeReason>Loyalty discount</cbc:AllowanceChargeReason>
<cbc:Amount currencyID="GBP">5.00</cbc:Amount>
<cac:TaxCategory>
<cbc:ID>O</cbc:ID>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:TaxCategory>
</cac:AllowanceCharge>Fragment of the corrected invoice: the buyer keeps only its legal registration identifier
<cac:AccountingCustomerParty>
<cac:Party>
<cbc:EndpointID schemeID="0088">7300010000001</cbc:EndpointID>
<!-- postal address omitted from this fragment -->
<cac:PartyLegalEntity>
<cbc:RegistrationName>Example Buyer Ltd</cbc:RegistrationName>
<cbc:CompanyID>87654321</cbc:CompanyID>
</cac:PartyLegalEntity>
</cac:Party>
</cac:AccountingCustomerParty>
<!-- the loyalty discount of 5.00 in category O, unchanged, omitted from this fragment -->The failing invoice adds a VAT cac:PartyTaxScheme with GB987654321 to the buyer; the corrected invoice has no VAT identifier for any party, and both keep the 5.00 allowance and the line in category O. The failing document reports BR-O-02 as well as BR-O-03, because its line is in O too and that rule forbids the same buyer identifier on account of the line.
What the validator reported
- The failing invoice reports BR-O-02 and BR-O-03. 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. Rewritten as a credit note, the failing invoice reported the same two findings when tried. - Charges have their own rule,
BR-O-04, and lines haveBR-O-02; the three share the list of forbidden identifiers and differ only in what sets them off. - The same allowance must not state a rate (
BR-O-06), and its amount is deducted in theOtaxable amount checked byBR-O-08.
Related rules
- BR-O-02 forbids the same identifiers when a line is not subject to VAT, and is reported with this rule in the example
- BR-O-04 applies the same ban when a document level charge is not subject to VAT
- BR-O-06 keeps a VAT rate off the same not subject to VAT allowance
- BR-CO-26 needs another seller identifier once a seller VAT identifier has been removed
- 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-03 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.

