Automation MCP Server Features Blog Pricing Contact
Validation rule EN 16931 core

BR-CO-14

The VAT side of the totals chain: BR-CO-14 requires the invoice total VAT amount (BT-110) to equal the sum of the VAT category tax amounts (BT-117) across the breakdown. Mixed rates and per-line VAT rounding are its favourite prey.

What BR-CO-14 checks

BR-CO-14 requires that Invoice total VAT amount (BT-110) = Σ VAT category tax amount (BT-117). An EN 16931 invoice carries a VAT breakdown, one group per category and rate, and each group states its own tax amount. The header's total VAT amount must equal the sum over those groups exactly. Together with BR-CO-17, which checks each group's amount against taxable amount × rate, it makes the invoice's VAT arithmetic self-consistent.

Layer and formats

The finding carries "layer": "en16931" and applies to every syntax and profile. In the totals chain it is the VAT-side sibling of BR-CO-10: BR-CO-10 anchors the net side to the lines, BR-CO-14 anchors the VAT side to the breakdown, and BR-CO-15 ties both into the total with VAT (BT-112). Inside each breakdown group, BR-CO-17 checks the multiplication that produces the amounts this rule sums.

Why it fails in practice

  • Per-line VAT rounding. VAT is rounded on every line and summed, while the breakdown (or the check) computes per category with one rounding step; on long invoices the two disagree by a cent.
  • A category missing from the breakdown. Lines with a second rate were added later, BT-110 was updated, but no breakdown group for the new rate was created.
  • Manual corrections. Someone adjusts the VAT total for a perceived rounding issue, and the breakdown no longer sums to it.

How to fix it

Compute VAT per category: group line net amounts by category and rate into BT-116, apply the rate once per group, round once per group, and set BT-110 to the sum of the group amounts. In an InvoiceXML create request the robust fix is omission: leave invoice.totals and invoice.vatBreakdowns out, and the API derives both from invoice.lines server-side. Supplied values are validated, so an inconsistency comes back as a finding instead of leaving the API inside a broken document.

The raw rejection vs the InvoiceXML finding

The Schematron report gives you the equation:

<svrl:failed-assert id="BR-CO-14" flag="fatal"
    location="/*:Invoice[namespace-uri()='urn:oasis:names:specification:ubl:schema:xsd:Invoice-2'][1]">
  <svrl:text>[BR-CO-14]-Invoice total VAT amount (BT-110) =
    Σ VAT category tax amount (BT-117).</svrl:text>
</svrl:failed-assert>

The InvoiceXML finding for the same failure:

{
  "rule": "BR-CO-14",
  "layer": "en16931",
  "line": null,
  "message": "The invoice total VAT amount does not match the sum of VAT breakdown amounts. Check that all VAT calculations are consistent.",
  "btCodes": ["BT-110", "BT-117"],
  "fields": ["totals.taxTotalAmount"],
  "raw": "[BR-CO-14] EN16931: Invoice total VAT amount (BT-110) = Σ VAT category tax amount (BT-117)."
}

Human-readable message, BT codes for standardese cross-reference, and a dotted path naming the request field to check. Clients that want their own texts localize by the stable rule key and keep the field mapping for free.

Check or generate documents with consistent VAT

Run received files through the UBL validator or the XRechnung validator. If your outbound documents trip the VAT chain, generation via POST /v1/create/ubl or POST /v1/create/facturx removes the whole class of failure: breakdown and totals are computed server-side from your lines. The category arithmetic is explained in EN 16931 explained.

  • BR-CO-10, the line sum (BT-106)
  • BR-CO-11, the allowance sum (BT-107)
  • BR-CO-13, the total without VAT (BT-109)
  • BR-CO-14, the VAT total against the breakdown (BT-110), this page
  • BR-CO-15, the total with VAT (BT-112), and BR-CO-16, the amount due (BT-115)
  • BR-CO-17, the multiplication inside each group, and BR-AE-10 / BR-E-10, the 0% category reasons

Frequently asked questions

Where is the VAT breakdown in the XML?

One group per VAT category and rate: cac:TaxSubtotal inside cac:TaxTotal in UBL, ram:ApplicableTradeTax in the CII settlement block. Each carries its taxable amount (BT-116), tax amount (BT-117), category code (BT-118) and rate (BT-119). BT-110 is the header's total VAT amount that must equal the sum of the BT-117 values.

I compute VAT per line and the total is off by a cent. Why?

EN 16931 VAT arithmetic works per category, not per line: sum the net amounts of a category into BT-116, apply the rate once, round once. Summing per-line rounded VAT amounts instead produces cent drift on invoices with many lines, which is exactly what BR-CO-14 (and BR-CO-17 inside each group) catch.

Does BR-CO-14 fire for XRechnung and Peppol documents?

Yes. It is an en16931 core layer rule and applies to every format and profile: UBL, CII, XRechnung, Peppol BIS, Factur-X and ZUGFeRD. National overlays add rules on top but never relax the core arithmetic.

Can documents created via the API fail this rule?

Not in practice. Omit the totals and the VAT breakdown in a /v1/create/* request and both are computed server-side from the line items, per category with a single rounding step, then validated before delivery. The rule bites on documents arriving from other systems.