DEEN
Python & Node SDK

E-Rechnung mit Python und Node.js erzeugen (API-Integration)

Kurz gesagt: Sie senden einen kompakten JSON-Payload per HTTP POST an die fakturai REST-API und erhalten eine EN-16931-konforme ZUGFeRD-/Factur-X-PDF zurück — ohne XML-Wissen, ohne lokale Generator-Bibliotheken, ohne manuelle Namespace-Deklarationen. Die API prüft die erzeugte Datei vor der Auslieferung gegen ein KoSIT-orientiertes Akzept-Gate.

Warum API statt lokaler Bibliothek?

Lokale XML-Bibliotheken für ZUGFeRD oder XRechnung erfordern tiefes Format-Know-how: EN-16931-BT-/BG-Codes, Namespace-Deklarationen, Schematron-Regeln, Profil-Spezifika. Die API abstrahiert das:

Python-Beispiel (httpx / requests)

Dieses synthetische B2B-Beispiel erzeugt eine ZUGFeRD/Factur-X-PDF. Voraussetzung: eine freigegebene Web-App-Instanz, ein gespeichertes Verkäuferprofil und dessen API-Key. Verkäuferdaten kommen aus dem Profil, die Rechnungsnummer vergibt der Server. Dieser Endpoint unterstützt keinen format-Schalter für reine XRechnung-XML. Erfolgreiche Erzeugung zählt zum Verbrauch; keine automatische Wiederholung starten.

Setzen Sie FAKTURAI_BASE_URL auf die Web-App (lokal z. B. http://127.0.0.1:3004, bei freigegebenem Betrieb https://fakturai.de) und FAKTURAI_API_KEY sicher in Ihrer Umgebung, nicht im Quellcode. Installieren Sie httpx mit python -m pip install httpx, speichern Sie den Block als generate.py und starten Sie python generate.py. Verwenden Sie nur synthetische Daten; die Anfrage wird an die konfigurierte Instanz übertragen.

import os, pathlib
import httpx

base = os.environ["FAKTURAI_BASE_URL"].rstrip("/")
key = os.environ["FAKTURAI_API_KEY"]
payload = {
  "invoice_date": "2026-06-16",
  "due_date": "2026-06-30",
  "currency": "EUR",
  "buyer": {
    "name": "Synthetic Client GmbH",
    "address": {
      "line_one": "Beispielweg 2", "postcode": "80331",
      "city": "München", "country": "DE"
    },
    "contact_email": "billing@example.invalid"
  },
  "lines": [{
    "name": "Beratungsleistung", "quantity": "2", "unit": "HUR",
    "unit_price": "50.00", "vat_rate": "19.00"
  }]
}
resp = httpx.post(
    base + "/api/v1/invoices",
    json=payload,
    headers={"Authorization": "Bearer " + key},
    timeout=120.0,
)
resp.raise_for_status()
if resp.status_code != 201 or resp.headers.get("content-type", "").split(";")[0] != "application/pdf":
    raise RuntimeError("Expected HTTP 201 application/pdf")
pathlib.Path("invoice.pdf").write_bytes(resp.content)

Für requests ersetzen Sie httpx.post durch requests.post — der Payload ist identisch.

Node.js / TypeScript-Beispiel (fetch)

Node.js 22 oder neuer: als generate.mjs speichern und mit node generate.mjs starten. Dieselben Umgebungsvariablen gelten. Beide Beispiele speichern nur bei 201 application/pdfeine invoice.pdf; Fehlerantworten sind JSON, keine PDF und kein bestandener Test.

import fs from "node:fs/promises";

const base = process.env.FAKTURAI_BASE_URL;
const key = process.env.FAKTURAI_API_KEY;
if (!base || !key) throw new Error("Set FAKTURAI_BASE_URL and FAKTURAI_API_KEY");
const payload = {
  invoice_date: "2026-06-16",
  due_date: "2026-06-30",
  currency: "EUR",
  buyer: {
    name: "Synthetic Client GmbH",
    address: {
      line_one: "Beispielweg 2", postcode: "80331",
      city: "München", country: "DE"
    },
    contact_email: "billing@example.invalid"
  },
  lines: [{
    name: "Beratungsleistung", quantity: "2", unit: "HUR",
    unit_price: "50.00", vat_rate: "19.00"
  }]
};
const res = await fetch(new URL("/api/v1/invoices", base), {
  method: "POST",
  headers: { "Content-Type": "application/json", Authorization: "Bearer " + key },
  body: JSON.stringify(payload),
  signal: AbortSignal.timeout(120_000),
});
if (!res.ok) throw new Error("API error " + res.status);
if (res.status !== 201 || res.headers.get("content-type")?.split(";")[0] !== "application/pdf") {
  throw new Error("Expected HTTP 201 application/pdf");
}
await fs.writeFile("invoice.pdf", Buffer.from(await res.arrayBuffer()));

Der Payload ist dieselbe JSON-Struktur — die Sprache ist irrelevant für die API. In TypeScript fügen Sie eine Typ-Definition für den Payload hinzu; das Ergebnis bleibt ein Buffer bzw. ein ArrayBuffer.

Wichtige Pflichtfelder

Feld (JSON)EN-16931-CodePflicht
invoice_dateBT-2✓ (YYYY-MM-DD)
due_dateBT-9✓ (YYYY-MM-DD)
buyer.name, buyer.addressBG-7 / BG-8✓ (verschachtelte Adresse)
lines[].name, lines[].quantityBT-153 / BT-129✓ (Menge als Dezimalstring)
lines[].unit, lines[].unit_priceBT-130 / BT-146✓ (Preis als Dezimalstring)
lines[].vat_rateBT-152✓ (Dezimalstring)
currencyBT-5Optional, Standard EUR

KoSIT-Accept-Gate: was die API vor der Rückgabe prüft

Jede erzeugte Datei durchläuft serverseitig ein vierschichtiges Prüf-Gate:

  1. Schema-Konformität (XSD)
  2. Schematron-Regeln (EN 16931 + ggf. CIUS XRechnung)
  3. Summenvalidierung (Positionsnetto, USt-Aufschlüsselung, Dokumentsummen)
  4. PDF/A-3-Konformität (bei ZUGFeRD/Factur-X)

Erreicht die Datei nicht ACCEPT-Status, gibt die API einen Fehler mit den konkreten Schematron-Regeln zurück — so sehen Sie sofort, welche Pflichtfelder fehlen oder welche Summe nicht stimmt.

Vorhandene Dateien — z. B. aus einem Drittsystem oder einem früheren API-Aufruf — können Sie ohne Konto im kostenlosen Validator gegen EN 16931 prüfen.

E-Rechnung kostenlos prüfen

MCP-Integration für AI-Agenten

Neben der REST-API steht ein MCP-Server bereit, der dieselbe Erzeuge-und-prüfe-Logik als Tool-Call exponiert. AI-Agenten und MCP-Clients können damit E-Rechnungen erzeugen, ohne HTTP manuell zu formulieren. Details im Beitrag E-Rechnung per API & MCP erstellen.

Was fakturai nicht ersetzt

fakturai erzeugt und prüft die technische Format- und Strukturkonformität nach EN 16931 mit einem KoSIT-orientierten Akzept-Gate. Die inhaltliche und steuerliche Richtigkeit des JSON-Payloads, die GoBD-konforme Archivierung der erzeugten Datei und die buchhalterische Behandlung bleiben in Ihrer Verantwortung. fakturai ist kein Buchhaltungssystem und gibt keine Rechts-, Steuer- oder Zustellungsgarantien.

Weiterlesen

Vertragsreferenz: REST-Dokumentation. Synthetische Integrationsbeispiele; technische Struktursprache nach EN 16931, kein Rechts-/Steuer-/Zustellungsversprechen.


English companion: Generate German e-invoices with Python and Node.js (API integration).