Skip to content

PEPPOL-EN16931-P0106: Pair the VATEX-EU-IC exemption code with category K

The exemption reason code VATEX-EU-IC is reserved for intra-community supplies, category K. A tax category with any other code that carries it is rejected.

Peppol BIS BillingFatal: the document is invalidVATCode lists

The short answer

PEPPOL-EN16931-P0106 fails for each cac:TaxCategory that carries the exemption reason code VATEX-EU-IC while its cbc:ID is not K. The finding points at that tax category. If the supply really is an intra-community supply, change the category to K; if it is not, replace the code with the one for the real exemption, or remove it.

In the recorded example the code sits in an exempt (E) breakdown. Moving to K changes the VAT treatment of the invoice, not just its coding, and brings the intra-community requirements with it.

What the rule checks

The rule selects every cac:TaxCategory whose cbc:TaxExemptionReasonCode, upper-cased, is VATEX-EU-IC, and passes only when its cbc:ID is K. Lower case is no escape: vatex-eu-ic on an exempt breakdown was reported when tried.

Every category other than K fails. On a Standard rated breakdown, the code was reported by this rule and by BR-S-10, which forbids exemption reasons there, when tried.

Document-level allowances and charges are included, because their category is a cac:TaxCategory too; a code there was reported by this rule, with the warning UBL-CR-480, when tried. Line categories are cac:ClassifiedTaxCategory and are not read: on a line the code produced only the warning UBL-CR-600.

Sibling Peppol rules tie the other category-specific codes to their categories in the same way: PEPPOL-EN16931-P0104 for VATEX-EU-G and G, PEPPOL-EN16931-P0105 for VATEX-EU-O and O, PEPPOL-EN16931-P0107 for VATEX-EU-AE and AE, and PEPPOL-EN16931-P0108 to PEPPOL-EN16931-P0111 for the margin scheme codes VATEX-EU-D, VATEX-EU-F, VATEX-EU-I and VATEX-EU-J, which belong with E.

The rule does not check that a K breakdown meets the intra-community conditions. EN 16931 rules such as BR-IC-02, BR-IC-11 and BR-IC-12 do that.

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

How an integration ends up here

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

  • One exemption code is configured for every zero-VAT sale to an EU customer, including sales that are exempt or outside the scope of VAT for other reasons.
  • The category comes from the item tax code while the exemption code comes from the customer record, so an EU customer buying an exempt item gets E with VATEX-EU-IC.
  • Intra-community supplies are mapped to E or Z because no VAT is charged, while the exemption code was set correctly.

How to fix it

  1. Establish the real VAT treatment from your tax determination. K is the category for an intra-community supply; if the supply is not one, the code is what has to change.
  2. If it is an intra-community supply, set cbc:ID to K on the breakdown and on every line, allowance and charge it covers, and keep VATEX-EU-IC. Then supply what category K needs: when tried, switching the recorded example to K brought BR-IC-02 (seller and buyer VAT identifiers), BR-IC-11 (delivery date or invoicing period) and BR-IC-12 (deliver-to country), all of which need real data.
  3. If it is exempt for another reason, keep E and replace the code with the VATEX code for that basis, or remove the code and give the reason as text. BR-E-10 needs one of the two.
  4. Derive the exemption code from the same decision that sets the category, so the two cannot disagree.

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 exempt breakdown carrying the intra-community code

<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-IC</cbc:TaxExemptionReasonCode>
    <cbc:TaxExemptionReason>Exempt from VAT</cbc:TaxExemptionReason>
    <cac:TaxScheme>
      <cbc:ID>VAT</cbc:ID>
    </cac:TaxScheme>
  </cac:TaxCategory>
</cac:TaxSubtotal>

Fragment of the corrected invoice: the breakdown stays exempt and the intra-community code is removed

<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:TaxExemptionReason>Exempt from VAT</cbc:TaxExemptionReason>
    <cac:TaxScheme>
      <cbc:ID>VAT</cbc:ID>
    </cac:TaxScheme>
  </cac:TaxCategory>
</cac:TaxSubtotal>

The failing invoice adds <cbc:TaxExemptionReasonCode>VATEX-EU-IC</cbc:TaxExemptionReasonCode> to its exempt breakdown; the corrected one keeps category E with the reason text alone. The failing document reports only this Peppol rule. Its EN 16931 layer passes, because VATEX-EU-IC is a valid VATEX code and the text satisfies BR-E-10. The correction shown is the not-intra-community branch: the supply stays exempt and the misleading code goes.

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-IC reported this rule when tried.
  • Reported by the Peppol layer only. EN 16931 checks that the code is on the VATEX list, through BR-CL-22, but not which category it is used with.
  • A correct K breakdown still needs an exemption reason code or text of its own, under BR-IC-10.

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-24.1: source checked 2026-09-24, explanation last updated 2026-09-24.

The official definition of PEPPOL-EN16931-P0106 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.