# PEPPOL-EN16931-P0104: Use category G on the breakdown that carries the export code VATEX-EU-G

`VATEX-EU-G` states an export outside the EU, and Peppol accepts it only in a tax category with the ID `G`. The recorded export was coded exempt, `E`.

- 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-P0104/
- Explanation last updated: 2026-09-28

## The short answer

`PEPPOL-EN16931-P0104` fails for each `cac:TaxCategory` that carries `VATEX-EU-G` while its `cbc:ID` is not `G`. The code says the supply is an export outside the EU, and EN 16931 gives exports a category of their own, `G`, apart from exempt and zero rated supplies. If the goods leave the EU, set the category to `G`; if they do not, it is the export code that is wrong.

In the recorded example an invoice to a buyer in New York keeps the export code and the text `Export outside the EU` but puts its breakdown and its line in category `E`. The EN 16931 layer accepts that, because an exempt breakdown with a reason is complete; only the Peppol layer sees that the reason contradicts the category.

## What the rule checks

The rule picks out a `cac:TaxCategory` by its exemption code, upper-cased, and passes it only when the category, trimmed, is `G`. When tried, `vatex-eu-g` in the exempt breakdown was reported just as the upper-case code was.

The code itself is not trimmed. When tried, `VATEX-EU-G` with a space before it, or after it, in the same exempt breakdown passed every layer: `BR-CL-22` trims the value and accepts it, and this rule no longer recognises it. The padding hides the mismatch without correcting it.

Other wrong categories fail the same way, each with its own rules added. When tried, a Zero rated breakdown with `VATEX-EU-G` reported this rule and `BR-Z-10`, which allows no exemption reason there, and a Not subject to VAT breakdown carrying the code reported this rule alone.

Nothing in the check reads the buyer or the delivery address, so the rule cannot tell whether the goods really left the EU. It only holds the code and the category to each other.

| 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-151 | Invoiced item VAT category code | `cac:InvoiceLine/cac:Item/cac:ClassifiedTaxCategory/cbc:ID` |

## How an integration ends up here

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

- Sales outside the EU are booked as exempt because no VAT is charged, while the exemption code comes from a separate export flag.
- In UK VAT terms exports of goods are zero-rated, so they are mapped to `Z`, and the EN 16931 export category `G` is never used.
- One exemption code is set per customer, so a customer abroad gets `VATEX-EU-G` on every breakdown, including services taxed in another way.

## How to fix it

1. Check whether the supply is an export of goods leaving the EU, with the evidence your VAT rules require. That decision, not the absence of VAT, chooses the category.
2. If it is an export, set `cbc:ID` to `G` on the breakdown and on every line, allowance and charge it covers, with the rate `0`, and keep `VATEX-EU-G`. The corrected example needed no other change: its seller VAT identifier was already there for `BR-G-02`.
3. If it is not an export, keep the real category and replace `VATEX-EU-G` with the code for that treatment, or remove the code and give reason text, as `BR-E-10` allows on an exempt breakdown. On a Zero rated or Standard rated breakdown, remove the code and give no reason text either: `BR-Z-10` and `BR-S-10` allow neither.
4. Take the category and the exemption code from one tax determination, so a later change to one cannot leave the other behind.

## Before and after

These are fragments, not complete documents. The complete synthetic documents they come from are linked below.

Fragment of the failing invoice: an export coded exempt, E, in the breakdown and on the line

```xml
<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-G</cbc:TaxExemptionReasonCode>
    <cbc:TaxExemptionReason>Export outside the EU</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:ClassifiedTaxCategory>
  <cbc:ID>E</cbc:ID>
  <cbc:Percent>0</cbc:Percent>
  <cac:TaxScheme>
    <cbc:ID>VAT</cbc:ID>
  </cac:TaxScheme>
</cac:ClassifiedTaxCategory>
```

Fragment of the corrected invoice: the export is category G in both places

```xml
<cac:TaxSubtotal>
  <cbc:TaxableAmount currencyID="GBP">25.00</cbc:TaxableAmount>
  <cbc:TaxAmount currencyID="GBP">0.00</cbc:TaxAmount>
  <cac:TaxCategory>
    <cbc:ID>G</cbc:ID>
    <cbc:Percent>0</cbc:Percent>
    <cbc:TaxExemptionReasonCode>VATEX-EU-G</cbc:TaxExemptionReasonCode>
    <cbc:TaxExemptionReason>Export outside the EU</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:ClassifiedTaxCategory>
  <cbc:ID>G</cbc:ID>
  <cbc:Percent>0</cbc:Percent>
  <cac:TaxScheme>
    <cbc:ID>VAT</cbc:ID>
  </cac:TaxScheme>
</cac:ClassifiedTaxCategory>
```

The failing invoice has `E` where the corrected one has `G`, in the breakdown and in the line category; the code `VATEX-EU-G`, the reason text, the buyer in the United States and the amounts are the same in both. The failing document reports only this Peppol rule, since an exempt breakdown with a reason and a zero rate satisfies every EN 16931 rule.

### What the validator reported

- The failing invoice reports **PEPPOL-EN16931-P0104**. The corrected document passes every layer with no findings.
  - [Download the failing XML](https://ironfang.com/finance/rule-examples/PEPPOL-EN16931-P0104-invalid.xml)
  - [Download the corrected XML](https://ironfang.com/finance/rule-examples/export-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`. An exempt credit note carrying `VATEX-EU-G` reported this rule when tried.
- Document-level allowances and charges carry a `cac:TaxCategory` too, so a code there is checked in the same way. The line category is a `cac:ClassifiedTaxCategory`, which this rule does not read.
- A Peppol BIS Billing rule on the Peppol layer. On the EN 16931 layer, `BR-CL-22` confirms only that `VATEX-EU-G` is a listed code.

## Related rules

- [BR-G-10 requires an exemption reason on an export breakdown, which VATEX-EU-G provides](https://ironfang.com/docs/finance/rules/BR-G-10.md)
- [PEPPOL-EN16931-P0106 ties the intra-community code VATEX-EU-IC to category K in the same way](https://ironfang.com/docs/finance/rules/PEPPOL-EN16931-P0106.md)
- [PEPPOL-EN16931-P0110 catches the opposite mix-up, a works of art margin scheme code in an export breakdown](https://ironfang.com/docs/finance/rules/PEPPOL-EN16931-P0110.md)
- [BR-Z-10 reports VATEX-EU-G a second time when an export is coded Zero rated](https://ironfang.com/docs/finance/rules/BR-Z-10.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-P0104](https://docs.peppol.eu/poacc/billing/3.0/rules/ubl-peppol/PEPPOL-EN16931-P0104/) 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-P0104)
- [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
