Python & Node SDK
Generate German e-invoices with Python and Node.js (API integration)
Short answer: send a compact JSON payload via HTTP POST to the fakturai REST API and receive an EN 16931-compliant ZUGFeRD/Factur-X or XRechnung file back — no XML knowledge, no local libraries, no manual namespace declarations. The API checks the generated file against a KoSIT-aligned accept gate before returning it.
Why API instead of a local library?
Local XML libraries for ZUGFeRD or XRechnung require deep format knowledge: EN 16931 BT/BG codes, namespace declarations, Schematron rules, profile specifics. The API abstracts all of that:
- Language-agnostic — works with Python, Node.js, TypeScript, Go, curl, n8n, Make, AI agents.
- No local tooling — no local validation tooling, no KoSIT validator installed locally.
- KoSIT accept gate server-side — the file is only returned when it reaches ACCEPT level.
- Always current — profile updates (e.g. XRechnung 3.0) land server-side, not in your client code.
Python example (httpx / requests)
import httpx, pathlib
payload = {
"invoiceNumber": "INV-2026-0042",
"issueDate": "2026-06-16",
"seller": {
"name": "Sample GmbH", "street": "Musterstraße 1", "city": "Berlin",
"postalCode": "10115", "countryCode": "DE", "vatId": "DE123456789"
},
"buyer": {
"name": "Client AG", "street": "Clientweg 2", "city": "Munich",
"postalCode": "80331", "countryCode": "DE"
},
"lines": [{"description": "Consulting", "quantity": 2, "unitCode": "C62",
"unitPrice": 50.0, "vatRate": 19.0}],
"currency": "EUR",
"format": "zugferd" # or "xrechnung"
}
resp = httpx.post(
"https://api.fakturai.de/v1/invoices",
json=payload,
headers={"Authorization": "Bearer YOUR_API_KEY"},
)
resp.raise_for_status()
pathlib.Path("invoice.pdf").write_bytes(resp.content)For requests, replace httpx.post with requests.post — the payload is identical.
Node.js / TypeScript example (fetch)
import fs from "fs/promises";
const payload = {
invoiceNumber: "INV-2026-0042", issueDate: "2026-06-16",
seller: { name: "Sample GmbH", street: "Musterstraße 1", city: "Berlin",
postalCode: "10115", countryCode: "DE", vatId: "DE123456789" },
buyer: { name: "Client AG", street: "Clientweg 2", city: "Munich",
postalCode: "80331", countryCode: "DE" },
lines: [{ description: "Consulting", quantity: 2, unitCode: "C62",
unitPrice: 50.0, vatRate: 19.0 }],
currency: "EUR",
format: "zugferd", // or "xrechnung"
};
const res = await fetch("https://api.fakturai.de/v1/invoices", {
method: "POST",
headers: { "Content-Type": "application/json", Authorization: "Bearer YOUR_API_KEY" },
body: JSON.stringify(payload),
});
if (!res.ok) throw new Error(`API error ${res.status}: ${await res.text()}`);
await fs.writeFile("invoice.pdf", Buffer.from(await res.arrayBuffer()));The payload is the same JSON structure regardless of language. In TypeScript, add a type definition for the payload; the result is a Buffer / ArrayBuffer.
Key mandatory fields
invoiceNumber(BT-1),issueDate(BT-2),currency(BT-5) — requiredseller.vatId(BT-31),lines[].unitCode(BT-130),lines[].vatRate(BT-119) — requiredformat:"zugferd"(ZUGFeRD/Factur-X PDF/A-3) or"xrechnung"(pure XML)
MCP integration for AI agents
Alongside the REST API, a MCP server exposes the same generate-and-check logic as a tool call. AI agents and MCP clients can generate e-invoices without crafting HTTP manually. See create e-invoices per API & MCP.
What fakturai does not replace
fakturai generates and checks the technical format and structural compliance per EN 16931 with a KoSIT-aligned accept gate. The content and tax correctness of the JSON payload, GoBD-compliant archiving and accounting treatment remain your responsibility. fakturai is not tax advice and makes no legal, tax or delivery guarantees.
Next step
Free German e-invoice validator · Create an API key · API docs
Related: API & MCP creation guide · E-invoice example (XML) · XRechnung validation errors