The German rules of XRechnung — what applies on top of EN 16931
EN 16931 applies across Europe and so leaves open what a recipient in Germany needs to process an invoice. XRechnung closes those gaps with rules of its own: BR-DE makes mandatory what the norm only permits and checks German formats such as IBAN and Skonto. BR-TMP holds the newest rules, most recently extended with the version of 2 September 2026.
37 rules · 37 explained · Rule set v2026-08-31
Mandatory where the norm only permits
Most BR-DE rules do not check a new particular but one that EN 16931 treats as optional: city and post code of seller and buyer (BR-DE-3, BR-DE-4, BR-DE-8, BR-DE-9), a contact point with telephone number and email address (BR-DE-2, BR-DE-5 to BR-DE-7), and the payment instructions (BR-DE-1). An invoice that would be valid anywhere in Europe therefore often fails in Germany on fields nobody ever filled in the mapping.
The best-known rule of the family is BR-DE-15: the buyer reference (BT-10) has to be present. On invoices to the public sector it carries the Leitweg-ID, by which the recipient routes the invoice — without it the invoice is not valid.
Payment data has to match the payment means
BR-DE-23, BR-DE-24 and BR-DE-25 check the payment data against the payment means chosen: a credit transfer needs bank details (BG-17), a card payment card data (BG-18), a direct debit mandate data (BG-19). The -a variants report what is missing, the -b variants what belongs to another payment means and is filled in anyway.
Then come the format checks: the IBAN for credit transfer and direct debit (BR-DE-19, BR-DE-20), for direct debit also the creditor identifier and the debited account (BR-DE-30, BR-DE-31), and the Skonto in the payment terms (BR-DE-18), for which XRechnung defines a text syntax of its own.
BR-TMP: what the version of 2 September added
The rule set v2026-08-31, published on 2 September 2026, added four BR-TMP rules: BR-TMP-6 and BR-TMP-7 check the format of dates — YYYY-MM-DD in UBL, eight digits with format="102" in CII — and under BR-TMP-4 and BR-TMP-5 a supporting document (BG-24) in CII may carry only one description and one embedded file. All four report a warning, not an error.
BR-TMP-2 was tightened in the same version: an external document address in BT-124 that is not a complete URL is now an error rather than a warning. Anyone shipping an internal path there will have the invoice rejected.
All German rules
With the official rule text, and the cause and fix for every rule.
BR-DE-1
Payment instructions (BG-16) missing
Eine Rechnung (INVOICE) muss Angaben zu "PAYMENT INSTRUCTIONS" (BG-16) enthalten.
- What the rule requires
- Every XRechnung invoice must carry the payment instructions group BG-16 — at minimum, by what means the invoice is meant to be paid.
- Why it fires
- Many systems print bank details only in the footer of the PDF. They are visible to a human but entirely absent from the structured data. The expression only checks that the group is there at all: an empty cac:PaymentMeans already satisfies BR-DE-1. What has to be inside it comes from other rules — the payment means code BT-81 is required by BR-49, not by BR-DE-1.
- How to fix it
- Populate BG-16 as structured data: payment means code (BT-81) and, depending on the method, the account details such as IBAN in BT-84. Free text in the footer does not count. Which account group belongs there is decided by the code in BT-81: for a credit transfer (30, 58) BR-DE-23-a requires group BG-17, for a card payment (48, 54, 55) BR-DE-24-a requires BG-18, and for a direct debit (59) BR-DE-25-a requires BG-19 — and in each case only that one.
- What the validator checks
UBLcac:PaymentMeansCIIrsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeSettlementPaymentMeans
In the XML
A UBL fragment. The CII path is named above — same change, different element names.
Fails <cac:PaymentTerms> <cbc:Note>Zahlbar innerhalb von 14 Tagen auf DE02120300000000202051</cbc:Note> </cac:PaymentTerms>Fixed <cac:PaymentMeans> <cbc:PaymentMeansCode>58</cbc:PaymentMeansCode> <cac:PayeeFinancialAccount> <cbc:ID>DE02120300000000202051</cbc:ID> </cac:PayeeFinancialAccount> </cac:PaymentMeans> <cac:PaymentTerms> <cbc:Note>Zahlbar innerhalb von 14 Tagen</cbc:Note> </cac:PaymentTerms>BR-DE-2
Seller contact (BG-6) missing
Die Gruppe "SELLER CONTACT" (BG-6) muss übermittelt werden.
- What the rule requires
- Every XRechnung invoice must carry the "SELLER CONTACT" group (BG-6) — a named contact at the seller, with a way to reach them. EN 16931 leaves this group optional; it becomes mandatory only through the German CIUS, including B2B.
- Why it fires
- Invoice templates usually carry contact details only in the letterhead. When mapping to the structured format the contact group is dropped entirely, because the internal data model has no mandatory field for it. The expression only checks that the group is there: an empty cac:Contact already satisfies BR-DE-2 — and immediately triggers BR-DE-5, BR-DE-6 and BR-DE-7, because the contact point, the telephone number and the email address are each required by a rule of their own.
- How to fix it
- Send BG-6 with contact point (BT-41), telephone (BT-42) and email (BT-43). In UBL that is cac:AccountingSupplierParty/cac:Party/cac:Contact, in CII ram:SellerTradeParty/ram:DefinedTradeContact. All three have to carry a value: the expressions test with normalize-space, so an empty element or a single space does not count.
- What the validator checks
UBLcac:Party/cac:ContactCIIram:DefinedTradeContact
In the XML
A UBL fragment. The CII path is named above — same change, different element names.
Fails <cac:AccountingSupplierParty> <cac:Party> <cac:PartyLegalEntity> <cbc:RegistrationName>Muster GmbH</cbc:RegistrationName> </cac:PartyLegalEntity> </cac:Party> </cac:AccountingSupplierParty>Fixed <cac:AccountingSupplierParty> <cac:Party> <cac:PartyLegalEntity> <cbc:RegistrationName>Muster GmbH</cbc:RegistrationName> </cac:PartyLegalEntity> <cac:Contact> <cbc:Name>Buchhaltung</cbc:Name> <cbc:Telephone>+49 30 1234567</cbc:Telephone> <cbc:ElectronicMail>rechnung@muster.de</cbc:ElectronicMail> </cac:Contact> </cac:Party> </cac:AccountingSupplierParty>BR-DE-3
Seller city (BT-37) missing
Das Element "Seller city" (BT-37) muss übermittelt werden.
- What the rule requires
- The seller's postal address (BG-5) must carry the city: BT-37, mandatory in XRechnung and not required by EN 16931 at all. It is the seller's address that is meant — the buyer's city is BR-DE-8, a differing delivery address BR-DE-10.
- Why it fires
- The address often exists internally as one combined address line. Without clean separation into street, post code and city, the structured city field stays empty. An empty element is no way out: the expression tests with normalize-space, so a <cbc:CityName/> with no content, or with a single space in it, counts as not transmitted.
- How to fix it
- Send the city in BT-37: cac:AccountingSupplierParty/cac:Party/cac:PostalAddress/cbc:CityName in UBL, ram:SellerTradeParty/ram:PostalTradeAddress/ram:CityName in CII. Split addresses into individual fields once, in the master data. The post code beside it is BR-DE-4, and the two usually fail together.
- What the validator checks
UBLcbc:CityName[boolean(normalize-space(.))]CIIram:CityName[boolean(normalize-space(.))]
In the XML
A UBL fragment. The CII path is named above — same change, different element names.
Fails <cac:AccountingSupplierParty> <cac:Party> <cac:PostalAddress> <cbc:StreetName>Musterstraße 1</cbc:StreetName> <cbc:PostalZone>10115</cbc:PostalZone> <cac:Country><cbc:IdentificationCode>DE</cbc:IdentificationCode></cac:Country> </cac:PostalAddress> </cac:Party> </cac:AccountingSupplierParty>Fixed <cac:AccountingSupplierParty> <cac:Party> <cac:PostalAddress> <cbc:StreetName>Musterstraße 1</cbc:StreetName> <cbc:CityName>Berlin</cbc:CityName> <cbc:PostalZone>10115</cbc:PostalZone> <cac:Country><cbc:IdentificationCode>DE</cbc:IdentificationCode></cac:Country> </cac:PostalAddress> </cac:Party> </cac:AccountingSupplierParty>BR-DE-4
Seller post code (BT-38) missing
Das Element "Seller post code" (BT-38) muss übermittelt werden.
- What the rule requires
- The seller's postal address must carry the post code (BT-38) — and the check is only that something is there, not that it looks like one. EN 16931 does not require BT-38 at all; the German CIUS is what makes it mandatory, with BR-DE-9 as the buyer's equivalent.
- Why it fires
- As with the city, the post code usually sits inside a combined address line and is never populated as its own field on export. A placeholder gets through technically: that existence check is the only expression in the whole rule set that touches BT-38 — neither XRechnung nor EN 16931 tests length, digits or country. "00000" passes validation and surfaces only at the recipient.
- How to fix it
- Send the post code in BT-38: cac:AccountingSupplierParty/cac:Party/cac:PostalAddress/cbc:PostalZone in UBL, ram:SellerTradeParty/ram:PostalTradeAddress/ram:PostcodeCode in CII. Note that CII calls the element PostcodeCode, not PostalCode — a regular slip when mapping by hand. The city beside it is BR-DE-3.
- What the validator checks
UBLcbc:PostalZone[boolean(normalize-space(.))]CIIram:PostcodeCode[boolean(normalize-space(.))]
In the XML
A UBL fragment. The CII path is named above — same change, different element names.
Fails <cac:AccountingSupplierParty> <cac:Party> <cac:PostalAddress> <cbc:StreetName>Musterstraße 1</cbc:StreetName> <cbc:CityName>Berlin</cbc:CityName> <cac:Country><cbc:IdentificationCode>DE</cbc:IdentificationCode></cac:Country> </cac:PostalAddress> </cac:Party> </cac:AccountingSupplierParty>Fixed <cac:AccountingSupplierParty> <cac:Party> <cac:PostalAddress> <cbc:StreetName>Musterstraße 1</cbc:StreetName> <cbc:CityName>Berlin</cbc:CityName> <cbc:PostalZone>10115</cbc:PostalZone> <cac:Country><cbc:IdentificationCode>DE</cbc:IdentificationCode></cac:Country> </cac:PostalAddress> </cac:Party> </cac:AccountingSupplierParty>BR-DE-5
Seller contact point (BT-41) missing
Das Element "Seller contact point" (BT-41) muss übermittelt werden.
- What the rule requires
- The seller contact point (BT-41) has to be filled — a named person or a department at the seller that the buyer can write to. EN 16931 carries BT-41 as an optional field and never tests it; the German CIUS is what makes it mandatory.
- Why it fires
- The field simply does not exist in many invoicing systems; only company name and address are captured. On export BT-41 stays empty even though BG-6 is present. An empty element is no help: the expression tests with normalize-space. In CII either of two elements satisfies it — a document carrying only ram:DepartmentName passes BR-DE-5, and converted to UBL that same text has to go into the single cbc:Name.
- How to fix it
- Send a person or department, such as "Accounting" or "Jane Doe": cac:AccountingSupplierParty/cac:Party/cac:Contact/cbc:Name in UBL, ram:SellerTradeParty/ram:DefinedTradeContact/ram:PersonName or ram:DepartmentName in CII. The telephone and email of the same group are BR-DE-6 and BR-DE-7, which report separately.
- What the validator checks
UBLcbc:Name[boolean(normalize-space(.))]CII(ram:PersonName,ram:DepartmentName)[boolean(normalize-space(.))]
In the XML
A UBL fragment. The CII path is named above — same change, different element names.
Fails <cac:AccountingSupplierParty> <cac:Party> <cac:Contact> <cbc:Telephone>+49 30 1234567</cbc:Telephone> <cbc:ElectronicMail>rechnung@muster.de</cbc:ElectronicMail> </cac:Contact> </cac:Party> </cac:AccountingSupplierParty>Fixed <cac:AccountingSupplierParty> <cac:Party> <cac:Contact> <cbc:Name>Buchhaltung</cbc:Name> <cbc:Telephone>+49 30 1234567</cbc:Telephone> <cbc:ElectronicMail>rechnung@muster.de</cbc:ElectronicMail> </cac:Contact> </cac:Party> </cac:AccountingSupplierParty>BR-DE-6
Contact telephone (BT-42) missing
Das Element "Seller contact telephone number" (BT-42) muss übermittelt werden.
- What the rule requires
- The seller contact needs a telephone number (BT-42), and it is an error that rejects the invoice rather than a warning. Whether what you put there is a number at all is BR-DE-27, which is only a warning.
- Why it fires
- The phone number appears in the PDF letterhead but is not attached to any contact in the data model — so it is missing when the structured document is generated. BR-DE-6 itself asks only for a non-empty value: "on request" satisfies it. BR-DE-27 is the rule that looks for at least three digits, and it reports as a warning rather than an error.
- How to fix it
- Send the number in BT-42: cac:AccountingSupplierParty/cac:Party/cac:Contact/cbc:Telephone in UBL, ram:SellerTradeParty/ram:DefinedTradeContact/ram:TelephoneUniversalCommunication/ram:CompleteNumber in CII. CII also has DirectTelephoneUniversalCommunication and MobileTelephoneUniversalCommunication — neither counts for BR-DE-6, and EN 16931 warns through CII-SR-234 if they appear at all.
- What the validator checks
UBLcbc:Telephone[boolean(normalize-space(.))]CIIram:TelephoneUniversalCommunication/ram:CompleteNumber[boolean(normalize-space(.))]
In the XML
A UBL fragment. The CII path is named above — same change, different element names.
Fails <cac:AccountingSupplierParty> <cac:Party> <cac:Contact> <cbc:Name>Buchhaltung</cbc:Name> <cbc:ElectronicMail>rechnung@muster.de</cbc:ElectronicMail> </cac:Contact> </cac:Party> </cac:AccountingSupplierParty>Fixed <cac:AccountingSupplierParty> <cac:Party> <cac:Contact> <cbc:Name>Buchhaltung</cbc:Name> <cbc:Telephone>+49 30 1234567</cbc:Telephone> <cbc:ElectronicMail>rechnung@muster.de</cbc:ElectronicMail> </cac:Contact> </cac:Party> </cac:AccountingSupplierParty>BR-DE-7
Contact email (BT-43) missing
Das Element "Seller contact email address" (BT-43) muss übermittelt werden.
- What the rule requires
- The seller contact needs an email address (BT-43), and that is an error which rejects the invoice rather than a warning. Whether the address looks like one at all is BR-DE-28, and only as a warning.
- Why it fires
- As with the phone number and the contact point, the address sits in the letterhead but not as a structured contact field in the data model. BR-DE-7 accepts any non-empty text — "see our website" satisfies it. The shape is BR-DE-28's job, and it checks less than its own rule text promises: that text asks for two characters either side of the @ and no dot beside it, while the compiled expression lets a single character through, and a dot immediately before the @ as well.
- How to fix it
- Send the address in BT-43: cac:AccountingSupplierParty/cac:Party/cac:Contact/cbc:ElectronicMail in UBL, ram:SellerTradeParty/ram:DefinedTradeContact/ram:EmailURIUniversalCommunication/ram:URIID in CII. In CII it belongs in ram:URIID — put it in ram:CompleteNumber, as the telephone group invites you to, and it does not count for BR-DE-7 while EN 16931 warns through CII-SR-238.
- What the validator checks
UBLcbc:ElectronicMail[boolean(normalize-space(.))]CIIram:EmailURIUniversalCommunication/ram:URIID[boolean(normalize-space(.))]
In the XML
A UBL fragment. The CII path is named above — same change, different element names.
Fails <cac:AccountingSupplierParty> <cac:Party> <cac:Contact> <cbc:Name>Buchhaltung</cbc:Name> <cbc:Telephone>+49 30 1234567</cbc:Telephone> </cac:Contact> </cac:Party> </cac:AccountingSupplierParty>Fixed <cac:AccountingSupplierParty> <cac:Party> <cac:Contact> <cbc:Name>Buchhaltung</cbc:Name> <cbc:Telephone>+49 30 1234567</cbc:Telephone> <cbc:ElectronicMail>rechnung@muster.de</cbc:ElectronicMail> </cac:Contact> </cac:Party> </cac:AccountingSupplierParty>BR-DE-8
Buyer city (BT-52) missing
Das Element "Buyer city" (BT-52) muss übermittelt werden.
- What the rule requires
- The buyer's postal address must carry the city (BT-52) — EN 16931 asks only for the country, and the city comes from the German CIUS. It is the buyer's invoicing address that is meant, not the seller's (BR-DE-3) and not a differing delivery address (BR-DE-10).
- Why it fires
- The source system usually holds the address as one collapsed line ("Musterstraße 1, 10115 Berlin") and the mapping never splits it into fields — so the city ends up nowhere. An empty element does not count either: the expression tests with normalize-space. And for a public-sector buyer the Leitweg-ID in BT-10 does not stand in for the address — it is a routing identifier, and group BG-8 still has to be complete.
- How to fix it
- Send the city as structured data in BT-52: cac:AccountingCustomerParty/cac:Party/cac:PostalAddress/cbc:CityName in UBL, ram:BuyerTradeParty/ram:PostalTradeAddress/ram:CityName in CII.
- What the validator checks
UBLcbc:CityName[boolean(normalize-space(.))]CIIram:CityName[boolean(normalize-space(.))]
In the XML
A UBL fragment. The CII path is named above — same change, different element names.
Fails <cac:AccountingCustomerParty> <cac:Party> <cac:PostalAddress> <cbc:PostalZone>53113</cbc:PostalZone> <cac:Country><cbc:IdentificationCode>DE</cbc:IdentificationCode></cac:Country> </cac:PostalAddress> </cac:Party> </cac:AccountingCustomerParty>Fixed <cac:AccountingCustomerParty> <cac:Party> <cac:PostalAddress> <cbc:CityName>Bonn</cbc:CityName> <cbc:PostalZone>53113</cbc:PostalZone> <cac:Country><cbc:IdentificationCode>DE</cbc:IdentificationCode></cac:Country> </cac:PostalAddress> </cac:Party> </cac:AccountingCustomerParty>BR-DE-9
Buyer post code (BT-53) missing
Das Element "Buyer post code" (BT-53) muss übermittelt werden.
- What the rule requires
- The buyer's postal address must carry a post code (BT-53) — BR-DE-8 asks for the city beside it, BR-DE-4 the same on the seller. There is no exception for countries that have no post codes: the expression never looks at the country code.
- Why it fires
- Same root as BR-DE-8: unsplit address lines. It also bites invoices to buyers in countries without a post-code system, where the field is simply left empty — and the rule makes no exception for that, neither through BT-55 nor otherwise. An empty element will not do either: the test runs through normalize-space.
- How to fix it
- Send the post code in BT-53: cac:AccountingCustomerParty/cac:Party/cac:PostalAddress/cbc:PostalZone in UBL, ram:BuyerTradeParty/ram:PostalTradeAddress/ram:PostcodeCode in CII. If the buyer's country has no post codes, put in whatever is used postally there: the check is only that something is present, not that it is a valid code.
- What the validator checks
UBLcbc:PostalZone[boolean(normalize-space(.))]CIIram:PostcodeCode[boolean(normalize-space(.))]
In the XML
A UBL fragment. The CII path is named above — same change, different element names.
Fails <cac:AccountingCustomerParty> <cac:Party> <cac:PostalAddress> <cbc:CityName>Bonn</cbc:CityName> <cac:Country><cbc:IdentificationCode>DE</cbc:IdentificationCode></cac:Country> </cac:PostalAddress> </cac:Party> </cac:AccountingCustomerParty>Fixed <cac:AccountingCustomerParty> <cac:Party> <cac:PostalAddress> <cbc:CityName>Bonn</cbc:CityName> <cbc:PostalZone>53113</cbc:PostalZone> <cac:Country><cbc:IdentificationCode>DE</cbc:IdentificationCode></cac:Country> </cac:PostalAddress> </cac:Party> </cac:AccountingCustomerParty>BR-DE-10
Delivery address with no city (BT-77)
Das Element "Deliver to city" (BT-77) muss übermittelt werden, wenn die Gruppe "DELIVER TO ADDRESS" (BG-15) übermittelt wird.
- What the rule requires
- Once a delivery address (BG-15) is in the document it must carry the city (BT-77), and otherwise the rule never fires. The group is "DELIVER TO ADDRESS", and a delivery date on its own is not one.
- Why it fires
- A half-filled delivery address: once the address group is in the document the source system fills only the fields it has — leaving, say, a country without a city. A delivery date on its own does not trigger the rule: in UBL BT-72 sits at cac:Delivery/cbc:ActualDeliveryDate, beside the address rather than inside it. Note too that the expression below does not show the condition — it lives in the rule's context, the path cac:Delivery/cac:DeliveryLocation/cac:Address, which the export drops. That is why BR-DE-10 reads there exactly like BR-DE-3 and BR-DE-8.
- How to fix it
- Either transmit the delivery address completely (city in BT-77: cac:Delivery/cac:DeliveryLocation/cac:Address/cbc:CityName in UBL, ram:ShipToTradeParty/ram:PostalTradeAddress/ram:CityName in CII) — or omit group BG-15 entirely if you do not mean to state one.
- What the validator checks
UBLcbc:CityName[boolean(normalize-space(.))]CIIram:CityName[boolean(normalize-space(.))]
In the XML
A UBL fragment. The CII path is named above — same change, different element names.
Fails <cac:Delivery> <cac:DeliveryLocation> <cac:Address> <cbc:PostalZone>53113</cbc:PostalZone> <cac:Country><cbc:IdentificationCode>DE</cbc:IdentificationCode></cac:Country> </cac:Address> </cac:DeliveryLocation> </cac:Delivery>Fixed <cac:Delivery> <cac:DeliveryLocation> <cac:Address> <cbc:CityName>Bonn</cbc:CityName> <cbc:PostalZone>53113</cbc:PostalZone> <cac:Country><cbc:IdentificationCode>DE</cbc:IdentificationCode></cac:Country> </cac:Address> </cac:DeliveryLocation> </cac:Delivery>BR-DE-11
Delivery address with no post code (BT-78)
Das Element "Deliver to post code" (BT-78) muss übermittelt werden, wenn die Gruppe "DELIVER TO ADDRESS" (BG-15) übermittelt wird.
- What the rule requires
- Once a delivery address (BG-15) is in the document it must carry the post code (BT-78) — the city beside it is BR-DE-10. EN 16931 asks only for the country in this group (BT-80, through BR-57); the city and the post code come from the German CIUS.
- Why it fires
- As with BR-DE-10, a partially filled group — the two findings almost always appear together, because the same mapping leaves out both fields. Opening BG-15 commits you to three fields: the country is already required by the norm through BR-57, and the city and post code are added by BR-DE-10 and BR-DE-11. An empty element does not count here either: the test runs through normalize-space.
- How to fix it
- Add the post code in BT-78: cac:Delivery/cac:DeliveryLocation/cac:Address/cbc:PostalZone in UBL, ram:ShipToTradeParty/ram:PostalTradeAddress/ram:PostcodeCode in CII. Or leave BG-15 out altogether when the delivery address is the invoicing address.
- What the validator checks
UBLcbc:PostalZone[boolean(normalize-space(.))]CIIram:PostcodeCode[boolean(normalize-space(.))]
In the XML
A UBL fragment. The CII path is named above — same change, different element names.
Fails <cac:Delivery> <cac:DeliveryLocation> <cac:Address> <cbc:CityName>Bonn</cbc:CityName> <cac:Country><cbc:IdentificationCode>DE</cbc:IdentificationCode></cac:Country> </cac:Address> </cac:DeliveryLocation> </cac:Delivery>Fixed <cac:Delivery> <cac:DeliveryLocation> <cac:Address> <cbc:CityName>Bonn</cbc:CityName> <cbc:PostalZone>53113</cbc:PostalZone> <cac:Country><cbc:IdentificationCode>DE</cbc:IdentificationCode></cac:Country> </cac:Address> </cac:DeliveryLocation> </cac:Delivery>BR-DE-14
VAT category rate (BT-119) missing
Das Element "VAT category rate" (BT-119) muss übermittelt werden.
- What the rule requires
- The VAT category rate (BT-119) must appear in every VAT breakdown (BG-23), including the exempt and reverse-charge ones where it is 0. EN 16931 allows exactly one exception through BR-48, category O for not subject to VAT; the German CIUS removes it.
- Why it fires
- For exempt or reverse-charge invoices (categories E, AE, Z) many systems omit the percentage because it "says nothing". XRechnung requires it anyway. The rule sits on the breakdown BG-23, so it reports once per category that has no rate. Against BR-48 there are two differences: the norm exempts category O, and the norm is satisfied by an element that merely exists — BR-DE-14 tests with normalize-space for an actual value, so an empty cbc:Percent will not do.
- How to fix it
- Always write BT-119, explicitly 0 for exempt categories: cac:TaxCategory/cbc:Percent in UBL, ram:ApplicableTradeTax/ram:RateApplicablePercent in CII.
- What the validator checks
UBLcac:TaxCategory/cbc:Percent[boolean(normalize-space(.))]CIIram:RateApplicablePercent[boolean(normalize-space(.))]
In the XML
A UBL fragment. The CII path is named above — same change, different element names.
Fails <cac:TaxCategory> <cbc:ID>E</cbc:ID> <cbc:TaxExemptionReason>Kleinunternehmer nach § 19 UStG</cbc:TaxExemptionReason> <cac:TaxScheme><cbc:ID>VAT</cbc:ID></cac:TaxScheme> </cac:TaxCategory>Fixed <cac:TaxCategory> <cbc:ID>E</cbc:ID> <cbc:Percent>0</cbc:Percent> <cbc:TaxExemptionReason>Kleinunternehmer nach § 19 UStG</cbc:TaxExemptionReason> <cac:TaxScheme><cbc:ID>VAT</cbc:ID></cac:TaxScheme> </cac:TaxCategory>BR-DE-15
Leitweg-ID (BT-10) or buyer reference
Das Element "Buyer reference" (BT-10) muss übermittelt werden.
- What the rule requires
- Every XRechnung needs a buyer reference in BT-10 — for invoices to a German public authority that is the Leitweg-ID. It routes the invoice to the right office. All that is checked, though, is that the field is not empty: the rule set never looks at its structure or its check digit.
- Why it fires
- It is usually missing because an existing B2B invoice template was reused: buyer reference is rarely needed there, but XRechnung makes it mandatory. The check does not help with the real risk — the only expression in the whole rule set that touches BT-10 is this existence test. "Test", or a Leitweg-ID that is out of date, passes validation and fails later at the receiving portal, which does not recognise the route.
- How to fix it
- Put the Leitweg-ID or buyer reference supplied by your customer into BT-10 — cbc:BuyerReference in UBL, ram:BuyerReference in CII. The field is mandatory for B2B invoices too: there it carries whatever reference the buyer asked for, an order number for instance.
- What the validator checks
UBLcbc:BuyerReference[boolean(normalize-space(.))]CIIrsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:BuyerReference[boolean(normalize-space(.))]- Further reading
In the XML
A UBL fragment. The CII path is named above — same change, different element names.
Fails <cbc:InvoiceTypeCode>380</cbc:InvoiceTypeCode> <cbc:DocumentCurrencyCode>EUR</cbc:DocumentCurrencyCode>Fixed <cbc:InvoiceTypeCode>380</cbc:InvoiceTypeCode> <cbc:DocumentCurrencyCode>EUR</cbc:DocumentCurrencyCode> <cbc:BuyerReference>04011000-12345-03</cbc:BuyerReference>BR-DE-16
Seller not identifiable for tax
Wenn in einer Rechnung die Steuercodes S, Z, E, AE, K, G, L oder M verwendet werden, muss mindestens eines der Elemente "Seller VAT identifier" (BT-31), "Seller tax registration identifier" (BT-32) oder "SELLER TAX REPRESENTATIVE PARTY" (BG-11) übermittelt werden.
- What the rule requires
- With tax category codes S, Z, E, AE, K, G, L or M the seller must be identifiable for tax: a VAT ID, a tax number or BG-11. Those are the VAT identifier (BT-31), the tax registration identifier (BT-32) and the tax representative (BG-11) — any one of the three will do.
- Why it fires
- Small businesses under § 19 UStG use category E and often have no VAT identifier. The tax number is frequently missing too, because the previous invoice layout never captured it. The UBL expression below shows variables rather than values: supportedVATCodes is the eight codes S, Z, E, AE, K, G, L and M, and BT-31orBT-32Path is cac:AccountingSupplierParty/cac:Party/cac:PartyTaxScheme/cbc:CompanyID with content in it. The two syntaxes also differ here: in UBL any identifier under PartyTaxScheme counts, while CII accepts only a registration whose schemeID is VA or FC.
- How to fix it
- Supply at least one of the three. Without a VAT identifier, BT-32 (tax registration number) is the usual choice — in UBL as cac:PartyTaxScheme/cbc:CompanyID with cac:TaxScheme/cbc:ID set to FC, in CII as ram:SpecifiedTaxRegistration/ram:ID with schemeID FC.
- What the validator checks
UBL(not( ($BT-95-UBL-Inv = $supportedVATCodes or $BT-95-UBL-CN = $supportedVATCodes) or ($BT-102 = $supportedVATCodes) or ($BT-151 = $supportedVATCodes) ) or (cac:TaxRepresentativeParty, $BT-31orBT-32Path))Variables in it
- $BT-95-UBL-Inv
- cac:AllowanceCharge/cac:TaxCategory/cbc:ID[ancestor::cac:AllowanceCharge/cbc:ChargeIndicator = 'false' and following-sibling::cac:TaxScheme/cbc:ID = 'VAT']
- $supportedVATCodes
- ('S', 'Z', 'E', 'AE', 'K', 'G', 'L', 'M')
- $BT-95-UBL-CN
- cac:AllowanceCharge/cac:TaxCategory/cbc:ID[ancestor::cac:AllowanceCharge/cbc:ChargeIndicator = 'false']
- $BT-102
- cac:AllowanceCharge/cac:TaxCategory/cbc:ID[ancestor::cac:AllowanceCharge/cbc:ChargeIndicator = 'true']
- $BT-151
- (cac:InvoiceLine | cac:CreditNoteLine)/cac:Item/cac:ClassifiedTaxCategory/cbc:ID
- $BT-31orBT-32Path
- cac:AccountingSupplierParty/cac:Party/cac:PartyTaxScheme/cbc:CompanyID[boolean(normalize-space(.))]
CIInot((rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem/ram:SpecifiedLineTradeSettlement/ram:ApplicableTradeTax/ram:TypeCode = 'VAT' and rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem/ram:SpecifiedLineTradeSettlement/ram:ApplicableTradeTax/ram:CategoryCode = ('S', 'Z', 'E', 'AE', 'K', 'G', 'L', 'M')) or (rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeAllowanceCharge/ram:CategoryTradeTax = 'VAT' and rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeAllowanceCharge/ram:CategoryTradeTax/ram:CategoryCode = ('S', 'Z', 'E', 'AE', 'K', 'G', 'L', 'M')) or (rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem/ram:SpecifiedLineTradeSettlement/ram:ApplicableTradeTax/ram:TypeCode = 'VAT' and rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem/ram:SpecifiedLineTradeSettlement/ram:ApplicableTradeTax/ram:CategoryCode = ('S', 'Z', 'E', 'AE', 'K', 'G', 'L', 'M'))) or ((rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTradeParty/ram:SpecifiedTaxRegistration/ram:ID[normalize-space(@schemeID)='VA' or normalize-space(@schemeID)='FC'][boolean(normalize-space(.))], rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTaxRepresentativeTradeParty))
In the XML
A UBL fragment. The CII path is named above — same change, different element names.
Fails <cac:Party> <cac:PartyLegalEntity> <cbc:RegistrationName>Muster GmbH</cbc:RegistrationName> </cac:PartyLegalEntity> </cac:Party>Fixed <cac:Party> <cac:PartyTaxScheme> <cbc:CompanyID>12/345/67890</cbc:CompanyID> <cac:TaxScheme><cbc:ID>FC</cbc:ID></cac:TaxScheme> </cac:PartyTaxScheme> <cac:PartyLegalEntity> <cbc:RegistrationName>Muster GmbH</cbc:RegistrationName> </cac:PartyLegalEntity> </cac:Party>BR-DE-17
Invoice type code (BT-3) not permitted
Mit dem Element "Invoice type code" (BT-3) sollen ausschließlich folgende Codes aus der Codeliste UNTDID 1001 übermittelt werden: 326 (Partial invoice), 380 (Commercial invoice), 384 (Corrected invoice), 389 (Self-billed invoice) und 381 (Credit note),875 (Partial construction invoice), 876 (Partial final construction invoice), 877 (Final construction invoice).Warning
- What the rule requires
- The invoice type code (BT-3) should be one of the permitted UNTDID 1001 codes: 326, 380, 384, 389, 381, 875, 876 or 877. BR-DE-17 reports as a warning rather than an error, so an invoice carrying another code is not rejected for it.
- Why it fires
- Most systems default to 380 (commercial invoice), which is correct. Deviations usually appear on credit notes or construction-industry partial invoices where a custom code was set. More often it is a code that EN 16931 permits through BR-CL-01 and XRechnung does not list — 383 for a debit note, say, or 386 for a prepayment invoice. The invoice is then compliant with the norm and still draws this warning. Both syntaxes check the same eight codes; in the UBL expression they are simply hidden behind the variable name supportedInvAndCNTypeCodes.
- How to fix it
- Map your internal document type onto one of the permitted codes — 380 for a normal invoice, 326 for a partial invoice, 381 for a credit note. Of the eight, 381 is the only one BR-CL-01 will not accept in cbc:InvoiceTypeCode in UBL: there it belongs in the cbc:CreditNoteTypeCode of a CreditNote document.
- What the validator checks
UBLnormalize-space(cbc:InvoiceTypeCode) = $supportedInvAndCNTypeCodes or normalize-space(cbc:CreditNoteTypeCode) = $supportedInvAndCNTypeCodesVariables in it
- $supportedInvAndCNTypeCodes
- ('326', '380', '384', '389', '381', '875', '876', '877')
CIInormalize-space(rsm:ExchangedDocument/ram:TypeCode) = ('326', '380', '384', '389', '381', '875', '876', '877')
In the XML
A UBL fragment. The CII path is named above — same change, different element names.
Fails <cbc:InvoiceTypeCode>RE</cbc:InvoiceTypeCode>Fixed <cbc:InvoiceTypeCode>380</cbc:InvoiceTypeCode>BR-DE-18
Wrong Skonto format in BT-20
Skonto Zeilen in […] müssen diesem regulärem Ausdruck entsprechen: […]. Die Informationen zur Gewährung von Skonto müssen wie folgt im Element "Payment terms" (BT-20) übermittelt werden: Anzugeben ist im ersten Segment "SKONTO", im zweiten "TAGE=n", im dritten "PROZENT=n". Prozentzahlen sind ohne Vorzeichen sowie mit Punkt getrennt von zwei Nachkommastellen anzugeben. Liegt dem zu berechnenden Betrag nicht BT-115, "fälliger Betrag" zugrunde, sondern nur ein Teil des fälligen Betrags der Rechnung, ist der Grundwert zur Berechnung von Skonto als viertes Segment "BASISBETRAG=n" gemäß dem semantischen Datentypen Amount anzugeben. Jeder Eintrag beginnt mit einer #, die Segmente sind mit einer # getrennt und eine Zeile schließt mit einer # ab. Am Ende einer vollständigen Skontoangabe muss ein XML-konformer Zeilenumbruch folgen. Alle Angaben zur Gewährung von Skonto müssen in Großbuchstaben gemacht werden. Zusätzliches Whitespace (Leerzeichen, Tabulatoren oder Zeilenumbrüche) ist nicht zulässig. Andere Zeichen oder Texte als in den oberen Vorgaben genannt sind nicht zulässig.
Wording in CII
Skonto Zeilen in […] muessen diesem regulärem Ausdruck entsprechen: […]. Die Informationen zur Gewährung von Skonto müssen wie folgt im Element "Payment terms" (BT-20) übermittelt werden: Anzugeben ist im ersten Segment "SKONTO", im zweiten "TAGE=n", im dritten "PROZENT=n". Prozentzahlen sind ohne Vorzeichen sowie mit Punkt getrennt von zwei Nachkommastellen anzugeben. Liegt dem zu berechnenden Betrag nicht BT-115, "fälliger Betrag" zugrunde, sondern nur ein Teil des fälligen Betrags der Rechnung, ist der Grundwert zur Berechnung von Skonto als viertes Segment "BASISBETRAG=n" gemäß dem semantischen Datentypen Amount anzugeben. Jeder Eintrag beginnt mit einer #, die Segmente sind mit einer # getrennt und eine Zeile schließt mit einer # ab. Am Ende einer vollständigen Skontoangabe muss ein XML-konformer Zeilenumbruch folgen. Alle Angaben zur Gewährung von Skonto müssen in Großbuchstaben gemacht werden. Zusätzliches Whitespace (Leerzeichen, Tabulatoren oder Zeilenumbrüche) ist nicht zulässig. Andere Zeichen oder Texte als in den oberen Vorgaben genannt sind nicht zulässig.
- What the rule requires
- Cash-discount (Skonto) information in the payment terms (BT-20) must follow a fixed machine-readable format: #SKONTO#TAGE=n#PROZENT=n.nn#, one entry per line, all in capitals, the percentage with a dot and exactly two decimals.
- Why it fires
- The rule only inspects lines beginning with #. Free text such as "2% discount if paid within 14 days" is ignored and passes — though it is also unusable to the recipient's software. The error comes from the half-correct attempt: PROZENT=2 instead of PROZENT=2.00, one space too many, or the missing trailing line break. The official text above leaves two gaps, because the rule set fills them in as it validates: the name of the element, and the expression itself. It is (^|\r?\n)#(SKONTO)#TAGE=([0-9]+#PROZENT=[0-9]+\.[0-9]{2})(#BASISBETRAG=-?[0-9]+\.[0-9]{2})?#$ and it says three things the prose does not: TAGE takes whole numbers only, PROZENT takes no sign, and BASISBETRAG explicitly allows a minus.
- How to fix it
- Write the entry exactly as #SKONTO#TAGE=14#PROZENT=2.00# and terminate it with a line break. Percentages always with a dot and exactly two decimals. If the discount applies to a partial amount only, append #BASISBETRAG=n.nn# as a fourth segment. No extra whitespace, no other text on the same line.
- What the validator checks
UBLevery $line in cac:PaymentTerms/cbc:Note[1]/tokenize(. , '(\r?\n)')[starts-with( normalize-space(.) , '#')] satisfies matches ( normalize-space ($line), $XR-SKONTO-REGEX) and matches( cac:PaymentTerms/cbc:Note[1]/tokenize(. , '#.+#')[last()], '^\s*\n' )Variables in it
- $XR-SKONTO-REGEX
- '(^|\r?\n)#(SKONTO)#TAGE=([0-9]+#PROZENT=[0-9]+\.[0-9]{2})(#BASISBETRAG=-?[0-9]+\.[0-9]{2})?#$'
CIIevery $line in rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradePaymentTerms/ram:Description[1]/tokenize(. , '(\r?\n)')[starts-with( normalize-space(.) , '#')] satisfies matches ( normalize-space ($line), $XR-SKONTO-REGEX ) and matches( rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradePaymentTerms/ram:Description[1]/tokenize(. , '#.+#')[last()], '^\s*\n' )Variables in it
- $XR-SKONTO-REGEX
- '(^|\r?\n)#(SKONTO)#TAGE=([0-9]+#PROZENT=[0-9]+\.[0-9]{2})(#BASISBETRAG=-?[0-9]+\.[0-9]{2})?#$'
In the XML
A UBL fragment. The CII path is named above — same change, different element names.
Fails <cac:PaymentTerms> <cbc:Note>2 % Skonto bei Zahlung innerhalb von 14 Tagen</cbc:Note> </cac:PaymentTerms>Fixed <cac:PaymentTerms> <cbc:Note>#SKONTO#TAGE=14#PROZENT=2.00# Zahlbar innerhalb von 30 Tagen netto</cbc:Note> </cac:PaymentTerms>BR-DE-19
Invalid IBAN for credit transfer (BT-84)
"Payment account identifier" (BT-84) soll eine korrekte IBAN enthalten, wenn in "Payment means type code" (BT-81) mit dem Code 58 SEPA als Zahlungsmittel gefordert wird.Warning
- What the rule requires
- If SEPA credit transfer is declared as the payment means (BT-81 with code 58), the payment account identifier (BT-84) should be a correct IBAN. It is checked only for code 58 and only as a warning: code 30, the generic credit transfer, goes through unchecked.
- Why it fires
- Usually a typo in the IBAN — or code 58 although the payment is not actually a SEPA transfer. Spaces are not the problem: xr:checkIBAN strips all whitespace first and then recomputes the ISO 7064 check digit, moving the first four characters to the end, mapping letters to 10 through 35, and requiring the result modulo 97 to be 1. "DE02 1203 0000 0000 2020 51" therefore passes exactly as the same IBAN without spaces does.
- How to fix it
- Send the IBAN with a valid check digit in BT-84 (cac:PayeeFinancialAccount/cbc:ID in UBL, ram:PayeePartyCreditorFinancialAccount/ram:IBANID in CII) — or pick the correct payment means code if it is not a SEPA transfer. The shape is also fixed: two letters, two digits, then at most thirty further characters.
- What the validator checks
UBLnot(normalize-space(cbc:PaymentMeansCode) = '58') or xr:checkIBAN(string(cac:PayeeFinancialAccount/cbc:ID))CIInot(normalize-space(ram:TypeCode) = '58') or xr:checkIBAN(string(ram:PayeePartyCreditorFinancialAccount/ram:IBANID))
In the XML
A UBL fragment. The CII path is named above — same change, different element names.
Fails <cac:PaymentMeans> <cbc:PaymentMeansCode>58</cbc:PaymentMeansCode> <cac:PayeeFinancialAccount> <cbc:ID>DE02120300000000202052</cbc:ID> </cac:PayeeFinancialAccount> </cac:PaymentMeans>Fixed <cac:PaymentMeans> <cbc:PaymentMeansCode>58</cbc:PaymentMeansCode> <cac:PayeeFinancialAccount> <cbc:ID>DE02120300000000202051</cbc:ID> </cac:PayeeFinancialAccount> </cac:PaymentMeans>BR-DE-20
Invalid IBAN for direct debit (BT-91)
"Debited account identifier" (BT-91) soll eine korrekte IBAN enthalten, wenn in "Payment means type code" (BT-81) mit dem Code 59 SEPA als Zahlungsmittel gefordert wird.Warning
- What the rule requires
- For SEPA direct debit (BT-81 with code 59), the debited account identifier (BT-91) should be a correct IBAN — the check digit, and only as a warning. The account is the buyer's, not yours: the number comes from the mandate the customer gave you.
- Why it fires
- Usually a typo in an IBAN transcribed from the mandate — and unlike your own account number, nobody in-house ever notices, because it is never used again. Spaces are not the problem: xr:checkIBAN strips all whitespace first and then recomputes the ISO 7064 check digit. Three errors hang off the same group around a direct debit: BR-DE-25-a requires BG-19 when the code is 59, BR-DE-31 requires the account BT-91 inside it, and BR-DE-30 requires the creditor identifier BT-90.
- How to fix it
- Send the debited account's IBAN with a valid check digit in BT-91: in UBL under cac:PaymentMandate/cac:PayerFinancialAccount/cbc:ID, in CII directly as ram:PayerPartyDebtorFinancialAccount/ram:IBANID. The mandate wrapper exists in UBL only — in CII the account sits without one.
- What the validator checks
UBLnot(normalize-space(cbc:PaymentMeansCode) = '59') or xr:checkIBAN(string(cac:PaymentMandate/cac:PayerFinancialAccount/cbc:ID))CIInot(normalize-space(ram:TypeCode) = '59') or xr:checkIBAN(string(ram:PayerPartyDebtorFinancialAccount/ram:IBANID))
In the XML
A UBL fragment. The CII path is named above — same change, different element names.
Fails <cac:PaymentMeans> <cbc:PaymentMeansCode>59</cbc:PaymentMeansCode> <cac:PaymentMandate> <cbc:ID>MANDAT-2026-0007</cbc:ID> <cac:PayerFinancialAccount> <cbc:ID>DE02120300000000202052</cbc:ID> </cac:PayerFinancialAccount> </cac:PaymentMandate> </cac:PaymentMeans>Fixed <cac:PaymentMeans> <cbc:PaymentMeansCode>59</cbc:PaymentMeansCode> <cac:PaymentMandate> <cbc:ID>MANDAT-2026-0007</cbc:ID> <cac:PayerFinancialAccount> <cbc:ID>DE02120300000000202051</cbc:ID> </cac:PayerFinancialAccount> </cac:PaymentMandate> </cac:PaymentMeans>BR-DE-21
Identifier is not XRechnung (BT-24)
Das Element "Specification identifier" (BT-24) soll syntaktisch der Kennung des Standards XRechnung entsprechen.Warning
- What the rule requires
- The specification identifier (BT-24) should be XRechnung's — exactly three values are accepted, and the rule only warns. It tells the recipient that the invoice was built to XRechnung, and in which variant.
- Why it fires
- Commonly only the EN 16931 identifier is present without the XRechnung part, or the version is outdated, or the URN carries a typo. In the expression below the three accepted values appear as variable names only; they are written out in the next section.
- How to fix it
- Send the identifier of the variant you actually produce — as cbc:CustomizationID in UBL, in ram:GuidelineSpecifiedDocumentContextParameter/ram:ID in CII. For the CIUS that is urn:cen.eu:en16931:2017#compliant#urn:xeinkauf.de:kosit:xrechnung_3.0; the Extension appends #conformant#urn:xeinkauf.de:kosit:extension:xrechnung_3.0 to it, and the CVD variant appends #compliant#urn:xeinkauf.de:kosit:xrechnung:cvd_0.9. Mind the version: the identifier carries 3.0, not the rule set's patch version.
- What the validator checks
UBLcbc:CustomizationID = $XR-CIUS-ID or cbc:CustomizationID = $XR-EXTENSION-ID or cbc:CustomizationID = $XR-CVD-IDVariables in it
- $XR-CIUS-ID
- concat('urn:cen.eu:en16931:2017#compliant#urn:xeinkauf.de:kosit:xrechnung_', $XR-MAJOR-MINOR-VERSION )
- $XR-EXTENSION-ID
- concat($XR-CIUS-ID, '#conformant#urn:xeinkauf.de:kosit:extension:xrechnung_' ,$XR-MAJOR-MINOR-VERSION )
- $XR-CVD-ID
- concat($XR-CIUS-ID, '#compliant#urn:xeinkauf.de:kosit:xrechnung:cvd_' , $CVD-MAJOR-MINOR-VERSION )
- $XR-MAJOR-MINOR-VERSION
- '3.0'
- $CVD-MAJOR-MINOR-VERSION
- '0.9'
CIIram:GuidelineSpecifiedDocumentContextParameter/ram:ID = $XR-CIUS-ID or ram:GuidelineSpecifiedDocumentContextParameter/ram:ID = $XR-EXTENSION-ID or ram:GuidelineSpecifiedDocumentContextParameter/ram:ID = $XR-CVD-IDVariables in it
- $XR-CIUS-ID
- concat('urn:cen.eu:en16931:2017#compliant#urn:xeinkauf.de:kosit:xrechnung_', $XR-MAJOR-MINOR-VERSION )
- $XR-EXTENSION-ID
- concat($XR-CIUS-ID, '#conformant#urn:xeinkauf.de:kosit:extension:xrechnung_' ,$XR-MAJOR-MINOR-VERSION )
- $XR-CVD-ID
- concat($XR-CIUS-ID, '#compliant#urn:xeinkauf.de:kosit:xrechnung:cvd_' , $CVD-MAJOR-MINOR-VERSION )
- $XR-MAJOR-MINOR-VERSION
- '3.0'
- $CVD-MAJOR-MINOR-VERSION
- '0.9'
In the XML
A UBL fragment. The CII path is named above — same change, different element names.
Fails <cbc:CustomizationID>urn:cen.eu:en16931:2017</cbc:CustomizationID>Fixed <cbc:CustomizationID>urn:cen.eu:en16931:2017#compliant#urn:xeinkauf.de:kosit:xrechnung_3.0</cbc:CustomizationID>BR-DE-22
Two attachments share a filename
Das "filename"-Attribut aller "EmbeddedDocumentBinaryObject"-Elemente muss eindeutig sein
Wording in CII
Not all filename attributes of the embeddedDocumentBinaryObject elements are unique
- What the rule requires
- All attachments embedded in an invoice must carry distinct filenames — the name in the filename attribute is all that tells them apart. The recipient files them under exactly that name.
- Why it fires
- The generator uses a constant name — every attachment is "anlage.pdf" or "attachment.pdf". With exactly one attachment this never shows; the second one triggers the error. The two syntaxes look different distances, too: in UBL the expression counts only the attachments at document level, while in CII it searches the whole document with // and so also picks up document references hanging off an invoice line. The same invoice can therefore fail in CII and pass in UBL.
- How to fix it
- Give each attachment a unique name in the filename attribute (cac:Attachment/cbc:EmbeddedDocumentBinaryObject/@filename in UBL, ram:AttachmentBinaryObject/@filename in CII) — simplest is the file's original name, with a running number if needed.
- What the validator checks
UBLcount(cac:AdditionalDocumentReference) = count(cac:AdditionalDocumentReference[not(./cac:Attachment/cbc:EmbeddedDocumentBinaryObject/@filename = preceding-sibling::cac:AdditionalDocumentReference/cac:Attachment/cbc:EmbeddedDocumentBinaryObject/@filename)])CIIcount(//ram:AdditionalReferencedDocument) = count(//ram:AdditionalReferencedDocument[not(./ram:AttachmentBinaryObject/@filename = preceding-sibling::ram:AdditionalReferencedDocument/ram:AttachmentBinaryObject/@filename)])
In the XML
A UBL fragment. The CII path is named above — same change, different element names.
Fails <cac:AdditionalDocumentReference> <cbc:ID>1</cbc:ID> <cac:Attachment> <cbc:EmbeddedDocumentBinaryObject mimeCode="application/pdf" filename="anhang.pdf">JVBERi0=</cbc:EmbeddedDocumentBinaryObject> </cac:Attachment> </cac:AdditionalDocumentReference> <cac:AdditionalDocumentReference> <cbc:ID>2</cbc:ID> <cac:Attachment> <cbc:EmbeddedDocumentBinaryObject mimeCode="application/pdf" filename="anhang.pdf">JVBERi0=</cbc:EmbeddedDocumentBinaryObject> </cac:Attachment> </cac:AdditionalDocumentReference>Fixed <cac:AdditionalDocumentReference> <cbc:ID>1</cbc:ID> <cac:Attachment> <cbc:EmbeddedDocumentBinaryObject mimeCode="application/pdf" filename="stundennachweis.pdf">JVBERi0=</cbc:EmbeddedDocumentBinaryObject> </cac:Attachment> </cac:AdditionalDocumentReference> <cac:AdditionalDocumentReference> <cbc:ID>2</cbc:ID> <cac:Attachment> <cbc:EmbeddedDocumentBinaryObject mimeCode="application/pdf" filename="lieferschein.pdf">JVBERi0=</cbc:EmbeddedDocumentBinaryObject> </cac:Attachment> </cac:AdditionalDocumentReference>BR-DE-23-a
Transfer with no bank details (BG-17)
Wenn BT-81 "Payment means type code" einen Schlüssel für Überweisungen enthält (30, 58), muss BG-17 "CREDIT TRANSFER" übermittelt werden.
- What the rule requires
- For a credit transfer (BT-81 with code 30 or 58) the document must carry group BG-17 with the payee's bank account. Asking for a transfer means saying where to — and the IBAN inside it is required by BR-50 and BR-61 from the norm, not by this rule.
- Why it fires
- The bank details live only in the PDF footer or in free-text payment terms, not as a structured group. Code 58 was set, BG-17 never mapped. The expression below shows none of this — it is just cac:PayeeFinancialAccount, the bare existence of the group. The condition sits in the rule's context, in the cac:PaymentMeans pattern with its predicate on codes 30 and 58, and the rule reports once per payment route: offer two and the same code can appear twice in the report.
- How to fix it
- Transmit BG-17 with at least the payee account's IBAN (BT-84): cac:PaymentMeans/cac:PayeeFinancialAccount/cbc:ID in UBL, ram:PayeePartyCreditorFinancialAccount/ram:IBANID in CII.
- What the validator checks
UBLcac:PayeeFinancialAccountCIIram:PayeePartyCreditorFinancialAccount
In the XML
A UBL fragment. The CII path is named above — same change, different element names.
Fails <cac:PaymentMeans> <cbc:PaymentMeansCode>58</cbc:PaymentMeansCode> </cac:PaymentMeans>Fixed <cac:PaymentMeans> <cbc:PaymentMeansCode>58</cbc:PaymentMeansCode> <cac:PayeeFinancialAccount> <cbc:ID>DE02120300000000202051</cbc:ID> </cac:PayeeFinancialAccount> </cac:PaymentMeans>BR-DE-23-b
Transfer with the wrong payment data
Wenn BT-81 "Payment means type code" einen Schlüssel für Überweisungen enthält (30, 58), dürfen BG-18 und BG-19 nicht übermittelt werden.
- What the rule requires
- For a credit transfer (BT-81 with code 30 or 58) no card data (BG-18) and no direct-debit data (BG-19) may sit beside it. BR-DE-23-a is its counterpart and requires the matching group, BG-17.
- Why it fires
- The system always writes every payment detail it has — say, the customer's stored direct-debit mandate, although this particular invoice is to be paid by transfer. The two syntaxes draw the line differently: in UBL the expression looks only at the children of the same cac:PaymentMeans, while in CII two of the three direct-debit checks start at the document root. An invoice offering two payment routes — a transfer alongside a direct debit with its mandate — therefore passes in UBL and fails in CII.
- How to fix it
- For each payment route transmit only the group that belongs to it: with 30 and 58, BG-17 alone. Drop card and mandate data — or fix the code if the invoice is in fact collected by direct debit. In CII that is not enough: as long as a transfer is present, no mandate or creditor reference may appear anywhere in the document.
- What the validator checks
UBLnot(cac:CardAccount) and not(cac:PaymentMandate)CIInot(ram:ApplicableTradeSettlementFinancialCard) and not(/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradePaymentTerms/ram:DirectDebitMandateID or /rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:CreditorReferenceID or ram:PayerPartyDebtorFinancialAccount/ram:IBANID)
In the XML
A UBL fragment. The CII path is named above — same change, different element names.
Fails <cac:PaymentMeans> <cbc:PaymentMeansCode>58</cbc:PaymentMeansCode> <cac:PayeeFinancialAccount> <cbc:ID>DE02120300000000202051</cbc:ID> </cac:PayeeFinancialAccount> <cac:PaymentMandate> <cbc:ID>MANDAT-2026-0007</cbc:ID> </cac:PaymentMandate> </cac:PaymentMeans>Fixed <cac:PaymentMeans> <cbc:PaymentMeansCode>58</cbc:PaymentMeansCode> <cac:PayeeFinancialAccount> <cbc:ID>DE02120300000000202051</cbc:ID> </cac:PayeeFinancialAccount> </cac:PaymentMeans>BR-DE-24-a
Card payment with no card data (BG-18)
Wenn BT-81 "Payment means type code" einen Schlüssel für Kartenzahlungen enthält (48, 54, 55), muss genau BG-18 "PAYMENT CARD INFORMATION" übermittelt werden.
- What the rule requires
- For a card payment (BT-81 with code 48, 54 or 55) the document must carry group BG-18 with the card details. What goes inside it is BR-51's business: the last digits of the card number, never the full PAN.
- Why it fires
- Card payment is rare in invoicing flows; when the code is set anyway (say, because payment was already taken by card), the matching group is almost always missing. The expression below gives none of that away: it is just cac:CardAccount, the bare existence of the group. The three codes live in the rule's context, in the pattern on cac:PaymentMeans, and each payment route is judged on its own.
- How to fix it
- Transmit BG-18 with the masked card number (BT-87, last digits only — never the full PAN): cac:PaymentMeans/cac:CardAccount in UBL, ram:ApplicableTradeSettlementFinancialCard in CII.
- What the validator checks
UBLcac:CardAccountCIIram:ApplicableTradeSettlementFinancialCard
In the XML
A UBL fragment. The CII path is named above — same change, different element names.
Fails <cac:PaymentMeans> <cbc:PaymentMeansCode>54</cbc:PaymentMeansCode> </cac:PaymentMeans>Fixed <cac:PaymentMeans> <cbc:PaymentMeansCode>54</cbc:PaymentMeansCode> <cac:CardAccount> <cbc:PrimaryAccountNumberID>******1234</cbc:PrimaryAccountNumberID> <cbc:NetworkID>NA</cbc:NetworkID> </cac:CardAccount> </cac:PaymentMeans>BR-DE-24-b
Card payment with the wrong data
Wenn BT-81 "Payment means type code" einen Schlüssel für Kartenzahlungen enthält (48, 54, 55), dürfen BG-17 und BG-19 nicht übermittelt werden.
- What the rule requires
- For a card payment (BT-81 with code 48, 54 or 55) neither credit-transfer data (BG-17) nor direct-debit data (BG-19) may sit beside it. BR-DE-24-a is its counterpart and requires the matching group, BG-18.
- Why it fires
- The seller's own payee IBAN is habitually written into every invoice, even when the chosen payment route is not a transfer at all — and that one default field is what fells a card payment. The codes 48, 54 and 55 are not in the expression but in the rule's context on cac:PaymentMeans, and each payment route is judged on its own. As on BR-DE-23-b, UBL looks only at the children of that one route, while in CII the two direct-debit checks start at the document root.
- How to fix it
- With card payment, transmit BG-18 only. Leave out the usual payee IBAN (BG-17) for this invoice — or change the payment means code to 58 if it is actually to be paid by transfer.
- What the validator checks
UBLnot(cac:PayeeFinancialAccount) and not(cac:PaymentMandate)CIInot(ram:PayeePartyCreditorFinancialAccount) and not(/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradePaymentTerms/ram:DirectDebitMandateID or /rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:CreditorReferenceID or ram:PayerPartyDebtorFinancialAccount/ram:IBANID)
In the XML
A UBL fragment. The CII path is named above — same change, different element names.
Fails <cac:PaymentMeans> <cbc:PaymentMeansCode>54</cbc:PaymentMeansCode> <cac:CardAccount> <cbc:PrimaryAccountNumberID>******1234</cbc:PrimaryAccountNumberID> <cbc:NetworkID>NA</cbc:NetworkID> </cac:CardAccount> <cac:PayeeFinancialAccount> <cbc:ID>DE02120300000000202051</cbc:ID> </cac:PayeeFinancialAccount> </cac:PaymentMeans>Fixed <cac:PaymentMeans> <cbc:PaymentMeansCode>54</cbc:PaymentMeansCode> <cac:CardAccount> <cbc:PrimaryAccountNumberID>******1234</cbc:PrimaryAccountNumberID> <cbc:NetworkID>NA</cbc:NetworkID> </cac:CardAccount> </cac:PaymentMeans>BR-DE-25-a
Direct debit, no mandate data (BG-19)
Wenn BT-81 "Payment means type code" einen Schlüssel für Lastschriften enthält (59), muss genau BG-19 "DIRECT DEBIT" übermittelt werden.
- What the rule requires
- If the payment means is SEPA direct debit (BT-81 with code 59), group BG-19 ("DIRECT DEBIT") must be transmitted — with the data the collection rests on: mandate reference, creditor identifier and the account to be debited.
- Why it fires
- Code 59 is set because payment is collected by direct debit — but the mandate reference and creditor ID live in the accounts-receivable master data and were never mapped into the invoice format. The bar then differs between the syntaxes: UBL wants the cac:PaymentMandate element itself, while CII accepts any one of three — the mandate reference, the creditor identifier, or the payer's IBAN. A CII document carrying only a creditor identifier and no mandate therefore satisfies BR-DE-25-a where the equivalent UBL document does not. Code 59 is not in the expression but in the rule's context, and each payment route is judged on its own.
- How to fix it
- Transmit BG-19: mandate reference (BT-89, cac:PaymentMandate/cbc:ID in UBL, ram:SpecifiedTradePaymentTerms/ram:DirectDebitMandateID in CII), creditor identifier (BT-90) and the debited account (BT-91). See also BR-DE-30 and BR-DE-31, which check the last two individually.
- What the validator checks
UBLcac:PaymentMandateCII/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradePaymentTerms/ram:DirectDebitMandateID or /rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:CreditorReferenceID or ram:PayerPartyDebtorFinancialAccount/ram:IBANID
In the XML
A UBL fragment. The CII path is named above — same change, different element names.
Fails <cac:PaymentMeans> <cbc:PaymentMeansCode>59</cbc:PaymentMeansCode> </cac:PaymentMeans>Fixed <cac:PaymentMeans> <cbc:PaymentMeansCode>59</cbc:PaymentMeansCode> <cac:PaymentMandate> <cbc:ID>MANDAT-2026-0007</cbc:ID> <cac:PayerFinancialAccount> <cbc:ID>DE02120300000000202051</cbc:ID> </cac:PayerFinancialAccount> </cac:PaymentMandate> </cac:PaymentMeans>BR-DE-25-b
Direct debit with the wrong data
Wenn BT-81 "Payment means type code" einen Schlüssel für Lastschriften enthält (59), dürfen BG-17 und BG-18 nicht übermittelt werden.
- What the rule requires
- If the payment means is SEPA direct debit (BT-81 with code 59), no credit-transfer data (BG-17) and no card data (BG-18) may be transmitted.
- Why it fires
- The most common of the three b-rules: the seller's own bank account sits in every invoice as BG-17 out of habit — with a direct debit it has no business there, since collection is from the buyer's account. CII's list of forbidden elements is longer than UBL's: besides the payee account and the card group it also names the payee's and the payer's financial institution, because CII carries those beside the account rather than inside it.
- How to fix it
- With direct debit, transmit BG-19 only and drop the payee bank account (BG-17) for this invoice. This rule looks at that one payment route alone: two routes side by side — a transfer and a direct debit as separate cac:PaymentMeans elements — are not forbidden by it. In CII such an invoice still fails, but on BR-DE-23-b.
- What the validator checks
UBLnot(cac:PayeeFinancialAccount) and not(cac:CardAccount)CIInot(ram:PayeePartyCreditorFinancialAccount) and not(ram:PayeeSpecifiedCreditorFinancialInstitution) and not(ram:PayerSpecifiedDebtorFinancialInstitution) and not(ram:ApplicableTradeSettlementFinancialCard)
In the XML
A UBL fragment. The CII path is named above — same change, different element names.
Fails <cac:PaymentMeans> <cbc:PaymentMeansCode>59</cbc:PaymentMeansCode> <cac:PayeeFinancialAccount> <cbc:ID>DE02120300000000202051</cbc:ID> </cac:PayeeFinancialAccount> <cac:PaymentMandate> <cbc:ID>MANDAT-2026-0007</cbc:ID> </cac:PaymentMandate> </cac:PaymentMeans>Fixed <cac:PaymentMeans> <cbc:PaymentMeansCode>59</cbc:PaymentMeansCode> <cac:PaymentMandate> <cbc:ID>MANDAT-2026-0007</cbc:ID> </cac:PaymentMandate> </cac:PaymentMeans>BR-DE-26
Correction with no reference (BG-3)
Wenn im Element "Invoice type code" (BT-3) der Code 384 (Corrected invoice) übergeben wird, soll PRECEDING INVOICE REFERENCE BG-3 mind. einmal vorhanden sein.Warning
Wording in CII
Wenn im Element Invoice type code (BT-3) der Code 384 (Corrected invoice) übergeben wird, soll PRECEDING INVOICE REFERENCE BG-3 mind. einmal vorhanden sein.
- What the rule requires
- A corrected invoice (BT-3 with code 384) should name the invoice it corrects, in group BG-3 "PRECEDING INVOICE REFERENCE". It is reported as a warning rather than an error — though without it the recipient cannot tell what is being corrected.
- Why it fires
- The correction is generated as a standalone document, and the original invoice number appears only in free text ("correction to invoice 2026-0815") instead of the structured field. Only code 384 triggers the rule: a credit note with 381, or a final construction invoice with 877, is not checked for it. And it asks for the group alone, not its content — an empty cac:InvoiceDocumentReference already satisfies it, and then fails BR-55, which requires the number BT-25 inside.
- How to fix it
- Transmit the corrected invoice's number in BG-3 (BT-25): cac:BillingReference/cac:InvoiceDocumentReference/cbc:ID in UBL, ram:InvoiceReferencedDocument/ram:IssuerAssignedID in CII.
- What the validator checks
UBL((not(normalize-space(cbc:InvoiceTypeCode) = '384' or normalize-space(cbc:CreditNoteTypeCode) = '384') or (cac:BillingReference/cac:InvoiceDocumentReference)))CIInot(normalize-space(rsm:ExchangedDocument/ram:TypeCode) = '384') or (rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:InvoiceReferencedDocument)
In the XML
A UBL fragment. The CII path is named above — same change, different element names.
Fails <cbc:InvoiceTypeCode>384</cbc:InvoiceTypeCode> <cbc:DocumentCurrencyCode>EUR</cbc:DocumentCurrencyCode>Fixed <cbc:InvoiceTypeCode>384</cbc:InvoiceTypeCode> <cbc:DocumentCurrencyCode>EUR</cbc:DocumentCurrencyCode> <cac:BillingReference> <cac:InvoiceDocumentReference> <cbc:ID>RE-2026-0041</cbc:ID> </cac:InvoiceDocumentReference> </cac:BillingReference>BR-DE-27
Telephone number too short (BT-42)
In BT-42 sollen mindestens drei Ziffern enthalten sein.Warning
- What the rule requires
- The seller contact telephone number (BT-42) should contain at least three digits — a plausibility check rather than a format rule, and reported as a warning.
- Why it fires
- The field holds a placeholder ("-", "0", "n/a") because BR-DE-6 demands some value and the source system has no phone number on file. The expression behind it is .*([0-9].*){3,}.* against the value after normalize-space: three digits anywhere in the text, in any order, with anything between them. "+49" and "0" fail it; "extension 123" passes, and so does "2026".
- How to fix it
- Enter a real, reachable number (cac:Contact/cbc:Telephone in UBL, ram:DefinedTradeContact/ram:TelephoneUniversalCommunication/ram:CompleteNumber in CII). The format is free — +49 30 1234567 is fine; it just must not consist of fewer than three digits.
- What the validator checks
UBLmatches(normalize-space(cbc:Telephone), $XR-TELEPHONE-REGEX)Variables in it
- $XR-TELEPHONE-REGEX
- '.*([0-9].*){3,}.*'
CIImatches(normalize-space(ram:TelephoneUniversalCommunication/ram:CompleteNumber), $XR-TELEPHONE-REGEX)Variables in it
- $XR-TELEPHONE-REGEX
- '.*([0-9].*){3,}.*'
In the XML
A UBL fragment. The CII path is named above — same change, different element names.
Fails <cac:Contact> <cbc:Name>Buchhaltung</cbc:Name> <cbc:Telephone>-</cbc:Telephone> </cac:Contact>Fixed <cac:Contact> <cbc:Name>Buchhaltung</cbc:Name> <cbc:Telephone>+49 30 1234567</cbc:Telephone> </cac:Contact>BR-DE-28
Email address not plausible (BT-43)
In BT-43 soll genau ein @-Zeichen enthalten sein, welches nicht von einem Leerzeichen, einem Punkt, aber mindestens zwei Zeichen auf beiden Seiten flankiert werden soll. Ein Punkt sollte nicht am Anfang oder am Ende stehen.Warning
- What the rule requires
- The seller contact email address (BT-43) should be plausibly formed: exactly one @, no whitespace, and a dot in the domain. The rule text asks for more than the expression tests, and it reports only a warning either way.
- Why it fires
- Placeholders like "-" or "none", two addresses in one field ("a@firma.de; b@firma.de"), or a truncated value ending in a dot. The rule text sounds stricter than the check is: it wants two characters either side of the @, no dot beside it and none at the start. The expression ^[^@\s]+@([^@.\s]+\.)+[^@.\s]+$ enforces only part of that — a@b.c with a single character on the left passes, and so do a.@b.c and .@b.c. What does fail reliably: a missing @, two @, whitespace in the value, a domain without a dot, and a trailing dot.
- How to fix it
- Enter exactly one valid address, e.g. invoices@company.com (cac:Contact/cbc:ElectronicMail in UBL, ram:EmailURIUniversalCommunication/ram:URIID in CII). Multiple recipients do not belong in the field — use a shared mailbox instead.
- What the validator checks
UBLmatches(normalize-space(cbc:ElectronicMail), $XR-EMAIL-REGEX)Variables in it
- $XR-EMAIL-REGEX
- '^[^@\s]+@([^@.\s]+\.)+[^@.\s]+$'
CIImatches(normalize-space(ram:EmailURIUniversalCommunication/ram:URIID), $XR-EMAIL-REGEX)Variables in it
- $XR-EMAIL-REGEX
- '^[^@\s]+@([^@.\s]+\.)+[^@.\s]+$'
In the XML
A UBL fragment. The CII path is named above — same change, different element names.
Fails <cac:Contact> <cbc:ElectronicMail>rechnung@muster.de, buchhaltung@muster.de</cbc:ElectronicMail> </cac:Contact>Fixed <cac:Contact> <cbc:ElectronicMail>rechnung@muster.de</cbc:ElectronicMail> </cac:Contact>BR-DE-30
Creditor identifier (BT-90) missing
Wenn "DIRECT DEBIT" BG-19 vorhanden ist, dann muss "Bank assigned creditor identifier" BT-90 übermittelt werden.
- What the rule requires
- If the invoice carries direct-debit data (BG-19), it must include the bank-assigned creditor identifier (BT-90) — the SEPA identifier under which you are allowed to collect.
- Why it fires
- The creditor ID is issued once per company and lives in accounting, not in the invoice data set — the mapping simply forgets it. The CII expression is four variables: BT-89 is ram:SpecifiedTradePaymentTerms/ram:DirectDebitMandateID, BT-90 is ram:CreditorReferenceID, BT-91 is the payer's IBAN, and BG-19-not-existing means none of the three is present. That produces a quirk: a CII document carrying only the creditor identifier, with no mandate reference and no payer IBAN, fails BR-DE-30 — even though the very field the rule asks for is the one that is there.
- How to fix it
- Transmit your creditor identifier (format DE98ZZZ09999999999) in BT-90. In UBL it normally belongs under the seller: cac:AccountingSupplierParty/cac:Party/cac:PartyIdentification/cbc:ID with schemeID="SEPA". Only where the payee is someone other than the seller does it go under cac:PayeeParty instead — the check accepts either location. Do not create cac:PayeeParty just for this: the group then needs a name as well (BR-17). In CII, ram:CreditorReferenceID.
- What the validator checks
UBLnot(cac:PaymentMeans/cac:PaymentMandate) or (cac:AccountingSupplierParty/cac:Party/cac:PartyIdentification/cbc:ID[@schemeID='SEPA'] | cac:PayeeParty/cac:PartyIdentification/cbc:ID[@schemeID='SEPA'])CII(($BT-89-path or $BT-91-path) and $BT-90-path) or $BG-19-not-existingVariables in it
- $BT-89-path
- rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradePaymentTerms/ram:DirectDebitMandateID
- $BT-91-path
- rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeSettlementPaymentMeans/ram:PayerPartyDebtorFinancialAccount/ram:IBANID
- $BT-90-path
- rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:CreditorReferenceID
- $BG-19-not-existing
- not(exists(($BT-89-path, $BT-90-path, $BT-91-path)))
In the XML
A UBL fragment. The CII path is named above — same change, different element names.
Fails <cac:AccountingSupplierParty> <cac:Party> <cac:PartyLegalEntity> <cbc:RegistrationName>Muster GmbH</cbc:RegistrationName> </cac:PartyLegalEntity> </cac:Party> </cac:AccountingSupplierParty>Fixed <cac:AccountingSupplierParty> <cac:Party> <cac:PartyIdentification> <cbc:ID schemeID="SEPA">DE98ZZZ09999999999</cbc:ID> </cac:PartyIdentification> <cac:PartyLegalEntity> <cbc:RegistrationName>Muster GmbH</cbc:RegistrationName> </cac:PartyLegalEntity> </cac:Party> </cac:AccountingSupplierParty>BR-DE-31
Debited account (BT-91) missing
Wenn "DIRECT DEBIT" BG-19 vorhanden ist, dann muss "Debited account identifier" BT-91 übermittelt werden.
- What the rule requires
- If the invoice carries direct-debit data (BG-19), it must include the debited account identifier (BT-91) — the buyer's IBAN the payment is collected from.
- Why it fires
- The customer's IBAN lives in the mandate at the payment provider or in the receivables master data, and is cautiously kept out of the invoice data set — but the rule requires it there. In CII it sits in a four-variable expression, the mirror image of BR-DE-30's: BT-91 is demanded as soon as any one of the three direct-debit fields appears. A document carrying only the payer's IBAN, with no mandate reference and no creditor identifier, fails BR-DE-31 all the same. Taken with BR-DE-30 that means, for CII: the creditor identifier and the payer's IBAN must both be present, while the mandate reference BT-89 stays optional.
- How to fix it
- Transmit the debited account's IBAN in BT-91: cac:PaymentMandate/cac:PayerFinancialAccount/cbc:ID in UBL, ram:PayerPartyDebtorFinancialAccount/ram:IBANID in CII. For IBAN correctness see BR-DE-20.
- What the validator checks
UBLnot(cac:PaymentMeans/cac:PaymentMandate) or (cac:PaymentMeans/cac:PaymentMandate/cac:PayerFinancialAccount/cbc:ID)CII(($BT-89-path or $BT-90-path) and $BT-91-path) or $BG-19-not-existingVariables in it
- $BT-89-path
- rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradePaymentTerms/ram:DirectDebitMandateID
- $BT-90-path
- rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:CreditorReferenceID
- $BT-91-path
- rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeSettlementPaymentMeans/ram:PayerPartyDebtorFinancialAccount/ram:IBANID
- $BG-19-not-existing
- not(exists(($BT-89-path, $BT-90-path, $BT-91-path)))
In the XML
A UBL fragment. The CII path is named above — same change, different element names.
Fails <cac:PaymentMandate> <cbc:ID>MANDAT-2026-0007</cbc:ID> </cac:PaymentMandate>Fixed <cac:PaymentMandate> <cbc:ID>MANDAT-2026-0007</cbc:ID> <cac:PayerFinancialAccount> <cbc:ID>DE02120300000000202051</cbc:ID> </cac:PayerFinancialAccount> </cac:PaymentMandate>BR-TMP-2
Attachment URL is not absolute (BT-124)
BT-124 "External document location" muss eine absolute URL mit gültigem Schema enthalten.
- What the rule requires
- Where the invoice points at an externally stored document (BT-124), the value must be an absolute address including its scheme. A file name, a drive path, or an address with no scheme in front of it all fail.
- Why it fires
- The value is usually copied straight out of an in-house document management system, where relative paths and network drives are normal. The recipient cannot resolve one: it points at a machine that does not exist on their side. The check is ^([a-zA-Z])([a-zA-Z0-9+.-])+:.* — purely whether a scheme name stands before a colon. Nothing tests that the address resolves, or that it is a web address at all: mailto:, ftp: and even file:///C:/attachment.pdf pass. So the internal path does slip through the moment somebody writes it as a file URL. Two differences between the syntaxes on top of that: CII only checks references carrying type code 916, and CII lets a missing address field pass where UBL counts it as an error.
- How to fix it
- Write an absolute URL including the scheme — cac:AdditionalDocumentReference/cac:Attachment/cac:ExternalReference/cbc:URI in UBL, ram:URIID in CII. If the document is not publicly reachable, attach it as an embedded object instead of shipping an internal path.
- What the validator checks
UBLmatches(cbc:URI, $XR-URL-REGEX)Variables in it
- $XR-URL-REGEX
- '^([a-zA-Z])([a-zA-Z0-9+.-])+:.*'
CIInot(exists(ram:URIID)) or (matches(ram:URIID, $XR-URL-REGEX))Variables in it
- $XR-URL-REGEX
- '^([a-zA-Z])([a-zA-Z0-9+.-])+:.*'
In the XML
A UBL fragment. The CII path is named above — same change, different element names.
Fails <cac:AdditionalDocumentReference> <cbc:ID>ANL-2026-0042</cbc:ID> <cac:Attachment> <cac:ExternalReference> <cbc:URI>www.beispiel.de/anlagen/stundennachweis.pdf</cbc:URI> </cac:ExternalReference> </cac:Attachment> </cac:AdditionalDocumentReference>Fixed <cac:AdditionalDocumentReference> <cbc:ID>ANL-2026-0042</cbc:ID> <cac:Attachment> <cac:ExternalReference> <cbc:URI>https://www.beispiel.de/anlagen/stundennachweis.pdf</cbc:URI> </cac:ExternalReference> </cac:Attachment> </cac:AdditionalDocumentReference>BR-TMP-3
Price base quantity (BT-149) inconsistent
Wenn BT-149 (Item price base quantity) sowohl in GrossPriceProductTradePrice als auch in NetPriceProductTradePrice vorhanden ist, müssen die Werte identisch sein. Wenn BT-150 (unit of measure code) auf dem NetPrice-Pfad vorhanden ist, muss es auch auf dem GrossPrice-Pfad vorhanden und identisch sein.
- What the rule requires
- Where the item price base quantity (BT-149) appears on both the gross and the net price of a line, the two values must be identical — and where the net price carries a unit of measure (BT-150), the gross price must carry the same one.
- Why it fires
- The gross price is often added later, to express a line-level discount. Its base quantity then gets filled from a different source or left out altogether, and the two price blocks immediately disagree. The rule exists in CII only, because only there do the gross and net prices each carry their own base quantity — UBL has no such pair to contradict itself. On the unit of measure the expression also parts company with the rule text: the text says a unit on the net price must appear on the gross price too, while the check only requires two units that are both present to match. Leave it off the gross price and the invoice passes.
- How to fix it
- Populate ram:BasisQuantity in GrossPriceProductTradePrice and NetPriceProductTradePrice from the same field, unitCode attribute included. If you do not need a differing base quantity, omit it from both blocks rather than from one.
- What the validator checks
CIInot(ram:SpecifiedLineTradeAgreement/ram:GrossPriceProductTradePrice/ram:BasisQuantity and ram:SpecifiedLineTradeAgreement/ram:NetPriceProductTradePrice/ram:BasisQuantity) or (ram:SpecifiedLineTradeAgreement/ram:GrossPriceProductTradePrice/ram:BasisQuantity = ram:SpecifiedLineTradeAgreement/ram:NetPriceProductTradePrice/ram:BasisQuantity and (not(ram:SpecifiedLineTradeAgreement/ram:NetPriceProductTradePrice/ram:BasisQuantity/@unitCode and ram:SpecifiedLineTradeAgreement/ram:GrossPriceProductTradePrice/ram:BasisQuantity/@unitCode) or ram:SpecifiedLineTradeAgreement/ram:GrossPriceProductTradePrice/ram:BasisQuantity/@unitCode = ram:SpecifiedLineTradeAgreement/ram:NetPriceProductTradePrice/ram:BasisQuantity/@unitCode))
In the XML
A CII fragment — the rule applies to that syntax only.
Fails <ram:GrossPriceProductTradePrice> <ram:ChargeAmount>100.00</ram:ChargeAmount> <ram:BasisQuantity unitCode="C62">1</ram:BasisQuantity> </ram:GrossPriceProductTradePrice> <ram:NetPriceProductTradePrice> <ram:ChargeAmount>90.00</ram:ChargeAmount> <ram:BasisQuantity unitCode="C62">10</ram:BasisQuantity> </ram:NetPriceProductTradePrice>Fixed <ram:GrossPriceProductTradePrice> <ram:ChargeAmount>100.00</ram:ChargeAmount> <ram:BasisQuantity unitCode="C62">10</ram:BasisQuantity> </ram:GrossPriceProductTradePrice> <ram:NetPriceProductTradePrice> <ram:ChargeAmount>90.00</ram:ChargeAmount> <ram:BasisQuantity unitCode="C62">10</ram:BasisQuantity> </ram:NetPriceProductTradePrice>BR-TMP-4
Attachment with two descriptions (BT-123)
BT-123 "Supporting document description" (ram:Name) darf innerhalb von "Additional supporting documents" (BG-24) höchstens einmal vorkommen.Warning
- What the rule requires
- Within one supporting document (BG-24) the document description (BT-123) may appear at most once — a warning, not an error. Several names for the same attachment are not allowed — a second document needs a second BG-24 group.
- Why it fires
- This happens when several attachments are written into one group instead of one group per attachment: the loop appends ram:Name repeatedly to the same node. The recipient can then no longer tell which name belongs to which file.
- How to fix it
- Emit one ram:AdditionalReferencedDocument group per attachment, each with exactly one ram:Name. BR-TMP-4 is the correctly scoped version of CII-SR-475: the CEN rule hangs off ram:ApplicableHeaderTradeAgreement and so counts the names of every 916 document together. Two attachments with one name each are fine by BR-TMP-4 and trip CII-SR-475 — though both report only a warning.
- What the validator checks
CIIcount(ram:Name) <= 1
In the XML
A CII fragment — the rule applies to that syntax only.
Fails <ram:AdditionalReferencedDocument> <ram:IssuerAssignedID>ANL-1</ram:IssuerAssignedID> <ram:TypeCode>916</ram:TypeCode> <ram:Name>Stundennachweis August</ram:Name> <ram:Name>Materialliste August</ram:Name> </ram:AdditionalReferencedDocument>Fixed <ram:AdditionalReferencedDocument> <ram:IssuerAssignedID>ANL-1</ram:IssuerAssignedID> <ram:TypeCode>916</ram:TypeCode> <ram:Name>Stundennachweis August</ram:Name> </ram:AdditionalReferencedDocument> <ram:AdditionalReferencedDocument> <ram:IssuerAssignedID>ANL-2</ram:IssuerAssignedID> <ram:TypeCode>916</ram:TypeCode> <ram:Name>Materialliste August</ram:Name> </ram:AdditionalReferencedDocument>BR-TMP-5
Attachment with two files (BT-125)
BT-125 "Attached document" (ram:AttachmentBinaryObject) darf innerhalb von "Additional Supporting documents" (BG-24) höchstens einmal vorkommen.Warning
- What the rule requires
- Within one supporting document (BG-24) there may be at most one embedded attachment (BT-125) — a warning, not an error. Two files in the same group are not allowed, even though the schema technically permits them.
- Why it fires
- Several attachments get written into a single group, as on BR-TMP-4. Since each group carries only one description and one document type, the recipient loses the link between file and description.
- How to fix it
- Emit one ram:AdditionalReferencedDocument group per file, each with exactly one ram:AttachmentBinaryObject including its mimeCode and filename. The filenames have to differ, which is BR-DE-22's job. BR-TMP-5 is the correctly scoped version of CII-SR-476: the CEN rule hangs off ram:ApplicableHeaderTradeAgreement and counts the files of every 916 document together, so two cleanly separated attachments set it off.
- What the validator checks
CIIcount(ram:AttachmentBinaryObject) <= 1
In the XML
A CII fragment — the rule applies to that syntax only.
Fails <ram:AdditionalReferencedDocument> <ram:IssuerAssignedID>ANL-1</ram:IssuerAssignedID> <ram:TypeCode>916</ram:TypeCode> <ram:Name>Nachweise August</ram:Name> <ram:AttachmentBinaryObject mimeCode="application/pdf" filename="stunden.pdf">JVBERi0xLjcK</ram:AttachmentBinaryObject> <ram:AttachmentBinaryObject mimeCode="application/pdf" filename="material.pdf">JVBERi0xLjcK</ram:AttachmentBinaryObject> </ram:AdditionalReferencedDocument>Fixed <ram:AdditionalReferencedDocument> <ram:IssuerAssignedID>ANL-1</ram:IssuerAssignedID> <ram:TypeCode>916</ram:TypeCode> <ram:Name>Stundennachweis August</ram:Name> <ram:AttachmentBinaryObject mimeCode="application/pdf" filename="stunden.pdf">JVBERi0xLjcK</ram:AttachmentBinaryObject> </ram:AdditionalReferencedDocument> <ram:AdditionalReferencedDocument> <ram:IssuerAssignedID>ANL-2</ram:IssuerAssignedID> <ram:TypeCode>916</ram:TypeCode> <ram:Name>Materialliste August</ram:Name> <ram:AttachmentBinaryObject mimeCode="application/pdf" filename="material.pdf">JVBERi0xLjcK</ram:AttachmentBinaryObject> </ram:AdditionalReferencedDocument>BR-TMP-6
Wrong date format in UBL
Datumsangaben in UBL müssen im Format JJJJ-MM-TT (YYYY-MM-DD) übermittelt werden.Warning
- What the rule requires
- Dates in a UBL XRechnung must be written as YYYY-MM-DD, for example 2026-08-26, and the check reports a warning rather than an error. It does not cover every date field, though, but seven named ones: IssueDate, DueDate, StartDate, EndDate, ActualDeliveryDate, TaxPointDate and PaymentDueDate — wherever they sit, including inside referenced documents.
- Why it fires
- The German display format 26.08.2026 ends up in the data because the date is taken from the invoice template as an already formatted string rather than as a date value. US ordering and appended times fall into the same trap.
- How to fix it
- Format date values explicitly as ISO 8601 (YYYY-MM-DD) when writing the XML, and never reuse the output of the presentation layer. A time of day does not belong in a date field — see BR-TMP-7 for the same rule in CII.
- What the validator checks
UBLmatches(normalize-space(text()), '^\d{4}-\d{2}-\d{2}$')
In the XML
A UBL fragment — the rule applies to that syntax only.
Fails <cbc:IssueDate>26.08.2026</cbc:IssueDate> <cbc:DueDate>2026-09-25T00:00:00</cbc:DueDate>Fixed <cbc:IssueDate>2026-08-26</cbc:IssueDate> <cbc:DueDate>2026-09-25</cbc:DueDate>BR-TMP-7
Wrong date format in CII
Datumsangaben in UNCEFACT/CII müssen das Attribut format="102" tragen und im Format JJJJMMTT (YYYYMMDD) übermittelt werden.Warning
- What the rule requires
- Dates in CII are written differently from UBL: as YYYYMMDD with no separators, for example 20260826, and the surrounding element must carry the attribute format="102", which announces exactly that pattern.
- Why it fires
- Almost always the attribute is missing or set to 610 or 616 while the value stays eight digits. Just as often the ISO format is carried over from the UBL output, where hyphens are correct — in CII they are not. Three elements are checked: udt:DateTimeString, qdt:DateTimeString and udt:DateString. And a wrong attribute rarely stops at this warning: BR-03 looks for the invoice date in CII as a udt:DateTimeString with format 102, so a missing or wrong attribute makes the date disappear as far as BR-03 is concerned — and that is an error, not a warning.
- How to fix it
- Write the date as a udt:DateTimeString with format="102" and eight digits. If you emit both syntaxes, keep date formatting in exactly one place per syntax; otherwise one spelling eventually leaks into the other output — see BR-TMP-6.
- What the validator checks
CIInormalize-space(@format) = '102' and matches(normalize-space(text()), '^\d{8}$')
In the XML
A CII fragment — the rule applies to that syntax only.
Fails <ram:IssueDateTime> <udt:DateTimeString format="610">2026-08-26</udt:DateTimeString> </ram:IssueDateTime>Fixed <ram:IssueDateTime> <udt:DateTimeString format="102">20260826</udt:DateTimeString> </ram:IssueDateTime>
NormAPI provides technical validation, not tax or legal advice.