What a ZUGFeRD file is
One file, two readers: people read the PDF page, accounting software reads the XML inside it.
ZUGFeRD is the German hybrid invoice format, maintained by the Forum elektronische Rechnung Deutschland (FeRD). The outside is a PDF/A-3 document that looks like any invoice. Inside it sits an XML file in the Cross Industry Invoice (CII) syntax. That XML holds every field of the invoice in the shape EN 16931 defines.
Since version 2.1, ZUGFeRD and the French Factur-X are the same standard. Both embed a file called factur-x.xml and describe it in the same PDF metadata. A German customer who asks for ZUGFeRD and a French one who asks for Factur-X can open the same file. CastPDF still lets you name the standard you mean, and the PDF metadata says which one it is.
- The PDF is PDF/A-3b: fonts embedded, colours defined, no encryption.
- The XML is attached as an associated file, with the relationship Alternative.
- The PDF metadata names the profile, so a reader knows what to expect.
- The page is rendered by Chromium, so your HTML and CSS look the way you designed them.
ZUGFeRD vs XRechnung
Both formats are valid e-invoices under the German rules from 2025. They carry the same EN 16931 data. The difference is what the file looks like and who expects it.
| ZUGFeRD | XRechnung | |
|---|---|---|
| The file | A PDF with the XML inside | The XML alone |
| Who usually asks for it | Businesses | Public buyers and their portals |
| Readable without software | Yes | No |
| Required extra fields | None beyond EN 16931 | Leitweg-ID, seller contact, electronic addresses |
| In CastPDF | "standard": "zugferd" | "standard": "xrechnung-cii" or "xrechnung-ubl" |
There is a middle way too. The ZUGFeRD profile XRECHNUNG embeds an XRechnung XML inside a readable PDF. Send "profile": "xrechnung" with "standard": "zugferd" to get one. Public portals still usually want the plain XML, which our XRechnung page covers.
One request for a ZUGFeRD PDF
You need no template. The built-in invoice template renders the page from the same data that fills the XML. Amounts can be numbers or decimal strings; strings rule out any doubt about decimals.
{
"e_invoice": {
"standard": "zugferd",
"profile": "en16931",
"invoice": {
"number": "RE-2026-0816",
"issue_date": "2026-10-11",
"currency": "EUR",
"seller": {
"name": "Lindqvist Software GmbH",
"vat_id": "DE123456789",
"tax_number": "37/123/45678",
"address": { "line1": "Kastanienallee 12", "city": "Berlin", "postal_code": "10435", "country_code": "DE" },
"contact": { "name": "Accounts", "email": "[email protected]" }
},
"buyer": {
"name": "Brightwater Kaffee GmbH",
"vat_id": "DE987654321",
"address": { "line1": "Speicherstadt 4", "city": "Hamburg", "postal_code": "20457", "country_code": "DE" }
},
"payment": { "iban": "DE89370400440532013000", "due_date": "2026-11-10", "terms": "Zahlbar innerhalb von 30 Tagen ohne Abzug." },
"lines": [
{ "name": "Support contract, October", "quantity": 1, "unit_code": "MON", "unit_price": "650.00", "vat": { "category": "S", "rate": 19 } },
{ "name": "On-site training", "quantity": 6, "unit_code": "HUR", "unit_price": "95.00", "vat": { "category": "S", "rate": 19 } }
]
}
},
"filename": "RE-2026-0816"
}curl https://api.castpdf.com/v1/pdf \
-H "Authorization: Bearer $CASTPDF_API_KEY" \
-H "Content-Type: application/json" \
-d @RE-2026-0816.json \
-o RE-2026-0816.pdfThe reply is the PDF, with the header x-e-invoice: zugferd/en16931. Ask for "response": "url" instead and you get a signed download link plus e_invoice.xml_filename in the JSON.
Who sends ZUGFeRD, and when
- SaaS and subscription businesses that bill German companies every month and want the invoice to land straight in the customer’s accounting tool.
- Agencies and consultancies whose clients started asking for e-invoices in 2025 and will require them by 2027 or 2028.
- Marketplaces and platforms that issue invoices on behalf of sellers and need one format both humans and machines accept.
The German mandate decides the timing. Since 2025 your customers must be able to receive e-invoices. From 2027, if your turnover was above EUR 800,000, you must send them; from 2028 everyone must. The e-invoicing overview has the full timeline.
The cases that trip up ZUGFeRD files
- A cent of difference. Per-line VAT rounding differs from EN 16931. We compute VAT once per rate, so validators agree with the totals.
- Mixed VAT rates. A 19 % service and a 7 % book on one invoice get one VAT line per rate in the XML and in the printed breakdown.
- Credit notes. Send
type_code381 and the original invoice number inpreceding_invoice. - Reverse charge. Use VAT category
AEwith the buyer’s VAT ID; the standard exemption text and code are added for you. - Long invoices. The invoice template repeats the table header on every page, and the XML carries every line.
If the data is incomplete or inconsistent, the API answers with invalid_e_invoice and lists every problem with its field. Nothing is rendered and nothing is counted until the invoice is right.