Automation MCP Server Features Blog Pricing Contact

ZUGFeRD Creation API Reference

Technical reference for generating ZUGFeRD hybrid invoices from a structured JSON request. Submit seller, buyer and line items, totals and the tax breakdown are calculated automatically. The API returns a ZUGFeRD 2.3 PDF/A-3 with the embedded CII XML attached as factur-x.xml (the attachment name the ZUGFeRD 2.2+ specification prescribes), validated against the full EN 16931 rule set before delivery and ready for German B2B exchange.

Two ways to get a compliant PDF

Let InvoiceXML design the document from your data, or keep your own PDF layout and have us make it ZUGFeRD compliant. Either way you get back a valid PDF/A-3 with the structured XML embedded.

We generate the PDF

Send only your invoice data and the API renders a clean, branded ZUGFeRD PDF for you. Tune the look with options.brandColor and options.language.

Bring your own PDF

Already have a designed invoice PDF? Pass its public URL as options.pdfUrl and we embed the compliant ZUGFeRD XML into it, keeping your exact layout, fonts, and branding.

POST /v1/create/zugferd

Quickstart

A minimal request, copy, paste, get a compliant invoice back.

curl -X POST https://api.invoicexml.com/v1/create/zugferd \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -o invoice-zugferd.pdf \
  -d '{
  "invoice": {
    "invoiceNumber": "INV-2025-001",
    "issueDate": "2025-07-01",
    "currency": "EUR",
    "seller": {
      "name": "Acme GmbH",
      "vatIdentifier": "DE123456789",
      "legalRegistration": { "identifier": "HRB98765" },
      "postalAddress": {
        "line1": "Musterstr. 1",
        "city": "Berlin",
        "postCode": "10115",
        "country": "DE"
      }
    },
    "buyer": {
      "name": "Example Corp",
      "postalAddress": {
        "line1": "12 Rue de Rivoli",
        "city": "Paris",
        "postCode": "75001",
        "country": "FR"
      }
    },
    "paymentDetails": {
      "paymentAccountIdentifier": "DE89370400440532013000"
    },
    "lines": [
      {
        "quantity": 10,
        "priceDetails": { "netPrice": 150.00 },
        "vatInformation": { "rate": 19 },
        "item": { "name": "Consulting Services" }
      }
    ]
  },
  "options": {
    "language": "en",
    "brandColor": "#173a40"
  }
}'

That's the whole request, the API fills in the rest.

  • invoice.totals and invoice.vatBreakdowns are calculated from line items.
  • invoice.typeCode defaults to 380 (commercial invoice), specificationId is set per standard.
  • The options object is optional. Every field has a sensible default, see Options below.

Try it out online, no coding required

Fill in the form and download a compliant invoice instantly, right in your browser.

Try It Online

Request body

Send invoice data as application/json. The body has two top-level keys: invoice (required) and options (optional). Browse the fields below; toggle Required only for the minimal payload, or filter by name.

POST /v1/create/zugferd Request body
invoiceobjectrequired22 fields · 7 requiredThe invoice document. Holds all business terms and groups defined by EN 16931.
invoiceNumberstringrequiredBT-1Unique invoice identifier.
issueDatedaterequiredBT-2Date the invoice was issued, in YYYY-MM-DD format.
currencystringrequiredBT-5ISO 4217 currency code (e.g. EUR, USD, GBP).
buyerReferencestringoptionalBT-10Free-text reference used by the buyer's accounting system.
sellerobjectrequired10 fields · 2 requiredBG-4The party issuing the invoice.
namestringrequiredBT-27Legal business name.
vatIdentifierstringoptionalBT-31VAT identification number, including country prefix (e.g. DE123456789). At least one seller identifier (this, legalRegistration.identifier, or an identifiers[] entry) is required by EN 16931 BR-CO-26.
line1stringoptionalBT-35Street address, line 1.
citystringoptionalBT-37City name.
postCodestringoptionalBT-38Postal or ZIP code.
countrystringrequiredBT-40ISO 3166-1 alpha-2 country code (e.g. DE, FR).
line2stringoptionalBT-36Address line 2.
line3stringoptionalBT-162Address line 3.
countrySubdivisionstringoptionalBT-39Region or state (e.g. Bayern).
namestringoptionalBT-41Contact person's name.
phonestringoptionalBT-42Contact phone number.
emailstringoptionalBT-43Contact email address.
identifierstringoptionalBT-34Endpoint identifier (email, GLN, VAT number, etc.).
Allowed values
EMEmail address
9930Generic EU VAT registration number
0204German Leitweg-ID (routing identifier)
0088GS1 Global Location Number (GLN)
0184OpenPEPPOL participant identifier
9958German Umsatzsteuer-ID
0009French SIRET
0060Dun & Bradstreet (DUNS)
0190Dutch OIN
0192Norwegian Organisasjonsnummer
identifierstringoptionalBT-30Registration number (e.g. HRB98765). Required when legalRegistration is present.
schemeIdstringoptionalBT-30-1Scheme code for the registration number (e.g. 0002 SIRENE, 0007 Sweden Bolagsverket).
tradingNamestringoptionalBT-28Trading name, if different from the legal business name.
taxRegistrationIdentifierstringoptionalBT-32National tax registration ID, when distinct from the VAT ID.
additionalLegalInformationstringoptionalBT-33Free-text additional legal information (e.g. share capital, registration court).
identifierstringoptionalBT-29Identifier value. Required when an identifiers entry is included.
schemeIdstringoptionalBT-29-1Scheme code for the identifier (e.g. 0088 GLN, 0060 DUNS).
buyerobjectrequired8 fields · 2 requiredBG-7The party receiving the invoice.
namestringrequiredBT-44Legal business name.
vatIdentifierstringoptionalBT-48Buyer VAT ID. Required for EU cross-border and reverse-charge invoices.
line1stringoptionalBT-50Street address, line 1.
citystringoptionalBT-52City name.
postCodestringoptionalBT-53Postal or ZIP code.
countrystringrequiredBT-55ISO 3166-1 alpha-2 country code.
line2stringoptionalBT-51Address line 2.
line3stringoptionalBT-163Address line 3.
countrySubdivisionstringoptionalBT-54Region or state.
identifierstringoptionalBT-49Endpoint identifier.
schemeIdstringoptionalBT-49-1Peppol EAS scheme code. See the seller electronicAddress for the full code list.
tradingNamestringoptionalBT-45Trading name, if different from the legal name.
identifierstringoptionalBT-47Registration number. Required when legalRegistration is present.
schemeIdstringoptionalBT-47-1Scheme code for the registration number.
identifierstringoptionalBT-46Identifier value.
schemeIdstringoptionalBT-46-1Scheme code for the identifier.
namestringoptionalBT-56Contact person's name.
phonestringoptionalBT-57Contact phone number.
emailstringoptionalBT-58Contact email address.
paymentDetailsobjectrequired8 fields · 1 requiredBG-16Payment instructions for the buyer. Defaults to a SEPA credit transfer.
paymentAccountIdentifierstringrequiredBT-84IBAN or other account identifier (e.g. DE89370400440532013000).
Allowed values
30Credit transfer (default)
58SEPA credit transfer
59SEPA direct debit
54Card payment
48Bank card
10Cash
paymentMeansTextstringoptionalBT-82Free-text description of the payment means.
remittanceInformationstringoptionalBT-83Remittance reference shown on the bank transfer.
paymentAccountNamestringoptionalBT-85Account holder name.
bicstringoptionalBT-86BIC / SWIFT code.
mandateReferencestringoptionalBT-89SEPA direct debit mandate reference.
paymentTermsstringoptionalBT-20Free-text payment terms (e.g. Net 30 days).
linesobject[]required14 fields · 4 requiredBG-25Invoice line items. At least one line is required (rule BR-16). Each line is independently VAT-categorised.
quantitydecimalrequiredBT-129Invoiced quantity. Negative values are allowed, e.g. a returned item or a credit note line.
namestringrequiredBT-153Item name shown on the invoice.
descriptionstringoptionalBT-154Longer item description (e.g. a components list).
sellerIdentifierstringoptionalBT-155Item identifier in the seller's catalogue.
buyerIdentifierstringoptionalBT-156Item identifier in the buyer's catalogue.
countryOfOriginstringoptionalBT-159ISO 3166-1 alpha-2 country code.
identifierstringoptionalBT-157Identifier value (e.g. a GTIN).
schemeIdstringoptionalBT-157-1Scheme code (e.g. 0160 for GTIN).
identifierstringoptionalBT-158Classification code value.
schemeIdstringoptionalBT-158-1Classification scheme (e.g. TST).
schemeVersionstringoptionalBT-158-2Scheme version.
netPricedecimalrequiredBT-146Net unit price, excluding VAT.
discountAmountdecimaloptionalBT-147Discount applied to the unit price.
grossPricedecimaloptionalBT-148Unit price before discount.
priceBaseQuantitydecimaloptionalBT-149Quantity the unit price refers to (e.g. price per 100 units). Defaults to 1.
priceBaseUnitstringoptionalBT-150Unit code for the base quantity (UN/ECE Rec 20).
ratedecimalrequiredBT-152VAT rate as a percentage (e.g. 19 for 19%, 0 for zero-rated).
Allowed values
SStandard rated
ZZero rated
EExempt from VAT
AEReverse charge
KIntra-Community supply (EU)
GExport outside the EU
ONot subject to VAT
lineIdstringoptionalBT-126Line identifier. Auto-generated as 1, 2, … when omitted.
lineNotestringoptionalBT-127Free-text note shown on the invoice line.
Allowed values
C62Piece (default)
HURHour
DAYDay
KGMKilogram
MTRMetre
MTKSquare metre
LTRLitre
lineNetAmountdecimaloptionalBT-131Line total before VAT. Auto-calculated when omitted as quantity × priceDetails.netPrice, plus any line charges and minus any line allowances.
buyerOrderLineReferencestringoptionalBT-132Buyer purchase order line reference.
lineBuyerAccountingReferencestringoptionalBT-133Buyer's accounting cost-centre reference for this line.
identifierstringoptionalBT-128Identifier value.
schemeIdstringoptionalBT-128-1Scheme code for the identifier.
startDatedateoptionalBT-134Line period start date, YYYY-MM-DD.
endDatedateoptionalBT-135Line period end date, YYYY-MM-DD.
amountdecimaloptionalBT-136Allowance amount. Required when an allowances entry is included.
baseAmountdecimaloptionalBT-137Base amount the percentage is calculated from.
percentagedecimaloptionalBT-138Allowance as a percentage of the base amount.
reasonstringoptionalBT-139Free-text reason for the allowance.
reasonCodestringoptionalBT-140UNTDID 5189 allowance reason code.
amountdecimaloptionalBT-141Charge amount. Required when a charges entry is included.
baseAmountdecimaloptionalBT-142Base amount the percentage is calculated from.
percentagedecimaloptionalBT-143Charge as a percentage of the base amount.
reasonstringoptionalBT-144Free-text reason for the charge.
reasonCodestringoptionalBT-145UNTDID 7161 charge reason code.
paidAmountdecimaloptionalBT-113Amount already paid, e.g. a deposit, down payment or prepaid amount. Carries no VAT and is subtracted from the grand total to give the amount due. A deposit belongs here, not in the lines.
roundingAmountdecimaloptionalBT-114Rounding adjustment added to the grand total when computing the amount due.
sumOfLineNetAmountsdecimaloptionalBT-106Sum of all line net amounts.
sumOfAllowancesdecimaloptionalBT-107Sum of document-level allowances.
sumOfChargesdecimaloptionalBT-108Sum of document-level charges.
taxBasisTotalAmountdecimaloptionalBT-109Total without VAT: line nets minus allowances plus charges.
taxTotalAmountdecimaloptionalBT-110Total VAT amount across all breakdowns.
taxTotalAmountInAccountingCurrencydecimaloptionalBT-111Total VAT in the accounting currency, when taxCurrency differs from currency.
grandTotalAmountdecimaloptionalBT-112Total with VAT: tax basis plus total VAT.
duePayableAmountdecimaloptionalBT-115Amount due: grand total minus paidAmount plus roundingAmount.
taxableAmountdecimaloptionalBT-116Net amount taxed at this category and rate.
taxAmountdecimaloptionalBT-117VAT charged on the taxable amount.
Allowed values
SStandard rated
ZZero rated
EExempt from VAT
AEReverse charge
KIntra-Community supply (EU)
GExport outside the EU
ONot subject to VAT
ratedecimaloptionalBT-119VAT rate as a percentage.
exemptionReasonTextstringoptionalBT-120Reason the amount is exempt or zero-rated. Auto-filled for non-standard categories.
exemptionReasonCodestringoptionalBT-121Coded exemption reason (e.g. VATEX-EU-AE). Auto-resolved from the category.
dueDatedateoptionalBT-9Payment due date, YYYY-MM-DD. Defaults to issue date + 30 days.
Allowed values
380Commercial invoice (default)
381Credit note
384Corrected invoice
389Self-billed invoice
875Partial construction invoice
876Partial final construction invoice
specificationIdstringoptionalBT-24EN 16931 specification identifier. Auto-set per standard, override only if you know what you are doing.
taxCurrencystringoptionalBT-6VAT accounting currency, if different from currency.
businessProcessTypestringoptionalBT-23Business process identifier (e.g. urn:fdc:peppol.eu:2017:poacc:billing:01:1.0).
purchaseOrderReferencestringoptionalBT-13Buyer purchase order reference.
notesstring[]optionalBT-22Free-text invoice notes. 0..n entries.
startDatedateoptionalBT-73Period start date, YYYY-MM-DD.
endDatedateoptionalBT-74Period end date, YYYY-MM-DD.
referencestringoptionalBT-25Preceding invoice number. Required when an entry is included.
issueDatedateoptionalBT-26Issue date of the preceding invoice, YYYY-MM-DD.
amountdecimaloptionalBT-92Allowance amount. Required when an allowances entry is included.
Allowed values
SStandard rated
ZZero rated
EExempt from VAT
AEReverse charge
KIntra-Community supply (EU)
GExport outside the EU
ONot subject to VAT
vatRatedecimaloptionalBT-96VAT rate as a percentage (e.g. 19). Required when the category is S.
baseAmountdecimaloptionalBT-93Base amount the percentage is calculated from.
percentagedecimaloptionalBT-94Allowance as a percentage of the base amount.
reasonstringoptionalBT-97Free-text reason for the allowance.
reasonCodestringoptionalBT-98UNTDID 5189 allowance reason code.
amountdecimaloptionalBT-99Charge amount. Required when a charges entry is included.
Allowed values
SStandard rated
ZZero rated
EExempt from VAT
AEReverse charge
KIntra-Community supply (EU)
GExport outside the EU
ONot subject to VAT
vatRatedecimaloptionalBT-103VAT rate as a percentage (e.g. 19). Required when the category is S. Usually matches the rate of the goods being shipped.
baseAmountdecimaloptionalBT-100Base amount the percentage is calculated from.
percentagedecimaloptionalBT-101Charge as a percentage of the base amount.
reasonstringoptionalBT-104Free-text reason for the charge, e.g. Shipping. Shown as the line label on the PDF.
reasonCodestringoptionalBT-105UNTDID 7161 charge reason code (e.g. FC for freight).
receiverNamestringoptionalBT-70Deliver-to party name.
locationIdentifierstringoptionalBT-71Deliver-to location identifier (e.g. GLN).
actualDeliveryDatedateoptionalBT-72Actual delivery date, YYYY-MM-DD.
line1stringoptionalBT-75Street address, line 1.
citystringoptionalBT-77City name.
postCodestringoptionalBT-78Postal or ZIP code.
countrystringoptionalBT-80ISO 3166-1 alpha-2 country code.
line2stringoptionalBT-76Address line 2.
line3stringoptionalBT-165Address line 3.
countrySubdivisionstringoptionalBT-79Region or state.
optionsobjectoptional3 fieldsBehaviour switches that change how the output is built. Every field has a sensible default, so the whole object is optional.
Allowed values
enEnglish
deGerman
frFrench
brandColorstringoptionalPrimary brand colour applied to PDF headings, table headers, totals box and section accents. 6-digit hex (e.g. #0F766E). Falls back to the default theme when omitted.
pdfUrlstringoptionalPublic URL of a PDF to use as the visual layer of the hybrid invoice. When set, the API downloads it and embeds the generated XML into it instead of rendering the built-in template, so language and brandColor no longer apply. Must be a publicly reachable absolute http/https URL pointing at a PDF no larger than 20 MB.

Headers

Header Value
Authorization * Bearer YOUR_API_KEY
Content-Type application/json

Response

200 Generated PDF

The invoice was generated. The response body is the PDF, returned as a binary download.

Content-Type: application/pdf

400 Model validation error

One or more request fields are missing or invalid, so generation never started.

{
  "type": "https://tools.ietf.org/html/rfc9110#section-15.5.1",
  "title": "One or more validation errors occurred.",
  "status": 400,
  "errorCode": 4002,
  "valid": false,
  "detail": "The request failed validation with 1 error(s).",
  "errors": [
    {
      "rule": null,
      "line": null,
      "message": "The Name field is required.",
      "btCodes": ["BT-27"],
      "fields": ["seller.name"],
      "raw": null
    }
  ],
  "warnings": []
}

400 Schematron validation error

The request was well-formed, but the generated invoice failed EN 16931 Schematron business rules.

{
  "type": "https://tools.ietf.org/html/rfc9110#section-15.5.1",
  "title": "XML Validation Failed",
  "status": 400,
  "detail": "The generated invoice contains 2 validation error(s).",
  "errors": [
    {
      "rule": "BR-CO-15",
      "line": null,
      "message": "The invoice total with VAT does not match. Expected 1500.00 + 285.00 = 1785.00.",
      "btCodes": ["BT-112"],
      "fields": ["totals.grandTotalAmount"],
      "raw": "[BR-CO-15] EN16931: Invoice total amount with VAT = 1785.00 expected 1500.00 + 285.00. (at /*:CrossIndustryInvoice/*:SupplyChainTradeTransaction/*:ApplicableHeaderTradeSettlement)"
    },
    {
      "rule": "BR-S-08",
      "line": null,
      "message": "The VAT breakdown for Standard rate must have a positive taxable amount and the correct rate. Check the tax breakdown.",
      "btCodes": ["BT-116", "BT-117"],
      "fields": ["taxBreakdown[0].taxableAmount"],
      "raw": "[BR-S-08] EN16931: VAT category tax amount must equal category basis × rate. (at /*:CrossIndustryInvoice/*:SupplyChainTradeTransaction/*:ApplicableHeaderTradeSettlement/*:ApplicableTradeTax)"
    }
  ],
  "warnings": [
    {
      "rule": "BR-CL-25",
      "line": null,
      "message": "The seller country code should be a valid ISO 3166-1 alpha-2 value.",
      "btCodes": ["BT-40"],
      "fields": ["seller.postalAddress.country"],
      "raw": "[BR-CL-25] EN16931: Country codes should follow ISO 3166-1 alpha-2. (at /*:CrossIndustryInvoice/*:SupplyChainTradeTransaction/*:ApplicableHeaderTradeAgreement/*:SellerTradeParty)"
    }
  ],
  "traceId": "00-54efc3135dd95c21098f45b67ae2b5ab-c894e992bbcccfd7-00",
  "errorCode": 4001
}

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 is a flat array of finding objects, each with rule, line, message, btCodes, fields, and raw. A parallel warnings array carries non-blocking advisory findings of the same shape. errors[]  warnings[]
4002 Model validation, one or more request fields are missing or invalid. Returned as the same flat errors array of finding objects as 4001, with fields pointing at the offending input. errors[]
4011 Remote fetch error, returned only when options.pdfUrl is set. The supplied URL could not be fetched: it is not a valid http/https URL, resolves to a blocked or private address, or the host was unreachable. A resource whose content is not a PDF is rejected as 4004 instead. none
4000 General error, check detail for more information. none

Useful resources

Companion material for integrating against the API.

Frequently Asked Questions

What ZUGFeRD version and profile are generated?

ZUGFeRD 2.3 with the EN 16931 (Comfort) profile. The PDF carries ZUGFeRD-branded XMP metadata, and the embedded CII XML is attached as factur-x.xml, which is the attachment name the ZUGFeRD specification prescribes since version 2.2 (zugferd-invoice.xml is the legacy 1.0/2.0 name). The XML declares urn:cen.eu:en16931:2017 and is validated against exactly that rule set before delivery.

Is the request format the same as /create/facturx?

Yes. ZUGFeRD 2.x and Factur-X are technically the same standard, share the same EN 16931 invoice document model, and accept identical JSON payloads. The differences are in the wrapper: the ZUGFeRD route brands the PDF's XMP metadata as ZUGFeRD and names the output file invoice-zugferd.pdf.

Can I use this for the German B2G mandate?

For German B2G (federal and state authorities), XRechnung as standalone XML is typically required via the ZRE/OZG-RE portals; use POST /v1/create/xrechnung for that. ZUGFeRD is the B2B workhorse: e-invoice reception has been mandatory in Germany since January 2025, and issuance phases in from 2027, with ZUGFeRD profiles EN 16931 and above qualifying as e-invoices.

Can I use my own PDF as the visual layer?

Yes. Set options.pdfUrl to an absolute http(s) URL and the API downloads your PDF (with size, content-type and SSRF protections) and embeds the generated XML into it. Without pdfUrl, the API renders its own template, localized via options.language (en, de, fr) and branded via options.brandColor (hex #RRGGBB); those two options are ignored when pdfUrl is set.

Do I need to calculate totals myself?

No. The entire invoice.totals object and the invoice.vatBreakdowns array are auto-calculated from your line items when omitted. You can still provide them explicitly to override, the API validates the result against EN 16931 arithmetic rules before delivery.

How are tax categories handled?

Each line item carries a vatInformation.categoryCode (S = standard VAT, AE = reverse charge, E = exempt, G = export, K = intra-community, Z = zero rated, O = not subject). The API groups lines by category and rate to compute the EN 16931 compliant invoice.vatBreakdowns automatically. Exemption reason codes are auto-resolved from the category.

Why is the request a JSON body and not multipart/form-data?

The /create endpoints accept a nested JSON document modelled directly on the EN 16931 semantic model (business terms and groups). This keeps deep structures like postal addresses, line price details, and VAT information clean to express, and matches what most modern HTTP clients expect. Set Content-Type: application/json.