ZUGFeRD XML Embedding API for your own PDFs
You already render a beautiful invoice PDF, and you already generate compliant CII XML. The missing piece is the container: this endpoint promotes your PDF to PDF/A-3, attaches the XML as factur-x.xml, and writes the ZUGFeRD XMP metadata. Your layout, fonts, and branding are never touched.
The alternative is wiring up iText, PDFBox, or pdflib, learning PDF/A-3 output intents, AFRelationship entries, and XMP extension schemas, and owning that code forever. Here it is one multipart request with two files in and one compliant hybrid out.
curl -X POST https://api.invoicexml.com/v1/embed/zugferd \ -H "Authorization: Bearer YOUR_API_KEY" \ -F "[email protected]" \ -F "[email protected]" \ -o invoice-zugferd.pdf
// Binary PDF/A-3 response: ✓ Your visual layer, unchanged ✓ factur-x.xml attachment (your CII) ✓ ZUGFeRD XMP metadata (zf: namespace) ✓ Profile read from your XML ✓ PDF/A-3 archival conformance
Embed your XML into a ZUGFeRD PDF/A-3 now
This demo calls the same POST /v1/embed/zugferd endpoint your integration will use. Drop your invoice PDF and your CII XML, and the finished ZUGFeRD hybrid downloads immediately.
The container work, done for you
A valid ZUGFeRD file is more than a PDF with an attachment. Three container-level requirements have to be exactly right, and they are the part teams usually get wrong when hand-rolling with a PDF library.
PDF/A-3 promotion
Any standard PDF is accepted and promoted to PDF/A-3 in place: output intent, XMP conformance metadata, and the document structure ISO 19005-3 requires are added while the visual content is preserved exactly as uploaded.
Spec-conformant attachment
Your CII XML is embedded under the converged filename factur-x.xml with the correct MIME type and AFRelationship, the details ZUGFeRD readers actually check before they even parse the invoice data.
Honest XMP branding
The zf: extension schema and urn:zugferd conformance URN are written into the XMP, with the profile level read from your XML's guideline parameter. The container never advertises a conformance level the payload does not declare.
Embed, create, or convert: pick the right endpoint
Three InvoiceXML endpoints produce ZUGFeRD hybrids. They differ in what you bring and what stays under your control.
/v1/embed/zugferd
You bring: PDF + CII XML
This page. Your rendered PDF stays pixel-identical; the API only builds the compliant container around it. Right choice when the visual invoice is produced by your ERP, template engine, or design team.
/v1/create/zugferd
You bring: invoice JSON
The API generates everything: the XML from your structured data and a clean visual layer to match. Right choice when you have invoice data but no PDF yet. Create ZUGFeRD →
/v1/transform/to/zugferd
You bring: a plain PDF
AI extracts the invoice data from an ordinary PDF and produces the hybrid. Right choice when you have no structured data at all. PDF to ZUGFeRD →
Two files in, one hybrid out
Send both files as multipart/form-data fields named pdf and xml. The response body is the binary ZUGFeRD PDF/A-3.
$ curl -X POST https://api.invoicexml.com/v1/embed/zugferd \ -H "Authorization: Bearer YOUR_API_KEY" \ -F "[email protected]" \ -F "[email protected]" \ -o invoice-zugferd.pdf
A UBL file in the xml field returns a clear 400 (convert it first with /v1/convert/ubl/to/cii). Need Factur-X branding for French recipients? Use the Factur-X embedding endpoint.
Complete ZUGFeRD Toolkit
Everything you need to create, convert, validate, and extract ZUGFeRD invoices, via REST API or online.
Frequently Asked Questions
How is this different from generating the invoice with /v1/create?
/v1/create/zugferd builds the whole hybrid from a JSON document, including rendering the visual layer. This endpoint is for the opposite situation: your accounting system, template engine, or designer already produces the exact PDF you want to send. You keep that PDF untouched, supply the CII XML separately, and the API only does the container work: PDF/A-3 promotion, attachment, and XMP metadata.
Do I really need PDF/A-3 to attach the XML?
Yes. ZUGFeRD builds on ISO 19005-3 (PDF/A-3), the first PDF/A revision that permits embedded files of arbitrary type. A plain PDF with a file attachment is not a valid ZUGFeRD invoice; readers check the PDF/A-3 conformance metadata and the AFRelationship of the attachment. The API handles that promotion in place, adding the output intent, metadata, and document structure archival conformance requires.
Why is the attachment called factur-x.xml and not zugferd-invoice.xml?
Since ZUGFeRD 2.1.1, the German and French standards converged on the shared attachment name factur-x.xml (zugferd-invoice.xml is the legacy 1.0/2.0 name). What distinguishes a ZUGFeRD file from a Factur-X file today is the XMP branding: this endpoint writes the zf: namespace and urn:zugferd conformance URN that German readers expect.
Which ZUGFeRD profile is written into the metadata?
The one your XML actually declares. The API reads the GuidelineSpecifiedDocumentContextParameter from your CII document and advertises that conformance level (Minimum, Basic WL, Basic, EN 16931 / Comfort, or Extended) in the XMP, so the container never claims a profile the payload does not have.
Is my XML validated against EN 16931 during embedding?
No, only shape-checked: the root element must be a CII CrossIndustryInvoice. That is deliberate, so you can embed EXTENDED-profile or edge-case documents without a rule engine interfering. For a full Schematron pass, call POST /v1/validate/cii on the XML before embedding, or POST /v1/validate/zugferd on the finished PDF after.
My invoice data is UBL, not CII. Can I still use this?
Convert it first with POST /v1/convert/ubl/to/cii, then embed the result. ZUGFeRD requires the embedded XML to be CII syntax; a UBL file is rejected with a clear 400 error rather than producing a non-compliant hybrid.
Ready to automate your invoices?
Validate, convert and embed compliant e-invoices through one API. Start your 30-day free trial. No credit card required.