BR-DE – XRechnung
BR-DE-18: Skonto line in the payment terms (BT-20) is malformed
ErrorXRechnung business rule (KoSIT)
Official message
[BR-DE-18] 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.Source: KoSIT XRechnung, version 3.0.2 (Schematron 2.6.0)
What the message means
The payment terms contain an early-payment discount that does not follow the fixed XRechnung pattern. A discount is not written as prose but in a prescribed form, so that the recipient can compute the deduction automatically. As soon as a line starts with #, it must name SKONTO, the days and the percentage with two decimals, end with # and be followed by a line break. Any deviation gets the invoice rejected.
Common causes
- The percentage lacks two decimals or uses a comma, for example PROZENT=2 or PROZENT=2,00.
- Lower-case letters, spaces inside the segments or a missing # at the end of the line.
- No line break after the last discount line, or further text on the same line.
How to fix it
Write each discount tier as its own line following #SKONTO#TAGE=n#PROZENT=n.nn# and end the last line with a line break. Other conditions may precede it as ordinary text.
<cac:PaymentTerms>
<cbc:Note>Payable within 30 days.
#SKONTO#TAGE=10#PROZENT=2#</cbc:Note>
</cac:PaymentTerms><cac:PaymentTerms>
<cbc:Note>Payable within 30 days.
#SKONTO#TAGE=10#PROZENT=2.00#
</cbc:Note>
</cac:PaymentTerms>Frequently asked
How do I state two discount tiers?
With two lines following the same pattern, for example #SKONTO#TAGE=7#PROZENT=3.00# and below it #SKONTO#TAGE=14#PROZENT=2.00#. Each line ends with # and a line break.
Do I have to structure the discount at all?
Only when you grant one. Without a discount, plain text in the payment terms is fine; as soon as a line starts with #, the fixed pattern applies.
Fields concerned
- BT-20
- BT-115
Related rules
Check your invoice
The XRechnung validator reports this rule with the line number and location – right in your browser, without upload.
Technical details
- UBL · Context (XPath)
/ubl:Invoice | /cn:CreditNote- UBL · Schematron test
every $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' )- CII · Context (XPath)
/rsm:CrossIndustryInvoice- CII · Schematron test
every $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' )
Explanation written on 13 September 2026