Issuing mandate in 94 days

XRechnung for your software — with one API call.

Send the invoice data you already have as JSON. You get back an XRechnung checked against the official KoSIT validator — or a plain-language note on what's missing and how to fix it. ZUGFeRD runs through the same API.

  • 50 documents/month free
  • No card, no call
  • 30-day validation guarantee

Integration help is optional and paid (€990 one-time, excl. VAT). See what's included → Self-service needs no call.

POST/v1/invoices/generateEdit the JSON ↓
StructureXSDAPIKoSITAPI200 OK

✓ validRE-2026-0042.xml · 3.9 kB · UBL 2.1

<?xml version="1.0" encoding="UTF-8"?>
<Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2" xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2" xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2">
  <cbc:CustomizationID>urn:cen.eu:en16931:2017#compliant#urn:xeinkauf.de:kosit:xrechnung_3.0</cbc:CustomizationID>
  <cbc:ProfileID>urn:fdc:peppol.eu:2017:poacc:billing:01:1.0</cbc:ProfileID>
  <cbc:ID>RE-2026-0042</cbc:ID>
  <cbc:IssueDate>2026-06-11</cbc:IssueDate>
  <cbc:DueDate>2026-07-11</cbc:DueDate>
  <cbc:InvoiceTypeCode>380</cbc:InvoiceTypeCode>
  <cbc:DocumentCurrencyCode>EUR</cbc:DocumentCurrencyCode>
  <cbc:BuyerReference>PO-2026-0117</cbc:BuyerReference>
  <cac:AccountingSupplierParty>
    <cac:Party>
      <cbc:EndpointID schemeID="EM">billing@acme.example</cbc:EndpointID>
      <cac:PostalAddress>
        <cbc:CityName>Berlin</cbc:CityName>
        <cbc:PostalZone>10115</cbc:PostalZone>
        <cac:Country>
          <cbc:IdentificationCode>DE</cbc:IdentificationCode>
        </cac:Country>
      </cac:PostalAddress>
      <cac:PartyTaxScheme>
        <cbc:CompanyID>DE123456789</cbc:CompanyID>
        <cac:TaxScheme>
          <cbc:ID>VAT</cbc:ID>
        </cac:TaxScheme>
      </cac:PartyTaxScheme>
      <cac:PartyLegalEntity>
        <cbc:RegistrationName>Acme GmbH</cbc:RegistrationName>
      </cac:PartyLegalEntity>
      <cac:Contact>
        <cbc:Name>Billing</cbc:Name>
        <cbc:Telephone>+49 30 1234567</cbc:Telephone>
        <cbc:ElectronicMail>billing@acme.example</cbc:ElectronicMail>
      </cac:Contact>
    </cac:Party>
  </cac:AccountingSupplierParty>
  <cac:AccountingCustomerParty>
    <cac:Party>
      <cbc:EndpointID schemeID="EM">ap@kunde.example</cbc:EndpointID>
      <cac:PostalAddress>
        <cbc:CityName>München</cbc:CityName>
        <cbc:PostalZone>80331</cbc:PostalZone>
        <cac:Country>
          <cbc:IdentificationCode>DE</cbc:IdentificationCode>
        </cac:Country>
      </cac:PostalAddress>
      <cac:PartyLegalEntity>
        <cbc:RegistrationName>Kunde AG</cbc:RegistrationName>
      </cac:PartyLegalEntity>
      <cac:Contact>
        <cbc:ElectronicMail>ap@kunde.example</cbc:ElectronicMail>
      </cac:Contact>
    </cac:Party>
  </cac:AccountingCustomerParty>
  <cac:PaymentMeans>
    <cbc:PaymentMeansCode>58</cbc:PaymentMeansCode>
    <cac:PayeeFinancialAccount>
      <cbc:ID>DE89370400440532013000</cbc:ID>
    </cac:PayeeFinancialAccount>
  </cac:PaymentMeans>
  <cac:TaxTotal>
    <cbc:TaxAmount currencyID="EUR">228.00</cbc:TaxAmount>
    <cac:TaxSubtotal>
      <cbc:TaxableAmount currencyID="EUR">1200.00</cbc:TaxableAmount>
      <cbc:TaxAmount currencyID="EUR">228.00</cbc:TaxAmount>
      <cac:TaxCategory>
        <cbc:ID>S</cbc:ID>
        <cbc:Percent>19</cbc:Percent>
        <cac:TaxScheme>
          <cbc:ID>VAT</cbc:ID>
        </cac:TaxScheme>
      </cac:TaxCategory>
    </cac:TaxSubtotal>
  </cac:TaxTotal>
  <cac:LegalMonetaryTotal>
    <cbc:LineExtensionAmount currencyID="EUR">1200.00</cbc:LineExtensionAmount>
    <cbc:TaxExclusiveAmount currencyID="EUR">1200.00</cbc:TaxExclusiveAmount>
    <cbc:TaxInclusiveAmount currencyID="EUR">1428.00</cbc:TaxInclusiveAmount>
    <cbc:PayableAmount currencyID="EUR">1428.00</cbc:PayableAmount>
  </cac:LegalMonetaryTotal>
  <cac:InvoiceLine>
    <cbc:ID>1</cbc:ID>
    <cbc:InvoicedQuantity unitCode="C62">10</cbc:InvoicedQuantity>
    <cbc:LineExtensionAmount currencyID="EUR">1200.00</cbc:LineExtensionAmount>
    <cac:Item>
      <cbc:Name>Consulting services</cbc:Name>
      <cac:ClassifiedTaxCategory>
        <cbc:ID>S</cbc:ID>
        <cbc:Percent>19</cbc:Percent>
        <cac:TaxScheme>
          <cbc:ID>VAT</cbc:ID>
        </cac:TaxScheme>
      </cac:ClassifiedTaxCategory>
    </cac:Item>
    <cac:Price>
      <cbc:PriceAmount currencyID="EUR">120</cbc:PriceAmount>
    </cac:Price>
  </cac:InvoiceLine>
</Invoice>
Runs in your browser — structural checks EN 16931 · XRechnung 3.0Open the full playground →
Built on the official standards
  • XRechnung 3.0
  • ZUGFeRD 2.x
  • Factur-X
  • Peppol BIS 3.0
  • EN 16931
  • UBL 2.1
  • UN/CEFACT CII
  • KoSIT validator 1.6.2
  • Leitweg-ID

Keep your invoicing workflow. Compliance on top.

No new workflow, no migration. Your software creates invoices the way it does today — normbill turns them into documents that meet the mandate.

  1. Step 1

    Send the JSON you have

    One POST from any language. The fields follow the business terms of EN 16931.

  2. Step 2

    Validated three times

    Every XRechnung passes the official KoSIT validator before you get it back.

  3. Step 3

    Deliver XML or PDF

    XRechnung for public authorities, ZUGFeRD for businesses — from the same data.

Errors you can actually fix.

Other validators hand you a rule code and an XPath. normbill shows the field in your JSON — and how to fix it. Never a silently invalid document.

The usual way[error] BR-DE-15 | severity=fatal cvc-complex-type.2.4.b: The content of element 'cac:PartyIdentification' is not complete… (line 47, col 28)
Validation report1 errorRE-2026-0045

BR-DE-15Error · XRechnung

Buyer reference (BT-10) is missing

XRechnung requires it. Public-sector buyers use their Leitweg-ID here.

In your requestinvoice.buyer_reference

Suggested fix

Set invoice.buyer_reference — Leitweg-ID format 04011000-1234512345-06

View rule

Your customers will ask before 2027.

Every German business must already be able to receive e-invoices. Issuing becomes mandatory in two steps — and your users expect your software to handle it.

94days until
1 Jan 2027

  1. Jan 2025Receiving mandatoryAll businesses
  2. Jan 2027Issuing mandatoryTurnover above €800,000
  3. Jan 2028Issuing mandatoryAll businesses
Simplified overview — not legal or tax advice.Get the 2027 checklist

Your first compliant invoice in five minutes.

Plain REST from any language, no SDK required. Or the typed clients — it's the same API.

curl https://api.normbill.com/v1/invoices/generate \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{ "format": "xrechnung-3.0", "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 }]
  } }'

200 OKINV-2026-0001.xmlXRechnung 3.0 · valid

Made in Germany. EU hosting. Nothing stored.

Security in detail
  • No storage

    Processed in memory and returned — never persisted, excluded from logs.

  • EU hosting, GDPR-compliant

    EU infrastructure, built and operated from Hannover.

  • AVV (DPA) included

    A data-processing agreement on every plan — nothing to negotiate.

  • Versions pinned

    KoSIT validator pinned to exact versions. New specifications arrive as their own format ID.

Start free. No sales call.

You pay only for documents you produce or parse. Validation, retries and failed calls are free. Prices excl. VAT.

  • Free

    €0

    50 documents / month · KoSIT validation · no card

    Start free
  • Solo

    €19/mo

    500 documents / month · ZUGFeRD PDF

    ≈ €0.038 per document

    + €0.06 per extra document¹

    Choose Solo
  • StarterMost popular

    €49/mo

    2,500 documents / month · ZUGFeRD PDF

    ≈ €0.02 per document

    + €0.04 per extra document¹

    Choose Starter
  • Growth

    €149/mo

    12,000 documents / month · priority support

    ≈ €0.012 per document

    + €0.02 per extra document¹

    Choose Growth
  • Platform

    €690/mo

    75,000 documents / month · dedicated support

    ≈ €0.009 per document

    + €0.012 per extra document¹

    Choose Platform

30-day validation guarantee. If an XRechnung we generate fails the official KoSIT validator, we fix it free — or refund the month.

Help with your first workflow? Integration Launch — optional, €990 one-time · Compare all plans

¹ Beyond your quota only while metered billing is active on your subscription, capped at 2× the plan fee; otherwise calls stop at the quota with a 429. All prices excl. VAT. German customers: +19% VAT at checkout. EU B2B with a valid VAT ID: reverse charge.

Questions developers actually ask.

Something missing? support@normbill.com — a human replies.

Is this compliant with the German E-Rechnungspflicht?

The output conforms to EN 16931, the European standard the German mandate is based on. XRechnung documents follow the current KoSIT specification and are validated against the official KoSIT Schematron before you get them back; ZUGFeRD output is valid Factur-X with structural EN 16931 checks. Compliance of the content (correct VAT treatment, mandatory references for your buyer) still depends on the data you send — which is exactly what the validation report tells you about.

XRechnung vs. ZUGFeRD — which one do I need?

XRechnung is pure XML — required for invoicing German public authorities (B2G) and common in B2B. ZUGFeRD / Factur-X is a normal PDF with the same structured XML embedded, so humans and machines both read it. Both satisfy the mandate; many teams send ZUGFeRD to businesses and XRechnung to government. The API generates either from the same JSON.

Do you store our invoice data?

No. Invoices are processed in memory and returned; nothing is persisted, and request bodies are excluded from our logs. EU-hosted infrastructure, GDPR-first — there is no retention setting to configure because there is nothing retained.

Can I validate invoices I generated somewhere else?

Yes — POST XRechnung (UBL or CII) to /v1/invoices/validate for authoritative KoSIT validation; ZUGFeRD / Factur-X CII is checked at the structural EN 16931 tier today. Either way you get a machine-readable report: every failed rule with its ID, severity, a plain-language message and a suggested fix. Or try the free validator with no key. Validation is free within a generous fair-use allowance — five times your plan's monthly document quota — and never counts against your billable documents.

We're a SaaS that issues invoices for our users — can we embed this?

That's the core use case. One API key, and a free-form metadata object on every invoice for your own per-tenant correlation. The API responds synchronously — your users never see normbill, they just get compliant invoices out of your product. At platform volume, the Platform tier adds dedicated support, an EU data-residency guarantee and pay-by-invoice billing on request (SEPA, net-30).

Can you deliver invoices over Peppol?

The API generates Peppol BIS Billing 3.0 UBL today, so your documents are network-ready. Transmission over the Peppol network (via a certified access point) is on the roadmap — generation and validation come first, because that's the part every team needs on day one.

What happens when validation fails?

You get a 422 with field-level errors: the rule that fired, the path in your JSON that caused it, a plain-language message, and a suggested fix. The API never silently returns an invalid document.

What happens when I run out of quota?

Only successful documents count against your quota — failed attempts cost nothing, and validation has its own generous free allowance. The quota runs with your billing period; on annual plans twelve months' worth of documents pool across the contract year. From 80% usage every response carries an X-Quota-Warning header, so nothing surprises you. On paid plans with metered overage active on your subscription, extra documents are billed at the per-document rate shown on your tariff (capped at 2× the plan fee); otherwise calls stop at the quota with a clear 429 instead of being billed. The Free plan always returns a 429 with an upgrade link. sk_test_ keys are never billed.

How do I reach a human?

Email support@normbill.com — for support, questions about the docs, or anything this FAQ doesn't cover. A practical getting-started guide lives in the public docs.

We could use an open-source library — why an API?

You can, and for pure generation they work. What you take on is running and updating the KoSIT validator, following rule and specification releases, and turning Schematron findings into something your users can act on. normbill is that part as a service: the same JSON in, a validated document or a field-level report out. If your team already has that knowledge in-house, a library may be all you need.

Does normbill export to DATEV?

Not as a separate export — the e-invoice itself is what DATEV takes in. DATEV states that its Rechnungseingangspostfach receives every e-invoice format that conforms to EN 16931, and that all of its existing Datenservices can already transport ZUGFeRD and XRechnung files — with differences, DATEV notes, in how each service processes the data. The file normbill returns is such a document; which DATEV channel carries it is an integration decision in your product. What normbill does not produce is booking data: per DATEV, complete Buchungssätze go through its Buchungsdatenservice and need accounts and contra-accounts (Konto und Gegenkonto) — data your product holds and an invoice does not carry.

What is not supported?

normbill generates, validates and parses documents. It does not deliver over the Peppol network or archive invoices (GoBD), and it covers EN 16931-based formats only. Official KoSIT validation applies to XRechnung (UBL and CII); ZUGFeRD / Factur-X and Peppol BIS are checked at the structural EN 16931 tier. Cancellations use type 384 with negative quantities; commercial credit notes without a preceding invoice (type 381) are available in the CII formats, not yet as a UBL CreditNote — see the guide on cancellations, corrections and credit notes. If one of these is a must-have for your rollout, tell us before you build.

Who keeps up with new XRechnung versions?

We do. The KoSIT validator and its XRechnung configuration are pinned to exact versions, and a new specification version gets its own format id next to the existing one instead of silently replacing the one you integrated against. Changes are announced in the changelog.

What if we want help integrating?

Paid plans include email support for questions about the API; the Free plan has community support. For hands-on help there is the optional Integration Launch package (€990 one-time, excl. VAT): one workflow, a documented data mapping, a working reference integration and 2 sessions. It is never required.

What if normbill goes away?

Your integration produces standard documents — XRechnung, ZUGFeRD / Factur-X — that stay valid and readable without us, and we never hold your invoices, so there is nothing to migrate out. The invoice JSON follows the EN 16931 business terms, so moving to a library or another provider is a mapping exercise, not a data rescue. normbill is operated by VIBOA UG (haftungsbeschränkt).

Ship e‑invoicing without rebuilding your invoicing.

50 documents a month with full validation. No call, no contract, no card.

Spotted something?

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