Skip to content

Ironfang Finance - Rule reference

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.

Peppol BIS BillingFatal: the document is invalidVATCode lists

On this page

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.

TermMeaningUBL element
BT-121VAT exemption reason codecac:TaxTotal/cac:TaxSubtotal/cac:TaxCategory/cbc:TaxExemptionReasonCode
BT-118VAT category codecac:TaxTotal/cac:TaxSubtotal/cac:TaxCategory/cbc:ID
BT-151Invoiced item VAT category codecac: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.

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: an export coded exempt, E, in the breakdown and on the line

<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

<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

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.

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 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.