What BR-CO-11 checks
BR-CO-11 is the allowance-side bookkeeping rule: Sum of allowances on document level (BT-107) = Σ Document level allowance amount (BT-92). Every document level allowance is a BG-20 group with its own amount; the totals block declares their sum, and the validator recomputes it. In UBL, BT-107 is the cbc:AllowanceTotalAmount in the legal monetary total, and each BT-92 is the cbc:Amount of an cac:AllowanceCharge with ChargeIndicator false.
Layer and formats
An en16931 core layer rule, applying to every syntax and profile. It is the second link of the totals chain: BR-CO-10 anchors the line sum, BR-CO-11 and its charge twin BR-CO-12 anchor the document level adjustments, and BR-CO-13 combines all three into the total without VAT.
Why it fails in practice
- A discount added after totals were computed. The order pipeline appends a rebate group to the XML, but the monetary total block was rendered earlier and never updated.
- Sign confusion. Allowances are positive amounts subtracted downstream; emitting them negative (or mixing a charge into the allowance sum via a wrong ChargeIndicator) breaks the equation.
- Hardcoded template totals. BT-107 carries a leftover value from the template or a previous document while the allowance list changed.
How to fix it
Recompute BT-107 as the sum of the BT-92 amounts you actually emit, with allowances kept strictly positive:
<cac:LegalMonetaryTotal>
...
<cbc:AllowanceTotalAmount currencyID="EUR">50.00</cbc:AllowanceTotalAmount>
</cac:LegalMonetaryTotal>
In an InvoiceXML create request the allowances live in the invoice.allowances array and the sum is totals.sumOfAllowances. The robust fix is omission: leave invoice.totals out and the API computes BT-107 from the allowance entries server-side.
The raw rejection vs the InvoiceXML finding
The Schematron report states the equation:
<svrl:failed-assert id="BR-CO-11" flag="fatal"
location="/*:Invoice[namespace-uri()='urn:oasis:names:specification:ubl:schema:xsd:Invoice-2'][1]">
<svrl:text>[BR-CO-11]-Sum of allowances on document level (BT-107) =
Σ Document level allowance amount (BT-92).</svrl:text>
</svrl:failed-assert>
The InvoiceXML finding for the same failure:
{
"rule": "BR-CO-11",
"layer": "en16931",
"line": null,
"message": "The sum of allowances on document level must equal the sum of all document level allowance amounts. Check the allowance totals.",
"btCodes": ["BT-107", "BT-92"],
"fields": ["totals.sumOfAllowances"],
"raw": "[BR-CO-11] EN16931: Sum of allowances on document level (BT-107) = Σ Document level allowance amount (BT-92)."
}
A readable message plus the dotted path of the request field to fix, no rule-code parsing on your side. Clients that want their own wording localize by the stable rule key and keep the mapping.
Check or generate documents with correct totals
Validate a file in the UBL validator or the XRechnung validator. Generating via POST /v1/create/ubl or POST /v1/create/facturx computes the whole chain server-side from lines and allowances, so it cannot drift. Background on the arithmetic: EN 16931 explained.