Für Softwarehersteller

invowerk prüft E-Rechnungen per REST-API, im Build Ihrer Software oder per MCP. Sie erhalten dasselbe Ergebnis wie im kostenlosen Prüf-Tool, als JSON mit Prüfbericht.

Prüfumfang · API · Prüfung im Build · MCP · Weitere Endpunkte

Was invowerk prüft

  • XRechnung 3.0.2 und EN 16931 (UBL und CII) nach der KoSIT-Prüfkonfiguration vom 31.08.2026. Es gilt das Ergebnis des KoSIT-Validators 1.6.3, des Prüfprogramms der Koordinierungsstelle für IT-Standards (KoSIT). Ist er nicht erreichbar, prüft invowerk mit denselben Regeln und meldet das im Feld verdict_source.
  • ZUGFeRD 2.5.2 und Factur-X nach den Prüfregeln der FeRD je Profil, von MINIMUM bis EXTENDED.
  • Peppol BIS Billing 3.0.21.
  • Das PDF: PDF/A mit veraPDF 1.30.2, dazu Dateiname, XMP-Metadaten und Einbettung der XML-Datei.
  • Hinweise (IW-*): Zusatzprüfungen, etwa Prüfziffern, Summen und der Abgleich von PDF und Rechnungsdaten. Sie stehen im Feld hints und ändern das Ergebnis nicht.

Regelwerke, Änderungen und die Testdateien stehen im Prüfstand. Warum Validatoren abweichen, erklärt Abweichungen zwischen E-Rechnungs-Validatoren. Jede Regel mit Erklärung finden Sie unter Fehlercodes.

API

Senden Sie die Rechnung (XML oder PDF) als Request-Body an POST https://api.invowerk.dev/v1/validate, den API-Schlüssel im Header X-API-Key. Ohne Schlüssel gilt ein niedrigeres Limit. Das Ergebnis kommt immer mit HTTP 200. Ein anderer Status bedeutet, dass die Anfrage selbst gescheitert ist (etwa 402, 413 oder 429). Mit ?explain=true enthalten Meldungen zu häufigen Regeln ihre Erklärung.

curl -sS -H "X-API-Key: $INVOWERK_KEY" \
     --data-binary @rechnung.xml https://api.invowerk.dev/v1/validate
import os

import requests

with open("rechnung.xml", "rb") as fh:
    r = requests.post(
        "https://api.invowerk.dev/v1/validate",
        headers={"X-API-Key": os.environ["INVOWERK_KEY"]},
        data=fh,
        timeout=60,
    )
r.raise_for_status()
report = r.json()
print(report["valid"], report["verdict_source"])
for f in report["findings"]:
    if f["severity"] == "fatal":
        print(f["rule_id"], f["message"])

Die wichtigsten Felder der Antwort

validDas Ergebnis (true oder false).
verdict_sourceofficial: Ergebnis des KoSIT-Validators. local: Ergebnis der eigenen Prüfung.
findings[]Alle Meldungen mit rule_id und severity (fatal = Fehler, warning = Warnung, information = Info).
errorsDie Meldungen nach Art: format, business_rules, carrier.
hintsHinweise (IW-*), getrennt vom Ergebnis.
rulesetsDie Versionen der Regelwerke dieser Prüfung.
evidence.document_sha256SHA-256 der geprüften Datei, für den Prüfbericht.
e_rechnung_de.statusEinordnung nach dem BMF-Schreiben vom 15.10.2025, z. B. e_rechnung oder keine_e_rechnung.

Prüfung im Build

Der Schritt prüft alle Dateien unter rechnungen/. Bei Fehlern gibt er die Regeln aus und lässt den Job fehlschlagen. Legen Sie den API-Schlüssel als Secret INVOWERK_KEY an.

# .github/workflows/e-rechnung.yml: als Schritt nach Ihrem Build
      - name: E-Rechnungen prüfen
        env:
          INVOWERK_KEY: ${{ secrets.INVOWERK_KEY }}
        run: |
          status=0
          for f in rechnungen/*.xml rechnungen/*.pdf; do
            [ -e "$f" ] || continue
            if ! res=$(curl -sS --fail-with-body -H "X-API-Key: $INVOWERK_KEY" \
                --data-binary @"$f" https://api.invowerk.dev/v1/validate); then
              echo "$f: Anfrage fehlgeschlagen: $res"; status=1; continue
            fi
            if echo "$res" | jq -e '.valid' >/dev/null; then
              echo "$f: bestanden"
            else
              echo "$f: nicht bestanden"
              echo "$res" | jq -r '.findings[] | select(.severity == "fatal") | "\(.rule_id): \(.message)"'
              status=1
            fi
          done
          exit "$status"
# .gitlab-ci.yml: INVOWERK_KEY als maskierte CI/CD-Variable anlegen
e-rechnungen-pruefen:
  image: alpine:3
  before_script:
    - apk add --no-cache curl jq
  script:
    - |
      status=0
      for f in rechnungen/*.xml rechnungen/*.pdf; do
        [ -e "$f" ] || continue
        if ! res=$(curl -sS --fail-with-body -H "X-API-Key: $INVOWERK_KEY" \
            --data-binary @"$f" https://api.invowerk.dev/v1/validate); then
          echo "$f: Anfrage fehlgeschlagen: $res"; status=1; continue
        fi
        if echo "$res" | jq -e '.valid' >/dev/null; then
          echo "$f: bestanden"
        else
          echo "$f: nicht bestanden"
          echo "$res" | jq -r '.findings[] | select(.severity == "fatal") | "\(.rule_id): \(.message)"'
          status=1
        fi
      done
      exit "$status"
# .forgejo/workflows/e-rechnung.yml: als Schritt nach Ihrem Build,
# das Runner-Image braucht curl und jq
      - name: E-Rechnungen prüfen
        env:
          INVOWERK_KEY: ${{ secrets.INVOWERK_KEY }}
        run: |
          status=0
          for f in rechnungen/*.xml rechnungen/*.pdf; do
            [ -e "$f" ] || continue
            if ! res=$(curl -sS --fail-with-body -H "X-API-Key: $INVOWERK_KEY" \
                --data-binary @"$f" https://api.invowerk.dev/v1/validate); then
              echo "$f: Anfrage fehlgeschlagen: $res"; status=1; continue
            fi
            if echo "$res" | jq -e '.valid' >/dev/null; then
              echo "$f: bestanden"
            else
              echo "$f: nicht bestanden"
              echo "$res" | jq -r '.findings[] | select(.severity == "fatal") | "\(.rule_id): \(.message)"'
              status=1
            fi
          done
          exit "$status"

MCP

Der MCP-Server unter https://invowerk.dev/mcp/ stellt dieselbe Prüfung KI-Assistenten bereit. So binden Sie ihn in Claude Code ein:

claude mcp add --transport http invowerk https://invowerk.dev/mcp/ \
     --header "X-API-Key: $INVOWERK_KEY"

Andere Clients: MCP verbinden.

Weitere Endpunkte

invowerk erzeugt E-Rechnungen aus JSON (/v1/generate), wandelt zwischen UBL und CII um (/v1/convert), liest Rechnungsdaten als JSON aus (/v1/parse) und stellt Rechnungen als HTML dar (/v1/render). Erzeugte und umgewandelte Rechnungen prüft invowerk vor der Ausgabe. Alle Endpunkte beschreibt die API-Dokumentation.

Tarife und Credits pro Aufruf (1 Prüfung = 1 Credit) stehen unter Preise.