ZUGFeRD 2.x / Factur-X

ZUGFeRD API. JSON in, PDF with XML out.

ZUGFeRD 2.x / Factur-X is a regular PDF/A-3 with the invoice as CII inside it. People open the PDF; machines read the XML. Same JSON payload as the XRechnung API, different format.

For product teams that have to send B2B recipients a PDF and still meet the mandate. Not MINIMUM, not BASIC-WL.

Get API keyValidate XRechnung, no key

JSON → PDF/A-3 with factur-x.xml

POST https://api.normbill.com/v1/invoices/generate with format: "zugferd-2.x" or "facturx-1.0". Response: xml plus pdf (base64). Paid plans. Same invoice JSON as the XRechnung API.

curl https://api.normbill.com/v1/invoices/generate \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{ "format": "zugferd-2.x", "invoice": {
    "number": "INV-2026-0001",
    "issue_date": "2026-06-15",
    "due_date": "2026-07-15",
    "buyer_reference": "04011000-1234512345-06",
    "seller": {
      "name": "Muster Lieferant GmbH", "vat_id": "DE123456789",
      "address": { "country": "DE", "city": "Berlin",
                   "postal_code": "10115" },
      "contact": { "name": "Billing", "phone": "+49 30 1234567",
                   "email": "billing@lieferant.example" }
    },
    "buyer": {
      "name": "Beispiel Kunde AG",
      "address": { "country": "DE", "city": "Hamburg",
                   "postal_code": "20095" },
      "contact": { "email": "ap@kunde.example" }
    },
    "payment": { "iban": "DE89370400440532013000" },
    "lines": [{ "name": "Beratungsleistung", "qty": 10,
                "unit_price": 100, "vat": 19 }]
  } }'

A successful response (HTTP 200):

{
  "format": "zugferd-2.x",
  "profile": "ZUGFeRD 2.x (EN 16931, CII D16B)",
  "xml": "<?xml version=\"1.0\" encoding=\"UTF-8\"?><rsm:CrossIndustryInvoice …",
  "pdf": "JVBERi0xLjQK…",
  "validation": {
    "valid": true,
    "tier": "structural",
    "counts": { "errors": 0, "warnings": 0 },
    "issues": []
  }
}

Playground · Docs

Which profile meets the mandate

EN 16931 profile: BASIC, EN 16931 or EXTENDED. MINIMUM and BASIC-WL are not a complete dataset — they do not meet the mandate. BMF circular of 15 Oct 2024: older ZUGFeRD 1.0 / 2.0 before 2.0.1 do not count.

Embed your own PDF vs render

The API renders the hybrid PDF. If you already have a corporate PDF, the report still tells you whether the embedded XML survives the structural rules — POST /v1/invoices/validate or the validator, no key.

Factur-X = ZUGFeRD for FR

Technically aligned. France starts Sep 2026. Generation: yes. We are not a PDP/PA — transport and clearance stay with you.

XRechnung vs ZUGFeRD

B2G and Leitweg-ID: XRechnung API. B2B, recipient wants a PDF: ZUGFeRD. One JSON, two format values. The comparison: XRechnung vs ZUGFeRD.

PHP and TypeScript clients

composer require normbill/xrechnung
npm i @normbill/xrechnung

Composer client: XRechnung PHP. MCP: @normbill/mcp. Generate, Validate, Parse. The same surface as REST.

Pricing with no sales call

ZUGFeRD / Factur-X is a paid feature. Paid from €19. 30-day guarantee. Design partners: 12 months of Growth. The free plan generates XRechnung, not a hybrid PDF.

Pricing · Design partners

FAQ

Which ZUGFeRD profile meets the mandate?

EN 16931 (BASIC, EN 16931, EXTENDED). MINIMUM and BASIC-WL do not. ZUGFeRD 1.0 and 2.0 before 2.0.1 do not count under the BMF circular of 15 Oct 2024.

Factur-X or ZUGFeRD?

Same technique, different name. zugferd-2.x or facturx-1.0. France starts Sep 2026; we are not a PDP/PA.

Do you store the PDF?

No. Neither XML nor PDF. Storage, EU, DPA (AVV).

Does the free plan include ZUGFeRD?

No. Hybrid PDF is paid from €19. Free generates XRechnung (KoSIT), without a PDF.

Spotted something?

Bug, missing feature, wrong validation result — tell us. The page you're on is attached automatically; email optional.