Create ZUGFeRD Invoice using REST-API
Generate a complete ZUGFeRD 2.x PDF/A-3 invoice from structured form data. Submit seller and buyer details, line items, and totals — the API produces a valid ZUGFeRD PDF with embedded zugferd-invoice.xml, ready for the German e-invoicing mandate and B2B exchange across Europe.
/v1/create/zugferd
Request
Submit invoice data as multipart/form-data.
All monetary values use decimal format (e.g. 1234.56).
Invoice Header
| Field | Type | Description |
|---|---|---|
| InvoiceNumber * | string | Unique invoice identifier (e.g. INV-2025-001). |
| IssueDate * | string | Issue date in YYYY-MM-DD format. |
| PaymentDueDate | string | Payment due date in YYYY-MM-DD format. |
| Currency * | string | ISO 4217 currency code (e.g. EUR, USD). |
Seller & Buyer
Both parties share the same field structure. Replace Seller with Buyer for the buyer fields.
| Field | Type | Description |
|---|---|---|
| SellerName * | string | Legal business name. |
| SellerLegalId | string | Legal registration number (e.g. SIRET, HRB). |
| SellerTaxId * | string | VAT identification number (e.g. DE123456789). |
| SellerStreet * | string | Street address. |
| SellerPostcode * | string | Postal code. |
| SellerCity * | string | City name. |
| SellerCountry * | string | ISO 3166-1 alpha-2 country code (e.g. DE, FR). |
Line Items
Submit one or more line items using indexed field names: Lines[0].Description, Lines[1].Description, etc.
| Field | Type | Description |
|---|---|---|
| Lines[n].Description * | string | Description of the goods or service. |
| Lines[n].Quantity * | decimal | Quantity of items. |
| Lines[n].UnitPrice * | decimal | Price per unit (net, excluding VAT). |
| Lines[n].LineTotal | decimal | Line net total. Auto-calculated from Quantity × UnitPrice if omitted. |
| Lines[n].UnitCode | string | UN/ECE Rec 20 unit code. Default: C62 (piece). Common: HUR (hour), DAY. |
| Lines[n].TaxPercentage * | decimal | VAT rate for this line (e.g. 19, 20). |
| Lines[n].TaxCategoryCode * | string | VAT category: S (standard), AE (reverse charge), E (exempt), G (export). |
Totals & Payment
| Field | Type | Description |
|---|---|---|
| LineTotalAmount * | decimal | Sum of all line net totals. |
| TaxTotalAmount * | decimal | Total VAT amount. |
| GrandTotalAmount * | decimal | Total payable amount (net + tax). |
| PaymentMeansCode | string | UNTDID 4461 code: 30 (credit transfer), 49 (SEPA DD), 54 (card). |
| IBAN | string | Seller bank account IBAN. |
| BIC | string | Seller bank BIC/SWIFT code. |
Headers
| Header | Value |
|---|---|
| Authorization * | Bearer YOUR_API_KEY |
| Content-Type | multipart/form-data |
Response
{
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.1",
"title": "Model Validation Failed",
"status": 400,
"errorCode": 4002,
"detail": "One or more fields are invalid.",
"errors": {
"SellerName": ["Seller name is required."],
"Lines[0].Description": ["Line item description is required."]
}
}
{
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.1",
"title": "XML Validation Failed",
"status": 400,
"errorCode": 4001,
"detail": "The generated invoice contains 2 validation error(s).",
"errors": {
"xml": [
"[BR-CO-15] Invoice total amount with VAT = 1785.00 expected 1500.00 + 285.00.",
"[BR-S-08] VAT category tax amount must equal category basis × rate."
]
}
}
Error Reference
Errors are returned as RFC 7807 ProblemDetails. The errorCode field indicates the error category.
| errorCode | Meaning | errors key |
|---|---|---|
| 4001 | XML validation — the generated XML violates EN 16931 Schematron rules. | errors.xml[] |
| 4002 | Model validation — one or more request fields are missing or invalid. | errors.{FieldName}[] |
| 4000 | General error — check detail for more information. |
— |
Code Example
curl -X POST https://api.invoicexml.com/v1/create/zugferd \ -H "Authorization: Bearer YOUR_API_KEY" \ -F "InvoiceNumber=INV-2025-001" \ -F "IssueDate=2025-07-01" \ -F "Currency=EUR" \ -F "SellerName=Acme GmbH" \ -F "SellerTaxId=DE123456789" \ -F "SellerStreet=Musterstr. 1" \ -F "SellerPostcode=10115" \ -F "SellerCity=Berlin" \ -F "SellerCountry=DE" \ -F "BuyerName=Example Corp" \ -F "BuyerTaxId=FR87654321012" \ -F "BuyerStreet=12 Rue de Rivoli" \ -F "BuyerPostcode=75001" \ -F "BuyerCity=Paris" \ -F "BuyerCountry=FR" \ -F "Lines[0].Description=Consulting Services" \ -F "Lines[0].Quantity=10" \ -F "Lines[0].UnitPrice=150.00" \ -F "Lines[0].UnitCode=HUR" \ -F "Lines[0].TaxPercentage=19" \ -F "Lines[0].TaxCategoryCode=S" \ -F "LineTotalAmount=1500.00" \ -F "TaxTotalAmount=285.00" \ -F "GrandTotalAmount=1785.00" \ -o invoice-zugferd.pdf
Frequently Asked Questions
What ZUGFeRD version is generated?
The API generates ZUGFeRD 2.3 invoices, the latest version aligned with EN 16931. This version is future-proof for the German e-invoicing mandate (Wachstumschancengesetz) taking effect from 2025.
Is the request format the same as /create/facturx?
Yes. Factur-X and ZUGFeRD use the same CII-based data model and accept identical request fields. The only difference is the branding of the embedded XML attachment (zugferd-invoice.xml vs factur-x.xml) and profile naming.
Can I use this for the German B2G mandate?
For German B2G (federal and state authorities), XRechnung in standalone XML is typically required via the ZRE/OZG-RE portals. ZUGFeRD is ideal for B2B exchange between private companies and is one of the accepted formats under the 2025 German mandate.
How are tax categories handled?
Each line item includes a TaxCategoryCode (S = standard VAT, AE = reverse charge, E = exempt, G = zero-rated export). The API groups lines by category and rate to compute the EN 16931 compliant tax breakdown automatically.
What happens if my totals don't match?
The API validates all totals against EN 16931 arithmetic rules (e.g. BR-CO-10 through BR-CO-16). If LineTotalAmount + TaxTotalAmount ≠ GrandTotalAmount, you'll receive a 400 response with errorCode 4001 listing the specific violated rules.