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.
The totals chain
- 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