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

- 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-P0106/
- Explanation last updated: 2026-09-24

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

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

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

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

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

```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: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

- The failing invoice reports **PEPPOL-EN16931-P0106**. The corrected document passes every layer with no findings.
  - [Download the failing XML](https://ironfang.uk/finance/rule-examples/PEPPOL-EN16931-P0106-invalid.xml)
  - [Download the corrected XML](https://ironfang.uk/finance/rule-examples/exempt-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-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`.

## Related rules

- [BR-IC-10 requires the exemption reason on an intra-community supply breakdown, where this code belongs](https://ironfang.uk/docs/finance/rules/BR-IC-10.md)
- [BR-CL-22 checks that an exemption reason code is on the VATEX list at all](https://ironfang.uk/docs/finance/rules/BR-CL-22.md)
- [BR-E-10 requires a reason on an exempt breakdown once the misplaced code is removed](https://ironfang.uk/docs/finance/rules/BR-E-10.md)
- [BR-IC-02 requires the seller and buyer VAT identifiers when the supply really is intra-community](https://ironfang.uk/docs/finance/rules/BR-IC-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-24.1: source checked 2026-09-24, explanation last updated 2026-09-24.

[The official definition of PEPPOL-EN16931-P0106](https://docs.peppol.eu/poacc/billing/3.0/rules/ubl-peppol/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.

## Links

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