# PEPPOL-EN16931-P0105: Keep the not subject to VAT code VATEX-EU-O for category O breakdowns

`VATEX-EU-O` says a supply is outside the scope of VAT and belongs only in tax category `O`. The recorded example put it in a reverse-charge breakdown, `AE`.

- Layer: Peppol BIS Billing
- Severity: fatal (the document is invalid)
- Topics: VAT, Code lists
- Official definition: https://docs.peppol.eu/poacc/billing/3.0/rules/ubl-peppol/PEPPOL-EN16931-P0105/
- Explanation last updated: 2026-09-28

## The short answer

`PEPPOL-EN16931-P0105` fails for each `cac:TaxCategory` that carries `VATEX-EU-O` while its `cbc:ID` is not `O`. The code states that the supply is not subject to VAT at all, which is what category `O` means; next to any other category it contradicts the treatment that category declares.

The recorded example is a reverse-charge invoice to a buyer with a German VAT identifier: category `AE`, reason text `Reverse charge`, and `VATEX-EU-O` as well. A cross-border service can look outside the scope from the seller side, but when the customer accounts for the VAT the treatment is the reverse charge, whose code is `VATEX-EU-AE`.

## What the rule checks

The rule matches a `cac:TaxCategory` on its exemption code after upper-casing, so mixed case is no way round it: `Vatex-EU-o` in the reverse-charge breakdown was reported when tried. The category must then be exactly `O` once trimmed.

It fails whatever the other category is. When tried, `VATEX-EU-O` in an export breakdown, category `G`, was reported by this rule alone, as it was in the recorded `AE` breakdown.

Replacing the code settles the recorded case: with `VATEX-EU-AE` in place of `VATEX-EU-O`, the reverse-charge invoice passed every layer when tried.

Moving the category is the heavier change. When tried, relabelling the breakdown and the line of the recorded example as `O` cleared this rule but brought `BR-O-02`, because a document with an `O` line may carry no VAT identifiers, and `BR-O-05`, because an `O` line may carry no rate.

| 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-120 | VAT exemption reason text | `cac:TaxTotal/cac:TaxSubtotal/cac:TaxCategory/cbc:TaxExemptionReason` |

## How an integration ends up here

Possible causes, from the shape of the rule rather than from measured usage:

- Cross-border business services are set up as outside the scope in the seller system, because the place of supply is abroad, while the invoice category follows the reverse-charge rules.
- A default exemption code of `VATEX-EU-O` is written into every breakdown with no VAT.
- The category is chosen from the customer type and the exemption code from the product, and the two settings were never lined up.

## How to fix it

1. Decide which treatment applies. `O` is for supplies outside the scope of VAT altogether; if the customer accounts for the VAT under the reverse charge, the treatment is `AE`.
2. For a reverse-charge supply, keep `AE` and give `VATEX-EU-AE`, reason text, or both, as `BR-AE-10` requires. The corrected example keeps the text `Reverse charge` and drops the code.
3. For a supply that really is not subject to VAT, change the breakdown and every line it covers to `O` and keep `VATEX-EU-O`. Remove the line VAT rates, which `BR-O-05` forbids, and the seller and buyer VAT identifiers, which `BR-O-02` forbids.

## 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 reverse-charge breakdown carrying the not subject to VAT code

```xml
<cac:TaxSubtotal>
  <cbc:TaxableAmount currencyID="GBP">25.00</cbc:TaxableAmount>
  <cbc:TaxAmount currencyID="GBP">0.00</cbc:TaxAmount>
  <cac:TaxCategory>
    <cbc:ID>AE</cbc:ID>
    <cbc:Percent>0</cbc:Percent>
    <cbc:TaxExemptionReasonCode>VATEX-EU-O</cbc:TaxExemptionReasonCode>
    <cbc:TaxExemptionReason>Reverse charge</cbc:TaxExemptionReason>
    <cac:TaxScheme>
      <cbc:ID>VAT</cbc:ID>
    </cac:TaxScheme>
  </cac:TaxCategory>
</cac:TaxSubtotal>
```

Fragment of the corrected invoice: the reverse-charge breakdown states its reason as text

```xml
<cac:TaxSubtotal>
  <cbc:TaxableAmount currencyID="GBP">25.00</cbc:TaxableAmount>
  <cbc:TaxAmount currencyID="GBP">0.00</cbc:TaxAmount>
  <cac:TaxCategory>
    <cbc:ID>AE</cbc:ID>
    <cbc:Percent>0</cbc:Percent>
    <cbc:TaxExemptionReason>Reverse charge</cbc:TaxExemptionReason>
    <cac:TaxScheme>
      <cbc:ID>VAT</cbc:ID>
    </cac:TaxScheme>
  </cac:TaxCategory>
</cac:TaxSubtotal>
```

The failing invoice adds `<cbc:TaxExemptionReasonCode>VATEX-EU-O</cbc:TaxExemptionReasonCode>` to its reverse-charge breakdown; the corrected one keeps category `AE` with the text `Reverse charge` alone. Only this Peppol rule is reported: the text satisfies `BR-AE-10`, and `VATEX-EU-O` is a listed code for `BR-CL-22`.

### What the validator reported

- The failing invoice reports **PEPPOL-EN16931-P0105**. The corrected document passes every layer with no findings.
  - [Download the failing XML](https://ironfang.com/finance/rule-examples/PEPPOL-EN16931-P0105-invalid.xml)
  - [Download the corrected XML](https://ironfang.com/finance/rule-examples/reverse-charge-valid.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 `Invoice` and `CreditNote`. When tried, an exempt credit note with `VATEX-EU-O` reported this rule.
- Reported on the Peppol layer only. The EN 16931 rule for category `O` breakdowns, `BR-O-10`, asks for some reason there but does not look at codes placed in other categories.
- The code is read in the VAT breakdown and in document-level allowances and charges. Line categories are `cac:ClassifiedTaxCategory` elements and lie outside the rule.

## Related rules

- [BR-O-10 requires a reason, such as VATEX-EU-O, on a breakdown that really is category O](https://ironfang.com/docs/finance/rules/BR-O-10.md)
- [BR-AE-10 requires the reverse-charge reason that the corrected breakdown gives as text](https://ironfang.com/docs/finance/rules/BR-AE-10.md)
- [PEPPOL-EN16931-P0107 ties the reverse-charge code VATEX-EU-AE to category AE](https://ironfang.com/docs/finance/rules/PEPPOL-EN16931-P0107.md)
- [BR-O-02 forbids VAT identifiers on a document with a not subject to VAT line](https://ironfang.com/docs/finance/rules/BR-O-02.md)

## 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-P0105](https://docs.peppol.eu/poacc/billing/3.0/rules/ubl-peppol/PEPPOL-EN16931-P0105/) 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.

## Links

- [This rule as a web page](https://ironfang.com/docs/finance/rules/PEPPOL-EN16931-P0105)
- [Free Peppol invoice validator](https://ironfang.com/tools/peppol-validator)
- [Rule index](https://ironfang.com/docs/finance/rules.md)
- [Ironfang Finance API docs](https://ironfang.com/docs/finance)
- The same rule is available to MCP clients as the tool `finance.rule.get` on https://mcp.ironfang.com/mcp
