On this page
The short answer
PEPPOL-EN16931-P0109 fails for each cac:TaxCategory that carries VATEX-EU-F while its cbc:ID is not E. Under the margin scheme for second-hand goods the dealer accounts for VAT on its margin and shows none on the invoice; the VATEX list pairs the code with the exempt category, and Peppol enforces that pairing.
The recorded example sells a second-hand bookcase and codes the sale O, not subject to VAT, with the margin scheme code beside it. A margin scheme sale is within the scope of VAT, so O misstates it even though the invoice shows no VAT.
What the rule checks
Each cac:TaxCategory whose exemption code, upper-cased, is VATEX-EU-F must have E as its category after trimming. The recorded O breakdown is the only finding, because the failing invoice otherwise meets category O: its line has no rate and its seller no VAT identifier.
Changing the letter alone is not enough. When tried, relabelling the recorded breakdown and line from O to E cleared this rule and brought BR-48 (the breakdown needs a rate), BR-E-02 (the seller VAT identifier) and BR-E-05 (the line rate must be 0).
Zero rating the sale fails as well. When tried, the corrected example with its breakdown and line set to Z was reported by this rule and by BR-Z-10, which forbids any exemption reason on a Zero rated breakdown.
The pairing is all the rule tests. When tried, VATEX-EU-O in place of VATEX-EU-F made the failing document pass every layer, which is right only if the sale really is outside the scope of VAT.
| Term | Meaning | UBL element |
|---|---|---|
| BT-121 | VAT exemption reason code | cac:TaxTotal/cac:TaxSubtotal/cac:TaxCategory/cbc:TaxExemptionReasonCode |
| BT-118 | VAT category code | cac:TaxTotal/cac:TaxSubtotal/cac:TaxCategory/cbc:ID |
| BT-31 | Seller VAT identifier | cac:AccountingSupplierParty/cac:Party/cac:PartyTaxScheme/cbc:CompanyID |
How an integration ends up here
Possible causes, from the shape of the rule rather than from measured usage:
- Sales without VAT on the invoice are mapped to
Oby default, and the margin scheme flag only sets the exemption code. - A shop or till system that handles the margin scheme has no exempt category, so margin sales go out as outside the scope or zero rated.
- The margin scheme code is taken from the stock item, while the category is taken from the customer or from the VAT total of the invoice.
How to fix it
- Treat a margin scheme sale as exempt in the e-invoice: category
Eon the breakdown and on each line of second-hand goods, with the rate0in both places, and keepVATEX-EU-F. - Give the seller VAT identifier in
cac:PartyTaxScheme.BR-E-02requires a seller tax identifier on an invoice with an exempt line, and a dealer using the margin scheme is registered for VAT, so its VAT number is the one to give. - Show no VAT on the margin: the breakdown tax amount stays
0.00, and the exemption code tells the buyer why. - Where one invoice mixes margin scheme items with normally taxed items, give each category its own breakdown.
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 margin scheme sale coded not subject to VAT, O, with no rates
<cac:TaxSubtotal>
<cbc:TaxableAmount currencyID="GBP">25.00</cbc:TaxableAmount>
<cbc:TaxAmount currencyID="GBP">0.00</cbc:TaxAmount>
<cac:TaxCategory>
<cbc:ID>O</cbc:ID>
<cbc:TaxExemptionReasonCode>VATEX-EU-F</cbc:TaxExemptionReasonCode>
<cbc:TaxExemptionReason>Margin scheme - Second-hand goods</cbc:TaxExemptionReason>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:TaxCategory>
</cac:TaxSubtotal>
<!-- totals and the start of the invoice line omitted from this fragment -->
<cac:Item>
<cbc:Name>Second-hand bookcase</cbc:Name>
<cac:ClassifiedTaxCategory>
<cbc:ID>O</cbc:ID>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:ClassifiedTaxCategory>
</cac:Item>Fragment of the corrected invoice: the same sale in category E, with the rate 0
<cac:TaxSubtotal>
<cbc:TaxableAmount currencyID="GBP">25.00</cbc:TaxableAmount>
<cbc:TaxAmount currencyID="GBP">0.00</cbc:TaxAmount>
<cac:TaxCategory>
<cbc:ID>E</cbc:ID>
<cbc:Percent>0</cbc:Percent>
<cbc:TaxExemptionReasonCode>VATEX-EU-F</cbc:TaxExemptionReasonCode>
<cbc:TaxExemptionReason>Margin scheme - Second-hand goods</cbc:TaxExemptionReason>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:TaxCategory>
</cac:TaxSubtotal>
<!-- totals and the start of the invoice line omitted from this fragment -->
<cac:Item>
<cbc:Name>Second-hand bookcase</cbc:Name>
<cac:ClassifiedTaxCategory>
<cbc:ID>E</cbc:ID>
<cbc:Percent>0</cbc:Percent>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:ClassifiedTaxCategory>
</cac:Item>In the failing invoice the breakdown and the bookcase line are category O without a rate, and the seller has no VAT identifier. The corrected invoice has E with the rate 0 in both places and the seller VAT identifier GB123456789. VATEX-EU-F and its reason text are the same in both, and the failing document reports only this rule.
What the validator reported
- The failing invoice reports PEPPOL-EN16931-P0109. 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. When tried, a credit note withVATEX-EU-Fin a Zero rated breakdown reported this rule together withBR-Z-10. - Reported on the Peppol layer; on the EN 16931 layer
BR-CL-22only confirms thatVATEX-EU-Fis on the VATEX list. - In an exempt breakdown the code needs no reason text beside it: when tried, the corrected example without its text passed every layer. Sending both, as the example does, is allowed.
Related rules
- PEPPOL-EN16931-P0108 applies the same pairing to VATEX-EU-D for second-hand means of transport
- PEPPOL-EN16931-P0111 ties the antiques margin scheme code VATEX-EU-J to category E
- BR-E-02 requires a seller tax identifier, which the corrected invoice gives as its VAT identifier
- BR-Z-10 adds its own finding when a margin sale is coded Zero rated with this code
- Browse every rule in the reference
- Background: How Peppol invoice validation actually works
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 PEPPOL-EN16931-P0109 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.

