rechnungsapi.de
    Startseite
    Lösungen
    Steuerberater & KanzleienUnternehmen & MittelstandIT-Teams & SoftwareanbieterE-Invoicing-Berater & PartnerStartups & SaaSInternational & Peppol
    PreiseValidatorBlogKontaktAPI Docs
    🔑Anmelden🚀Loslegen
    Zurück zum Blog
    27. August 202612 min LesezeitZahlungsbedingungen

    Skonto in der E-Rechnung: richtig modellieren, sauber auslesen

    Skonto ist die einzige Preisangabe auf einer Rechnung, die zum Zeitpunkt der Rechnungsstellung noch nicht feststeht. Wie Sie es normkonform kodieren – und auf der Eingangsseite zuverlässig wieder herausholen.

    In der täglichen Praxis sehen wir regelmäßig, dass Skonto falsch modelliert ist – teils in selbst gebauten Exportern, teils in etablierten ERP-Systemen. Mal landet es in den falschen Feldern, mal stimmt die Syntax nicht, mal fehlt das abschließende Rautezeichen. Das nehmen wir zum Anlass, an dieser Stelle eine klare Beschreibung zu geben: was normkonform ist, wo die häufigsten Fehler liegen – und wie man auf der Eingangsseite auch mit fehlerhaften Sendersystemen zurechtkommt.

    Skonto gehört in BT-20 – nicht in BG-20

    Wer Skonto als Abschlag verrechnet, stellt eine Rechnung über einen Betrag aus, den er gar nicht fordert. Bei 2 % auf ein Jahresvolumen von 3 Mio. € sind das 60.000 €, die im schlimmsten Fall unwiederbringlich fehlen.

    Warum Skonto kein Abschlag ist

    EN 16931 kennt für Nachlässe die Gruppe BG-20 (Abschläge auf Dokumentebene) mit BT-92 als Betrag und BT-94 als Prozentsatz. Der naheliegende Reflex – Skonto dort eintragen – ist falsch: Ein Abschlag nach BG-20 mindert die Bemessungsgrundlage sofort. Er fließt in BT-109 (Summe Nettobeträge) und damit in BT-115 (fälliger Betrag) ein.

    Skonto tut das nicht. Der Rechnungsbetrag ist und bleibt der volle Betrag. Erst wenn der Kunde innerhalb der Frist zahlt, mindert sich das Entgelt. Umsatzsteuerlich ist das eine Änderung der Bemessungsgrundlage nach § 17 UStG, die beide Seiten erst im Zeitpunkt der tatsächlichen Inanspruchnahme berichtigen.

    § 14 Abs. 4 Nr. 7 UStG: Im Voraus vereinbarte Entgeltminderungen müssen in der Rechnung angegeben sein. Fehlt die Angabe, ist die Rechnung formal unvollständig – und der Vorsteuerabzug Ihres Kunden steht zur Diskussion. Für eine E-Rechnung gilt: Das Feld ist nicht optional, sobald Sie Skonto gewähren.

    Die Regel lautet deshalb: Der Rechnungsbetrag enthält kein Skonto. Die Skontokondition steht in den Zahlungsbedingungen – BT-20.

    Die Syntax: strukturierter Text in BT-20

    BT-20 ist im Kern ein Freitextfeld. Ein Freitext wie „2 % Skonto bei Zahlung innerhalb von 14 Tagen" ist für einen Menschen eindeutig und für eine Kreditorensoftware wertlos. Die KoSIT hat deshalb für XRechnung eine feste Zeichenkettensyntax definiert, die sich als De-facto-Standard auch für ZUGFeRD und Factur-X in Deutschland durchgesetzt hat:

    BT-20 Syntax
    #SKONTO#TAGE=14#PROZENT=2.00#

    Jedes Segment beginnt mit #, und die Kondition endet mit #. Das abschließende Rautezeichen ist Teil der Syntax.

    TAGE und PROZENT gehören zusammen. Eine Kondition mit nur einem der beiden Werte ist ungültig.

    Prozentwerte ohne Vorzeichen, mit Punkt als Dezimaltrennzeichen, zwei Nachkommastellen: 2.00, nicht 2,00, nicht -2.00.

    Jede Kondition steht in einer eigenen Zeile, getrennt durch einen XML-konformen Zeilenumbruch.

    Freitext ist zusätzlich erlaubt, darf aber kein # enthalten.

    Mehrere Konditionen und Verzugszinsen in einem Feld:

    Mehrere Konditionen + Verzug
    #SKONTO#TAGE=10#PROZENT=3.00#
    #SKONTO#TAGE=20#PROZENT=1.50#
    #VERZUG#TAGE=30#PROZENT=9.62#

    BR-DE-18 (KoSIT-Geschäftsregel): Für XRechnung prüft diese Regel die Einhaltung der Syntax. Eine Rechnung mit „3 % Skonto" als reinem Freitext läuft in diese Regel und besteht die Validierung nicht.

    Der optionale vierte Parameter: BASISBETRAG

    Liegt der Skontoberechnung nicht der gesamte fällige Betrag zugrunde – etwa weil Fracht, durchlaufende Posten oder beigestelltes Material nicht skontierfähig sind – nennen Sie die Bemessungsgrundlage explizit:

    #SKONTO#TAGE=14#PROZENT=2.00#BASISBETRAG=10710.00#

    Ohne diesen Parameter gilt BT-115 (fälliger Gesamtbetrag) als Basis. Der häufigste Streitfall – „Skonto vom Netto oder vom Brutto?" – ist damit an der Quelle entschieden. Wenn Sie das anders wollen, schreiben Sie es hin.

    Rechenbeispiel für eine Rechnung über 10.000,00 € netto:

    Nettobetrag (BT-109)10.000,00 €
    19 % MwSt.1.900,00 €
    Fälliger Betrag (BT-115)11.900,00 €
    Skonto 2 % auf den Bruttobetrag238,00 €
    Zahlbetrag bei fristgerechter Zahlung11.662,00 €
    davon Entgeltminderung netto200,00 €
    davon zu berichtigende Umsatzsteuer38,00 €

    Für den Kunden ist das die mit Abstand beste Kapitalanlage im Unternehmen: 2 % Nachlass für 16 Tage früher zahlen entspricht rund 46 % Rendite pro Jahr. Wer Skonto anbietet, sollte wissen, dass ein professioneller Einkauf es auf den Tag genau ausreizt.

    Wo die Zeichenkette im XML landet

    FormatXML-Pfad
    UBL (XRechnung UBL, Peppol BIS 3.0)/Invoice/cac:PaymentTerms/cbc:Note
    CII (XRechnung CII, ZUGFeRD, Factur-X)/CrossIndustryInvoice/…/ram:SpecifiedTradePaymentTerms/ram:Description

    UBL (XRechnung UBL)

    <cac:PaymentTerms>
      <cbc:Note>
        #SKONTO#TAGE=14#PROZENT=2.00#
        #SKONTO#TAGE=30#PROZENT=0.00#
        Zahlbar bis 27.09.2026 ohne Abzug.
      </cbc:Note>
    </cac:PaymentTerms>

    CII (ZUGFeRD / Factur-X)

    <ram:SpecifiedTradePaymentTerms>
      <ram:Description>
        #SKONTO#TAGE=14#PROZENT=2.00#
      </ram:Description>
      <ram:DueDateDateTime>
        <udt:DateTimeString format="102">
          20260927
        </udt:DateTimeString>
      </ram:DueDateDateTime>
    </ram:SpecifiedTradePaymentTerms>

    Hinweis zu CII EXTENDED: Die CII-Syntax kennt mit ram:ApplicableTradePaymentDiscountTerms typisierte Skontofelder – diese stehen aber nur im EXTENDED-Profil von ZUGFeRD zur Verfügung und sind nicht Teil des EN-16931-Kerns. Verwenden Sie diese Felder zusätzlich, aber niemals anstelle der Zeichenkette in BT-20. Die Zeichenkette ist der Teil, der immer ankommt. Bei Auslandsrechnungen über Peppol: Die #SKONTO#-Konvention ist eine deutsche Vereinbarung – ergänzen Sie die Kondition im Klartext in der Sprache des Empfängers.

    Die Lücke, die die Syntax offen lässt

    TAGE=14 sagt nicht, ab wann diese vierzehn Tage laufen. Rechnungsdatum? Rechnungseingang? Leistungsdatum? Genau hier entstehen die Diskussionen im Mahnwesen – regelmäßig um zwei bis fünf Tage, die über die Berechtigung eines Skontoabzugs entscheiden.

    Zivilrechtlich beginnt die Frist mit Zugang der Rechnung. Die meisten ERP-Systeme rechnen ab Rechnungsdatum (BT-2). Bei einer E-Rechnung, die im selben Vorgang erzeugt und zugestellt wird, fallen beide Zeitpunkte ohnehin zusammen – ein unterschätztes Nebenargument für den automatisierten Versand.

    1

    BT-9 (Fälligkeitsdatum) immer setzen

    Auch wenn die Zahlungsbedingungen befüllt sind. Das Fälligkeitsdatum ist ein echtes Datum, kein Text, und wird von jedem Empfängersystem korrekt gelesen.

    2

    Skontodatum im Freitext ausschreiben

    Zusätzlich zur strukturierten Angabe: Bei Zahlung bis 11.09.2026 gewähren wir 2 % Skonto. Damit ist der Fall auch für den Menschen entschieden, der ihn klärt.

    3

    Fristbasis in AGB und Kundenstamm festhalten

    Der Zahllauf Ihres Kunden folgt seinen Stammdaten, nicht Ihrem Vertrag. Abgleich beim Onboarding verhindert spätere Streitigkeiten.

    Die andere Richtung: Skonto zuverlässig auslesen

    Auf der Eingangsseite steht das umgekehrte Problem: Aus einem Textfeld müssen belastbare Konditionen werden. Ein naiver Parser, der auf das exakt spezifizierte Format vertraut, zerbricht an der Realität der Sendersysteme.

    Diese Abweichungen sehen wir am häufigsten:

    Komma statt Punkt: PROZENT=2,00 – formal falsch, kommt aus jedem zweiten selbstgebauten Exporter.

    Fehlendes Schluss-#: #SKONTO#TAGE=14#PROZENT=2.00 – ohne abschließendes Rautezeichen.

    Kleinschreibung: #skonto#tage=14#prozent=2.00# – technisch eindeutig, syntaktisch out-of-spec.

    Leerzeichen ums Gleichheitszeichen: #SKONTO#TAGE = 14# – einige ERP-Exporter fügen Leerzeichen ein.

    Normalisierte Zeilenumbrüche: Mehrzeilige Angaben werden zu einer Zeile zusammengezogen. Ein zeilenbasierter Parser findet dann nur die erste Kondition.

    VERZUG als Skonto gebucht: VERZUG in derselben Zeichenkette wird versehentlich als Skonto verbucht – mit 9,62 % Abzug als Ergebnis.

    Ein robuster Parser sucht deshalb nicht nach Zeilen, sondern nach Mustern im gesamten Feld, akzeptiert beide Dezimaltrennzeichen und verwirft alles, was nicht vollständig ist:

    Python
    import re
    from decimal import Decimal, ROUND_HALF_UP
    
    TERM = re.compile(
        r"#\s*(?P<art>SKONTO|VERZUG)"
        r"\s*#\s*TAGE\s*=\s*(?P<tage>\d+)"
        r"\s*#\s*PROZENT\s*=\s*(?P<prozent>\d+(?:[.,]\d{1,4})?)"
        r"(?:\s*#\s*BASISBETRAG\s*=\s*(?P<basis>\d+(?:[.,]\d{1,2})?))?",
        re.IGNORECASE,
    )
    
    def dec(value):
        return Decimal(value.replace(",", "."))
    
    def parse_payment_terms(bt20: str, faelliger_betrag: Decimal):
        konditionen = []
        for m in TERM.finditer(bt20 or ""):
            art = m.group("art").upper()
            prozent = dec(m.group("prozent"))
            basis = dec(m.group("basis")) if m.group("basis") else faelliger_betrag
            betrag = (basis * prozent / 100).quantize(
                Decimal("0.01"), ROUND_HALF_UP
            )
            konditionen.append({
                "art": art,
                "tage": int(m.group("tage")),
                "prozent": prozent,
                "basisbetrag": basis,
                "betrag": betrag,
                "zahlbetrag": faelliger_betrag - betrag if art == "SKONTO" else None,
            })
        return konditionen
    Anwendung auf ein reales Feld
    bt20 = (
        "#SKONTO#TAGE=14#PROZENT=2.00#\n"
        "#SKONTO#TAGE=30#PROZENT=1,00#BASISBETRAG=10710.00#\n"
        "#VERZUG#TAGE=45#PROZENT=9.62#\n"
        "Zahlbar bis 27.09.2026 ohne Abzug."
    )
    
    for k in parse_payment_terms(bt20, Decimal("11900.00")):
        print(k["art"], k["tage"], k["prozent"], k["betrag"], k["zahlbetrag"])
    
    # SKONTO  14  2.00  238.00   11662.00
    # SKONTO  30  1.00  107.10   11792.90
    # VERZUG  45  9.62  1144.78  None

    VERZUG niemals in die Skontologik lassen: Trennen Sie die Arten sauber, bevor Sie irgendetwas abziehen.

    Günstigste noch erreichbare Stufe wählen: Bei mehreren Skontostufen nicht schematisch die erste nehmen, sondern die beste, gemessen am geplanten Zahldatum.

    Kaufmännisch auf zwei Stellen runden: Mit Decimal, nicht mit float. Ein Rundungsfehler von einem Cent produziert eine offene Restforderung und damit einen Klärfall.

    Nicht geparste Zeichenketten protokollieren: Ein Feld, das ein # enthält, aber kein Muster trifft, ist ein Fehler des Senders – und ein Anruf wert, weil er sich bei jeder Folgerechnung wiederholt.

    Der andere Grund, warum Skonto verfällt: Zeit und Liquidität

    Die saubere Kodierung ist die eine Hälfte. Die andere: Ein Skontoabzug nutzt nur dem, der am Tag 14 tatsächlich zahlen kann. In der Praxis verfällt der Vorteil aus zwei Gründen, und keiner davon ist technisch.

    Der Prozess ist zu langsam

    Eine Eingangsrechnung, die acht Tage in Prüfung und Freigabe liegt, hat die 14-Tage-Frist verbraucht, bevor der Zahllauf sie überhaupt sieht. Das ist kein Finanzierungsthema, sondern ein Prozessthema – an Eingangskanälen, Validierung, Matching und Freigabewegen. Meist innerhalb weniger Wochen messbar zu verbessern.

    Das Working Capital reicht nicht

    Die Rechnung ist geprüft, das Skonto berechtigt, die Frist läuft – aber die eigenen Forderungen kommen erst in 40 Tagen herein. Dann wird eine Kondition liegengelassen, die auf das Jahr gerechnet rund 46 % entspricht, weil für 16 Tage die Mittel fehlen.

    Finbc GmbH – das zweite Standbein

    Genau hier setzt die Finbc GmbH – die Gesellschaft hinter rechnungsapi.de – an: Wir unterstützen bei der Versorgung mit Liquidität und stellen Working Capital bereit, etwa über Factoring (Ihre Forderungen werden sofort zu Liquidität, statt 40 Tage im Debitorenbestand zu stehen) oder Einkaufsfinanzierung (Ihre Lieferanten werden fristgerecht und skontiert bezahlt, Ihr eigenes Zahlungsziel verlängert sich). Die Rechnung dahinter ist meist schnell gemacht: Skontokonditionen liegen in einer Größenordnung, gegen die sich kurzfristige Finanzierungskosten in aller Regel gut ausgehen.

    Mit rechnungsapi.de

    Beim Erzeugen übergeben Sie die Kondition im Feld paymentTerms (BT-20) und setzen zusätzlich paymentDueDate (BT-9):

    Request Body (JSON)
    {
      "invoice": {
        "invoiceNumber": "RE-2026-0815",
        "invoiceIssueDate": "2026-08-27",
        "paymentDueDate": "2026-09-27",
        "paymentTerms": "#SKONTO#TAGE=14#PROZENT=2.00#\nBei Zahlung bis 11.09.2026 gewähren wir 2 % Skonto.",
        "paymentMeansTypeCode": "58"
      }
    }

    Die Ausgabe ist wahlweise XRechnung oder ZUGFeRD – dieselbe Zeichenkette landet in cbc:Note beziehungsweise ram:Description, je nach Zielformat. Auf der Eingangsseite liefern die Extraktions- und Validierungsendpunkte die Felder aus einer ZUGFeRD-PDF, auf die Sie den Parser oben ansetzen.

    In Arbeit: Skonti als fertiges JSON aus jeder Eingangsrechnung

    Den Parser oben müssen Sie nicht selbst betreiben. Wir erweitern die Rechnungserkennung so, dass die Skontokonditionen jeder erkannten Eingangsrechnung bereits ausgelesen und normalisiert zurückkommen – Art, Frist, Prozentsatz, Bemessungsgrundlage, errechneter Skontobetrag und resultierender Zahlbetrag als strukturiertes JSON:

    "paymentDiscounts": [
      { "type": "SKONTO", "days": 14, "percent": 2.00,
        "baseAmount": 11900.00, "discountAmount": 238.00, "payableAmount": 11662.00 },
      { "type": "VERZUG", "days": 45, "percent": 9.62 }
    ]

    Ihr ERP übernimmt damit Werte statt Text – ohne eigene Regex-Logik, ohne zusätzliches KI-Modell. Wir suchen Pilotkunden mit nennenswertem Eingangsrechnungsvolumen. Sie bekommen früh Zugriff, wir bekommen echte Rechnungen mit echten Zahlungsbedingungen – auch die kaputten.

    Checkliste

    Ausgangsseite

    Skonto steht in BT-20, nicht in BG-20 / BT-92

    Syntax #SKONTO#TAGE=n#PROZENT=n.nn# mit abschließendem #

    Punkt als Dezimaltrennzeichen, zwei Nachkommastellen, kein Vorzeichen

    Jede Kondition in eigener Zeile, Freitext getrennt und ohne #

    BASISBETRAG gesetzt, wenn nicht der volle fällige Betrag skontierfähig ist

    BT-9 (Fälligkeitsdatum) immer befüllt

    Skontodatum zusätzlich im Klartext; bei Auslandsrechnungen in der Sprache des Empfängers

    Validierung gegen EN 16931 und KoSIT-Regeln vor dem Versand

    Eingangsseite

    Parser arbeitet musterbasiert, nicht zeilenbasiert

    Toleranz für Komma, Kleinschreibung, Leerzeichen, fehlendes Schluss-#

    SKONTO und VERZUG strikt getrennt

    Beträge mit Decimal und kaufmännischer Rundung (nicht float)

    Nicht interpretierbare Zahlungsbedingungen werden protokolliert, nicht verworfen

    Skonto modellieren, auslesen – oder endlich nutzen?

    Wir schauen uns Ihr Feld BT-20 an einem echten Beispiel an, sprechen über den Weg zum Pilotkunden und – wenn es an Zeit oder Liquidität hängt – über Factoring und Einkaufsfinanzierung. Kostenloses 30-Minuten-Gespräch.

    Gespräch buchensupport@rechnungsapi.de
    rechnungsapi.de

    Professionelle E-Rechnungs-APIs für KMUs. Transformieren Sie Ihr ERP-System mit ZUGFeRD-konformen Lösungen und DSGVO-konformer KI-Technologie.

    DSGVO-konform & sicher

    Produkt

    • Preise

    Lösungen

    • Steuerberater & Kanzleien
    • Unternehmen & Mittelstand
    • IT-Teams & Softwareanbieter
    • E-Invoicing-Berater & Partner
    • Startups & SaaS
    • International & Peppol

    Rechtliches

    • Impressum
    • Datenschutzerklärung
    • Nutzungsbedingungen
    • Kontakt
    • DSGVO-Konformität

    Server in Deutschland · DSGVO-konform · Auftragsverarbeiter ISO/IEC 27001-zertifiziert (Open Telekom Cloud)

    © 2026 rechnungsapi.de

    support@rechnungsapi.de