What BR-CO-03 checks
BR-CO-03 enforces a mutual exclusion: Value added tax point date (BT-7) and Value added tax point date code (BT-8) must not both be present. The tax point, the moment VAT becomes chargeable, can be stated once, either explicitly as a date or symbolically as a code referencing another date of the invoice. Two declarations invite contradiction, so the core model rejects the combination outright, even when the two happen to agree.
Layer and formats
The finding carries "layer": "en16931" and applies to every syntax and profile. Unlike most core rules, this one is not about missing data but about over-declaration: the invoice says the same thing twice through two channels, and the standard picks consistency over redundancy.
Why it fails in practice
- Belt and braces mapping. The ERP knows the tax point date, so the export writes it into BT-7 and also emits the matching code into BT-8 for good measure.
- A template default plus real data. The template hardcodes code 3 (issue date) while the integration fills BT-7 whenever the source system supplies a date.
- Period fields confused with the tax point. Data meant for the invoicing period (BG-14) lands in the tax point fields, colliding with an existing code.
How to fix it
Pick one channel and drop the other. Coded, in UBL:
<cbc:InvoicePeriod>
<cbc:DescriptionCode>3</cbc:DescriptionCode>
</cbc:InvoicePeriod>
In an InvoiceXML create request the code is invoice.vatPointDateCode (3, 35 or 432 in the UBL code space; the CII emitter translates automatically). If you need an explicit date instead, supply that and leave the code empty.
The raw rejection vs the InvoiceXML finding
The Schematron report:
<svrl:failed-assert id="BR-CO-03" flag="fatal"
location="/*:Invoice[namespace-uri()='urn:oasis:names:specification:ubl:schema:xsd:Invoice-2'][1]">
<svrl:text>[BR-CO-03]-Value added tax point date (BT-7) and
Value added tax point date code (BT-8) are mutually
exclusive.</svrl:text>
</svrl:failed-assert>
The InvoiceXML finding for the same failure:
{
"rule": "BR-CO-03",
"layer": "en16931",
"line": null,
"message": "The VAT point date and the VAT point date code are mutually exclusive. Provide one or the other, not both.",
"btCodes": ["BT-7", "BT-8"],
"fields": ["vatPointDateCode"],
"raw": "[BR-CO-03] EN16931: Value added tax point date (BT-7) and Value added tax point date code (BT-8) are mutually exclusive."
}
The message states the resolution directly, and the BT codes anchor the finding for a standardese cross-check. Your integration never parses rule prose, and clients can localize by the stable rule key.
Check or generate compliant documents
Validate a document in the UBL validator or the XRechnung validator. Generating through POST /v1/create/ubl or POST /v1/create/facturx sidesteps the collision: the request model has one place for the tax point, and the syntax-specific encoding is handled server-side. The date semantics are part of EN 16931 explained.