Steuerlogik

Valides XML ist nicht dasselbe wie richtige Steuer

Ein Format-Renderer nimmt entgegen, was du schickst, und gibt formal korrektes XML zurück — auch mit der falschen Steuerkategorie. Bei Factora entscheidet nicht der Renderer, sondern der amtliche Validator. Wird eine Regel verletzt, bekommst du HTTP 400 statt eines Dokuments.

Das Gate

Jede Rechnung läuft durch den KoSIT-Validator, bevor sie existiert

Der Aufruf sitzt innerhalb der Datenbank-Transaktion. Schlägt die Prüfung fehl, wird die gesamte Erzeugung zurückgerollt — Rechnung, Positionen und ein eventuell neu angelegter Kunde. Es gibt keinen Weg, ein ungeprüftes Dokument zu erhalten, auch keinen Schalter dafür.

Verstoß im Request
POST /api/v1/invoices/atomic/ HTTP/1.1
Authorization: Bearer fa_live_...

{
  "items": [
    {
      "description": "Bauleistung nach § 13b",
      "quantity": "1.000",
      "unit": "C62",
      "unit_price_net": "4000.00",
      "tax_category_code": "AE",
      "vat_rate": "19.00"
    }
  ]
}
Antwort statt Dokument
HTTP/1.1 400 Bad Request

{
  "valid": false,
  "data": null,
  "errors": [
    {
      "code": "xrechnung_invalid",
      "rule": "BR-AE-5",
      "bt": "BT-119",
      "message": "Bei Steuerkategorie AE muss der Steuersatz 0 sein.",
      "location": "/rsm:CrossIndustryInvoice[1]/.../ram:ApplicableTradeTax[1]"
    }
  ],
  "meta": { "validator": "kosit-xrechnung", "blocking": true }
}

Ist der Validator nicht erreichbar, antwortet die API mit 503 — nicht mit einem ungeprüften Dokument. Fail-closed ist eine bewusste Entscheidung: lieber kein Beleg als ein falscher.

Was das Gate abfängt

Steuerregeln aus EN 16931 und CIUS-DE, die zu HTTP 400 führen

Auswahl der Regeln mit Steuerbezug. Befunde kommen strukturiert zurück — Regel-ID, betroffener Business Term und XPath —, nicht als Freitext.

Steuerkategorie und Satz

  • BR-AE-05 Reverse Charge mit Steuersatz ungleich null → HTTP 400
  • BR-IC-05 Innergemeinschaftliche Lieferung mit Steuersatz ungleich null → HTTP 400
  • BR-E-05 Steuerbefreite Position mit Steuersatz ungleich null → HTTP 400
  • BR-Z-05 Nullsatz-Position mit Steuersatz ungleich null → HTTP 400
  • BR-O-05 Nicht steuerbare Position mit Steuersatz ungleich null → HTTP 400

Pflichtangaben je Kategorie

  • BR-AE-02 Reverse Charge ohne Identifikation des Empfängers → HTTP 400
  • BR-IC-11 Ig. Lieferung ohne Käufer-Identifikation → HTTP 400
  • BR-IC-12 Ig. Lieferung ohne Verkäufer-USt-IdNr. → HTTP 400
  • BR-*-10 Kategorie ohne Befreiungsgrund (BT-120) → HTTP 400

Aufschlüsselung und Summen

  • BR-*-01 / -02 Kategorie ohne passende Steueraufschlüsselung (BG-23) → HTTP 400
  • BR-CO-16 Vorauszahlung übersteigt den Rechnungsbetrag → HTTP 400
  • BR-CL-* Wert außerhalb der zulässigen Codeliste → HTTP 400
  • Summenabgleich ERP-Summen weichen von der Nachrechnung ab — 422 → HTTP 400
Die Fälle

Steuerlich abgebildet, nicht nur syntaktisch möglich

Sieben Kategorien nach UNTDID 5305 stehen zur Verfügung — S, Z, E, AE, K, G und O. Bewusst enger als die volle Codeliste: Kanaren, Ceuta/Melilla und das italienische Split Payment werden nicht angeboten, deutsche Sieben-Prozent-Positionen laufen als S.

  • § 13b Reverse Charge

    Grenzüberschreitend an einen EU-Unternehmer mit USt-IdNr. wird die Kategorie AE automatisch abgeleitet. Inländische Tatbestände — Bauleistungen, Metalle, Mobilfunk ab 5.000 € — kommen über den hinterlegten Rechtsgrund am Kunden oder Mandanten.

  • Innergemeinschaftliche Lieferung

    Kategorie K mit Befreiungsgrund nach § 4 Nr. 1b UStG. Der Validator besteht auf der USt-IdNr. beider Seiten; fehlt eine, entsteht kein Dokument.

  • Ausfuhr in Drittländer

    Kategorie G, Befreiungsgrund § 4 Nr. 1a UStG, VATEX-EU-G. Sitzt der Käufer in der EU, wird die Kategorie in der Web-Anwendung abgelehnt.

  • OSS-Fernverkauf § 3c

    Für B2C-Lieferungen in ein anderes EU-Land sind die Steuersätze von 28 Gebieten hinterlegt — die 27 Mitgliedstaaten und Nordirland, mit Gültigkeitsdatum. Die Bestimmungslandsätze werden zusätzlich zu den deutschen akzeptiert; die Kategorie bleibt S.

  • § 19 Kleinunternehmer

    Kategorie E mit dem Hinweis „Gemäß § 19 UStG wird keine Umsatzsteuer berechnet“. Ein VATEX-Code wird hier bewusst nicht gesetzt — CIUS-DE sieht für § 19 keinen vor.

  • Nordirland

    Der XI-Sonderfall aus dem Brexit-Protokoll wird an zwei Stellen erkannt: am Ländercode und am Präfix der USt-IdNr. Warenlieferungen laufen über den EU-Pfad, sonstige Leistungen über den Drittlandpfad.

  • Fiskalvertreter

    BG-11 und BG-12 mit BT-62 bis BT-69, schreibend und lesend in CII und UBL. Ein am Mandanten hinterlegter Vertreter wird in den Verkäufer-Snapshot eingefroren.

  • Self-Billing im Gutschriftverfahren

    Dokumenttyp 389 nach § 14 Abs. 2 UStG. Im UBL-Pfad schaltet die API auf das Peppol-Self-Billing-Profil um — das Standard-Billing-Profil weist 389 zurück.

Befreiungsgründe

BT-120 und BT-121 werden gesetzt, nicht abgefragt

Wer eine steuerbefreite Kategorie schickt, muss den Befreiungsgrund nicht kennen. Text und VATEX-Code werden aus der Kategorie abgeleitet und beim ersten Speichern eingefroren. Damit fällt die häufigste Ursache für abgelehnte Rechnungen weg, ohne dass das anbindende System eine Textbibliothek pflegen muss.

Automatisch gesetzt

  • AE — Reverse Charge VATEX-EU-AE, § 13b UStG / Art. 196 MwStSystRL ✓ live
  • K — ig. Lieferung VATEX-EU-IC, § 4 Nr. 1b UStG ✓ live
  • G — Ausfuhr VATEX-EU-G, § 4 Nr. 1a UStG ✓ live

Bewusst ohne Code

  • E — § 19 Kleinunternehmer nur BT-120-Text, CIUS-DE kennt keinen Code ✓ live
  • O — nicht steuerbar nur BT-120-Text ✓ live
Grenzen

Was der API-Pfad nicht leistet

Ein Vergleich, der nur Haken zeigt, ist keiner. Diese Prüfungen laufen in der Web-Anwendung beim Finalisieren, nicht im Integrationspfad — wer über die API bucht, muss sie im eigenen System abbilden.

  • Keine VIES-Abfrage im API-Call

    Die Live-Prüfung der USt-IdNr. gegen das EU-Register läuft beim Finalisieren in der Web-Anwendung: ungültig blockiert, nicht erreichbar warnt. Im API-Pfad wird die USt-IdNr. auf Format geprüft, nicht auf Existenz.

  • Kundentyp ist kein Feld der Norm

    EN 16931 kennt kein B2B und kein B2C. Trägt ein Request Reverse Charge für einen Privatkunden ein und liefert eine Registernummer mit, ist die Regel formal erfüllt — der Validator kann den Widerspruch nicht sehen. Die Plausibilität gegen den Kundentyp prüft nur die Web-Anwendung.

  • Sitzland wird nicht gegengeprüft

    Ob eine ig. Lieferung wirklich grenzüberschreitend ist oder eine Ausfuhr tatsächlich ins Drittland geht, prüft der API-Pfad nicht. Der Validator sieht die Angaben, nicht ihre Richtigkeit.

  • Kein Gelangensnachweis

    Der Nachweis nach § 17a UStDV wird in der Web-Anwendung als Hinweis geführt und blockiert dort bewusst nicht — er darf nach der Rechnung eintreffen. Über die API gibt es dafür keine Erfassung.

Eigenbau

XML zusammenbauen kann jeder. Die Kategorie richtig treffen nicht

Eine Bibliothek erzeugt aus deinen Feldern ein Dokument. Sie weiß nicht, ob Reverse Charge hier zulässig ist, ob der Befreiungsgrund zur Kategorie passt oder ob die Aufschlüsselung zur Summe stimmt. Das fällt nicht beim Deployment auf und nicht im Test — es fällt bei der Betriebsprüfung deines Mandanten auf, zwei Jahre später, und dann ist es dein Kunde, der erklären muss, warum die Steuer falsch ausgewiesen wurde. Der Unterschied zwischen einem Renderer und dieser API ist nicht die Ausgabe. Es ist die Antwort, wenn die Eingabe nicht stimmt.

Steuerlogik

Gegen echte Regeln testen

Die Sandbox ist dauerhaft kostenlos und braucht keine Kreditkarte. Sie durchläuft dieselbe Business-Rule- und KoSIT-Prüfung wie der Live-Betrieb — ein Verstoß liefert auch dort 400.