# PEPPOL-EN16931-R053: Put the whole VAT breakdown in a single tax total

The document must have exactly one `cac:TaxTotal` containing `cac:TaxSubtotal` elements. Put every VAT breakdown inside that one tax total.

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

## The short answer

`PEPPOL-EN16931-R053` fails when the number of root-level `cac:TaxTotal` elements that contain a `cac:TaxSubtotal` is anything other than one. Put every VAT breakdown, one `cac:TaxSubtotal` per category and rate, in a single `cac:TaxTotal` whose `cbc:TaxAmount` is the sum of their tax amounts.

Zero fails as well. A document with no VAT breakdown at all reports this rule beside the EN 16931 rules for the missing breakdown.

## What the rule checks

The rule runs once on the root and counts the `cac:TaxTotal` children that hold at least one `cac:TaxSubtotal`. It passes only when that count is exactly one.

A `cac:TaxTotal` without a breakdown is not counted. Peppol allows one of those, and only when `cbc:TaxCurrencyCode` is present, for the VAT total in the accounting currency; `PEPPOL-EN16931-R054` enforces that.

No amounts are compared. The recorded split keeps the figures right, 11.70 and 0.00 adding up to the old VAT total, and is still rejected on the count.

When tried, a document with no `cac:TaxTotal` reported this rule with `BR-CO-15`, `BR-CO-18` and `BR-S-01`. One whose only tax total had lost its breakdown reported it with `BR-CO-18`, `BR-S-01` and `PEPPOL-EN16931-R054`.

| Term | Meaning | UBL element |
|---|---|---|
| BG-23 | VAT breakdown | `cac:TaxTotal/cac:TaxSubtotal` |
| BT-110 | Invoice total VAT amount | `cac:TaxTotal/cbc:TaxAmount` |

## How an integration ends up here

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

- The mapping emits one `cac:TaxTotal` per VAT rate, mirroring a source table that holds one tax row per rate.
- A loop over tax categories opens and closes the tax total inside the loop instead of once around it.
- VAT in a second currency is sent as a full copy of the breakdown, which makes a second tax total with subtotals.

## How to fix it

1. Open one `cac:TaxTotal` directly under the root, after any document-level `cac:AllowanceCharge` and before `cac:LegalMonetaryTotal`.
2. Inside it, write one `cac:TaxSubtotal` for each combination of VAT category and rate used in the document.
3. Set its `cbc:TaxAmount` to the sum of the breakdown tax amounts, rounded to two decimals, in the document currency.
4. If VAT must also be stated in an accounting currency, add `cbc:TaxCurrencyCode` and a second `cac:TaxTotal` holding only a `cbc:TaxAmount` in that currency. It carries no breakdown, so it is not counted here.

## Before and after

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

Fragment of the failing invoice: the standard-rated and zero-rated breakdowns sit in two separate tax totals

```xml
<cac:TaxTotal>
  <cbc:TaxAmount currencyID="GBP">11.70</cbc:TaxAmount>
  <cac:TaxSubtotal>
    <cbc:TaxableAmount currencyID="GBP">58.50</cbc:TaxableAmount>
    <cbc:TaxAmount currencyID="GBP">11.70</cbc:TaxAmount>
    <cac:TaxCategory>
      <cbc:ID>S</cbc:ID>
      <cbc:Percent>20</cbc:Percent>
      <!-- tax scheme omitted from this fragment -->
    </cac:TaxCategory>
  </cac:TaxSubtotal>
</cac:TaxTotal>
<cac:TaxTotal>
  <cbc:TaxAmount currencyID="GBP">0.00</cbc:TaxAmount>
  <cac:TaxSubtotal>
    <cbc:TaxableAmount currencyID="GBP">10.00</cbc:TaxableAmount>
    <cbc:TaxAmount currencyID="GBP">0.00</cbc:TaxAmount>
    <cac:TaxCategory>
      <cbc:ID>Z</cbc:ID>
      <cbc:Percent>0</cbc:Percent>
      <!-- tax scheme omitted from this fragment -->
    </cac:TaxCategory>
  </cac:TaxSubtotal>
</cac:TaxTotal>
```

Fragment of the corrected invoice: one tax total of 11.70 holding both breakdowns

```xml
<cac:TaxTotal>
  <cbc:TaxAmount currencyID="GBP">11.70</cbc:TaxAmount>
  <cac:TaxSubtotal>
    <cbc:TaxableAmount currencyID="GBP">58.50</cbc:TaxableAmount>
    <cbc:TaxAmount currencyID="GBP">11.70</cbc:TaxAmount>
    <cac:TaxCategory>
      <cbc:ID>S</cbc:ID>
      <cbc:Percent>20</cbc:Percent>
      <!-- tax scheme omitted from this fragment -->
    </cac:TaxCategory>
  </cac:TaxSubtotal>
  <cac:TaxSubtotal>
    <cbc:TaxableAmount currencyID="GBP">10.00</cbc:TaxableAmount>
    <cbc:TaxAmount currencyID="GBP">0.00</cbc:TaxAmount>
    <cac:TaxCategory>
      <cbc:ID>Z</cbc:ID>
      <cbc:Percent>0</cbc:Percent>
      <!-- tax scheme omitted from this fragment -->
    </cac:TaxCategory>
  </cac:TaxSubtotal>
</cac:TaxTotal>
```

The failing invoice closes the tax total after the standard-rated breakdown and opens a second one, with its own VAT total of 0.00, for the zero-rated breakdown; the corrected invoice keeps both breakdowns in one tax total of 11.70. Each tax total still agrees with its own breakdown, so `BR-CO-14` passes. The failing document also reports `BR-CO-15` from the EN 16931 layer. That rule expects exactly one VAT total in the document currency to add to the total without VAT, finds two, 11.70 and 0.00, and fails on the count, even though 68.50 + 11.70 + 0.00 still equals the total with VAT of 80.20. Merging the tax totals clears both findings.

### What the validator reported

- The failing invoice reports [BR-CO-15](https://ironfang.uk/docs/finance/rules/BR-CO-15.md) and **PEPPOL-EN16931-R053**. The corrected document passes every layer with no findings.
  - [Download the failing XML](https://ironfang.uk/finance/rule-examples/PEPPOL-EN16931-R053-invalid.xml)
  - [Download the corrected XML](https://ironfang.uk/finance/rule-examples/invoice-rich.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` alike. When tried, a credit note split the same way reported the same two rules.
- It is a Peppol BIS rule, and the EN 16931 layer does not count tax totals as such. A split breakdown still fails both layers, because `BR-CO-15` reacts to the second VAT total in the document currency.
- A second tax total that repeats the breakdown in an accounting currency is counted too. When tried, a EUR copy of the standard-rated breakdown reported this rule, `PEPPOL-EN16931-R051` on each of its amounts and `PEPPOL-EN16931-R054`, among other findings. The accounting currency takes a single `cbc:TaxAmount` without a breakdown.

## Related rules

- [BR-CO-15 fails beside this rule because it needs a single VAT total in the document currency](https://ironfang.uk/docs/finance/rules/BR-CO-15.md)
- [PEPPOL-EN16931-R054 is the companion rule for the tax total without a breakdown](https://ironfang.uk/docs/finance/rules/PEPPOL-EN16931-R054.md)
- [BR-CO-14 checks that the VAT total equals the sum of its breakdown](https://ironfang.uk/docs/finance/rules/BR-CO-14.md)
- [BR-CO-18 requires at least one VAT breakdown, the case where this rule counts zero](https://ironfang.uk/docs/finance/rules/BR-CO-18.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-R053](https://docs.peppol.eu/poacc/billing/3.0/rules/ubl-peppol/PEPPOL-EN16931-R053/) 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-R053)
- [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
