API-Dokumentation
POST /v1/convert
Erzeugt aus Rechnungsdaten (JSON oder CII-XML) und einem optionalen Sicht-PDF
eine validierte ZUGFeRD/Factur-X-Rechnung (PDF/A-3, EN 16931).
multipart/form-data mit folgenden Feldern:
| Feld | Typ | Beschreibung |
|---|---|---|
invoice | JSON | Rechnungsdaten im eunormia-Schema (Formfeld oder Datei). Pflicht, außer bei XML-Passthrough. |
xml | Datei/Text | Fertiges CII-XML (Passthrough): wird 1:1 eingebettet, das Gate prüft es. Dann ist ein pdf Pflicht. |
pdf | Datei | Ihr Sicht-PDF (max. 10 MB). Ohne PDF rendert eunormia eine Standardvorlage aus den Rechnungsdaten. |
options | JSON | Siehe unten. |
Optionen
| Option | Beschreibung |
|---|---|
profile | EN16931 (Default), EXTENDED, XRECHNUNG, BASIC, BASICWL, MINIMUM. Achtung: MINIMUM/BASICWL erfüllen nicht die Anforderungen an eine E-Rechnung nach §14 UStG. |
includeUbl | Zusätzlich XRechnung-UBL-2.1-XML in der Antwort (ubl), experimentell. |
kosit | Zusätzlich mit dem amtlichen KoSIT-Validator prüfen (XRechnung/DE). Ergebnis unter report.kosit — informativ, blockt die Auslieferung nicht. Etwas langsamer. |
frCtc | Zusätzlich die französischen CTC-Regeln prüfen (FNFE-MPE). Ergebnis unter report.frCtc. |
sandbox | Bewusst ein Muster mit Wasserzeichen erzeugen (verbraucht kein Kontingent). |
Antwort
200: {"pdf": "<base64>", "filename": "…", "report": {…}, "ubl": "…"?}.
Der report enthält u. a. verapdf und xml
(beide immer PASS — sonst gäbe es keine Auslieferung),
watermark, sha256 und bei Anforderung
kosit/frCtc. Fachliche Fehler kommen als
422 mit error, stage und verständlichen
details — Summenabweichungen werden nie stillschweigend korrigiert.
Quickstarts
cURL — JSON → ZUGFeRD
curl -X POST https://eunormia.com/v1/convert \
-H "Authorization: Bearer eun_live_YOUR_TOKEN" \
-F 'invoice={"number":"RE-2026-0042","issueDate":"2026-07-08","dueDate":"2026-08-07","currency":"EUR","seller":{"name":"Muster GmbH","street":"Musterstraße 1","zip":"4020","city":"Linz","country":"AT","vatId":"ATU12345678"},"buyer":{"name":"Beispiel GmbH","street":"Beispielweg 2","zip":"80331","city":"München","country":"DE","vatId":"DE123456789"},"items":[{"name":"Leistung","quantity":1,"unit":"C62","unitPrice":100.0,"vatPercent":20}]}'
cURL — JSON + PDF → ZUGFeRD
curl -X POST https://eunormia.com/v1/convert \
-H "Authorization: Bearer eun_live_YOUR_TOKEN" \
-F 'invoice=@rechnung.json;type=application/json' \
-F 'pdf=@rechnung.pdf;type=application/pdf'
cURL — XML-Passthrough
curl -X POST https://eunormia.com/v1/convert \
-H "Authorization: Bearer eun_live_YOUR_TOKEN" \
-F 'xml=@factur-x.xml;type=application/xml' \
-F 'pdf=@rechnung.pdf;type=application/pdf'
cURL — XRechnung + KoSIT
curl -X POST https://eunormia.com/v1/convert \
-H "Authorization: Bearer eun_live_YOUR_TOKEN" \
-F 'invoice=@rechnung.json;type=application/json' \
-F 'options={"profile":"XRECHNUNG","kosit":true}'
Python (requests)
import requests, json, base64
invoice = {
"number": "RE-2026-0042", "issueDate": "2026-07-08", "dueDate": "2026-08-07",
"currency": "EUR",
"seller": {"name": "Muster GmbH", "street": "Musterstraße 1", "zip": "4020",
"city": "Linz", "country": "AT", "vatId": "ATU12345678"},
"buyer": {"name": "Beispiel GmbH", "street": "Beispielweg 2", "zip": "80331",
"city": "München", "country": "DE", "vatId": "DE123456789"},
"items": [{"name": "Leistung", "quantity": 1, "unit": "C62",
"unitPrice": 100.0, "vatPercent": 20}]
}
r = requests.post("https://eunormia.com/v1/convert",
headers={"Authorization": "Bearer eun_live_YOUR_TOKEN"},
files={"invoice": (None, json.dumps(invoice))})
r.raise_for_status()
data = r.json()
open(data["filename"], "wb").write(base64.b64decode(data["pdf"]))
print("Gate:", data["report"]["verapdf"]["result"], data["report"]["xml"]["result"])
PHP (cURL)
<?php
$invoice = json_encode([
"number" => "RE-2026-0042", "issueDate" => "2026-07-08", "dueDate" => "2026-08-07",
"currency" => "EUR",
"seller" => ["name"=>"Muster GmbH","street"=>"Musterstraße 1","zip"=>"4020",
"city"=>"Linz","country"=>"AT","vatId"=>"ATU12345678"],
"buyer" => ["name"=>"Beispiel GmbH","street"=>"Beispielweg 2","zip"=>"80331",
"city"=>"München","country"=>"DE","vatId"=>"DE123456789"],
"items" => [["name"=>"Leistung","quantity"=>1,"unit"=>"C62",
"unitPrice"=>100.0,"vatPercent"=>20]]
]);
$ch = curl_init("https://eunormia.com/v1/convert");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ["Authorization: Bearer eun_live_YOUR_TOKEN"],
CURLOPT_POSTFIELDS => ["invoice" => $invoice],
]);
$resp = json_decode(curl_exec($ch), true);
file_put_contents($resp["filename"], base64_decode($resp["pdf"]));
C# (HttpClient)
using System.Net.Http;
using System.Text.Json;
var invoice = File.ReadAllText("rechnung.json");
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer eun_live_YOUR_TOKEN");
var form = new MultipartFormDataContent { { new StringContent(invoice), "invoice" } };
var resp = await client.PostAsync("https://eunormia.com/v1/convert", form);
var doc = JsonDocument.Parse(await resp.Content.ReadAsStringAsync());
var pdf = Convert.FromBase64String(doc.RootElement.GetProperty("pdf").GetString());
File.WriteAllBytes(doc.RootElement.GetProperty("filename").GetString(), pdf);
Node.js (fetch)
import { readFileSync, writeFileSync } from "node:fs";
const form = new FormData();
form.append("invoice", readFileSync("rechnung.json", "utf8"));
const r = await fetch("https://eunormia.com/v1/convert", {
method: "POST",
headers: { Authorization: "Bearer eun_live_YOUR_TOKEN" },
body: form
});
const data = await r.json();
writeFileSync(data.filename, Buffer.from(data.pdf, "base64"));