Create an XRechnung via API: a guide with code examples
How to turn invoice data into a valid XRechnung through an API: format, mandatory fields, validation report and delivery – with curl and SDK examples.
As of 29 October 2026. This guide is not tax advice.
The short answer
An XRechnung is an e-invoice under the European standard EN 16931 with the German additional rules (CIUS), transmitted as an XML file in the UBL or CII syntax. It is already the standard for invoices to public authorities; between businesses you must issue e-invoices from 2027 if your prior-year turnover was above €800,000, and from 2028 regardless of turnover. An API takes your invoice data as JSON and returns a validated XRechnung, without you rebuilding the rules yourself.
What an XRechnung is technically
An XRechnung is plain XML. EN 16931 describes the content as numbered business terms (BT-1 to BT-165, groups BG-1 to BG-32) and allows two syntaxes: UBL 2.1 and UN/CEFACT CII. Both are equivalent; many recipients accept both.
KoSIT adds German business rules with identifiers such as BR-DE-15 to the standard, such as a mandatory buyer reference or seller contact details. Validation uses the open KoSIT validator with its published configuration: first the XML schema, then the Schematron rules of the standard and of XRechnung.
Versions: XRechnung 3.0 has applied since 1 February 2024; according to KoSIT it stays in force until at least 31 July 2027. Version 4.0 exists as a preliminary specification. Instead of a summer and a winter release, KoSIT plans one main release per year in the medium term, with bug-fix releases of the validator configuration in between. Fakturnaut currently validates against XRechnung 3.0.2 with the validator configuration of 31 August 2026.
ZUGFeRD (Factur-X in France) is a hybrid format: a PDF/A-3 with the invoice data embedded as CII XML. In the EN 16931 profile it meets the same standard but can also be read by people.
| XRechnung | ZUGFeRD (EN 16931 profile) | |
|---|---|---|
| Format | XML (UBL or CII) | PDF/A-3 with embedded CII XML |
| Readable without software | no | yes, as a PDF |
| Typical recipients | public authorities, businesses with automated processing | businesses that also want to look at the invoice |
More in the guide XRechnung or ZUGFeRD?
Mandatory fields that most often fail
The following rules come from the validator configuration we use (XRechnung 3.0.2). Each one is an error that makes the invoice invalid:
- Buyer reference (BT-10), BR-DE-15: always required. For public authorities it is the Leitweg-ID; between businesses an order number or a placeholder is enough.
- Seller contact (BG-6), BR-DE-2, BR-DE-5 to BR-DE-7: name, telephone number (BT-42) and e-mail address (BT-43) of the contact person.
- Payment instructions (BG-16), BR-DE-1: the payment means and, for credit transfers, the account details (BG-17, BR-DE-23-a).
- VAT: every VAT category needs a rate (BT-119, BR-DE-14). Exempt supplies, reverse charge or intra-community supplies need an exemption reason as text (BT-120) or code (BT-121), for example BR-E-10 or BR-AE-10. For standard-rated and most other VAT categories the seller needs a VAT identifier (BT-31) or tax number (BT-32), or a tax representative must be given (BR-DE-16).
- Electronic addresses (BT-34, BT-49): seller and buyer each need an electronic address with a scheme, such as
EMfor e-mail or0204for a Leitweg-ID (PEPPOL-EN16931-R020 and -R010).
The delivery date (BT-72) or a delivery period is often missing too. XRechnung only reports this as a note, but for VAT purposes the time of supply is a mandatory invoice field (§ 14(4) sentence 1 no. 6 UStG).
Build it yourself or use an API
You can generate an XRechnung yourself. There are good open-source libraries, for example Mustangproject for Java, ZUGFeRD-csharp for .NET or horstoeko/zugferd for PHP, and the KoSIT validator for checking.
With the library, the XML is written. What remains:
- Validating: running the validator with the right configuration and turning its messages into errors your users understand.
- Calculating: totals, VAT breakdown and rounding under EN 16931, so the BR-CO-* rules pass.
- Updating: installing and testing every new KoSIT release.
- Delivering: a contract with a certified access point for Peppol.
- Archiving: keeping every invoice unchanged and retrievable (§ 14b UStG).
Is it worth it? If e-invoicing is your core business, or you need one format for a few invoices, a library may be enough. If you generate invoices for many customers and want to focus on your own product, an API takes the ongoing maintenance off your hands. What the Fakturnaut API does is shown in the overview for software vendors; what it costs is on API pricing.
Step by step with the Fakturnaut API
All examples run in the free sandbox: test invoices are valid XRechnungen, marked as tests, never charged and deleted after 30 days. Every build checks the examples against the API reference; we also run the request, the answer and the validation report in the sandbox.
1. Create an account and copy your test key
Sign up and, in the portal under Sellers, add the company that issues the invoices – Muster GmbH in the example – with address, VAT ID, a contact with phone and e-mail, and bank details. Every invoice takes these from the seller. Then create a test key under API keys; it starts with fkn_test_ and is shown only once.
2. Send the invoice data as JSON
Muster GmbH charges Stadt Beispielhausen for two training days. The Leitweg-ID 04011000-BEISPIEL-19 is an invented example; the authority gives you the real one.
export FAKTURNAUT_KEY=fkn_test_… # your test key
# sellerId: your seller's ID from the portal
cat > invoice.json <<'JSON'
{
"sellerId": "5b1d7f0e-3c2a-4e8b-9f61-2d4c8a7e9b03",
"number": "RE-2026-0107",
"issueDate": "2026-11-03",
"dueDate": "2026-12-03",
"deliveryDate": "2026-10-28",
"buyerReference": "04011000-BEISPIEL-19",
"buyer": {
"name": "Stadt Beispielhausen",
"electronicAddress": "04011000-BEISPIEL-19",
"electronicAddressScheme": "0204",
"address": {
"street": "Rathausplatz 1",
"city": "Beispielhausen",
"postCode": "99999",
"country": "DE"
}
},
"lines": [
{ "name": "Schulung Fachverfahren", "quantity": 2, "unitCode": "DAY", "netPrice": 850.0, "vatRate": 19 }
]
}
JSON
curl -X POST https://api.fakturnaut.com/v1/invoices \
-H "Authorization: Bearer $FAKTURNAUT_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
--data @invoice.json
The Idempotency-Key makes retries safe: if you resend the same request with the same key after a network error, no second invoice is created. The response (shortened):
{
"id": "8f3a2c71-5d04-4e9b-b6a1-3c7e9d2f0b58",
"number": "RE-2026-0107",
"typeCode": "380",
"amountDue": 2023.0,
"currency": "EUR",
"findings": [],
"documents": [
{
"format": "xrechnung-ubl",
"mediaType": "application/xml",
"href": "/v1/invoices/8f3a2c71-5d04-4e9b-b6a1-3c7e9d2f0b58/document?format=xrechnung-ubl"
},
{
"format": "zugferd",
"mediaType": "application/pdf",
"href": "/v1/invoices/8f3a2c71-5d04-4e9b-b6a1-3c7e9d2f0b58/document?format=zugferd"
}
]
}
The same with the TypeScript SDK (npm install @fakturnaut/sdk); the documentation lists the SDKs for PHP, Java and C#:
import { readFileSync } from 'node:fs';
import { Configuration, InvoiceRequestFromJSON, InvoicesApi } from '@fakturnaut/sdk';
import { newIdempotencyKey } from '@fakturnaut/sdk/helpers';
const invoices = new InvoicesApi(new Configuration({ accessToken: process.env.FAKTURNAUT_KEY }));
const issued = await invoices.issueInvoice({
idempotencyKey: newIdempotencyKey(), // reuse the same key when you retry
invoiceRequest: InvoiceRequestFromJSON(JSON.parse(readFileSync('invoice.json', 'utf8'))),
});
console.log(issued.number, issued.documents);
3. Read the validation report
POST /v1/invoices/validate checks the same data without issuing anything. If the Leitweg-ID is missing, for example, the API answers:
{
"valid": false,
"summary": {
"de": "Die E-Rechnung ist nicht gültig: 1 Fehler.",
"en": "The e-invoice is not valid: 1 error."
},
"totals": {
"taxExclusiveAmount": 1700.0,
"vatTotal": 323.0,
"amountDue": 2023.0
},
"findings": [
{
"ruleId": "BR-DE-15",
"severity": "ERROR",
"source": "BUSINESS_RULES",
"location": "BT-10",
"message": {
"de": "Für XRechnung muss die Käuferreferenz bzw. Leitweg-ID (BT-10) angegeben werden.",
"en": "XRechnung requires the buyer reference or Leitweg-ID (BT-10)."
}
}
]
}
ruleId names the broken rule, location the field (here BT-10, buyerReference in the JSON), message the explanation in German and English. Show message to your users and act on ruleId in your code. The fix here: add the Leitweg-ID as buyerReference. When issuing, the same error leads to a 422 answer with the code invoice.invalid and the same findings; an invalid invoice is never issued. All codes are explained in Errors and rule codes.
4. Download the XML and the PDF
Download each document in documents from its href. The XML is the XRechnung, the PDF the ZUGFeRD version of the same invoice:
curl -OJ "https://api.fakturnaut.com/v1/invoices/<id>/document?format=xrechnung-ubl" \
-H "Authorization: Bearer $FAKTURNAUT_KEY"
curl -OJ "https://api.fakturnaut.com/v1/invoices/<id>/document?format=zugferd" \
-H "Authorization: Bearer $FAKTURNAUT_KEY"
The documents are stored unchanged; the ETag is their SHA-256 checksum. You can also cross-check them with our free validator.
5. Deliver
Peppol is a European network for e-invoices: senders and recipients are connected through certified access points and addressed by scheme and identifier. Peppol pays off when your recipient is reachable there – the federal invoice platform is, for example – and when you send many invoices automatically and want a delivery status. Without recipient the API uses the buyer's electronic address from the invoice (BT-49):
curl -X POST https://api.fakturnaut.com/v1/invoices/<id>/deliveries \
-H "Authorization: Bearer $FAKTURNAUT_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
--data '{"channel": "peppol", "recipient": "0204:04011000-BEISPIEL-19"}'
In the sandbox Peppol is simulated; follow the status with GET /v1/deliveries/{id} or by webhook. Real Peppol delivery needs a verified seller with a Peppol address (for example scheme 9930 with the VAT ID). Details: Deliveries and status.
Delivery: Via Peppol on the Growth, Scale and Enterprise plans. Sending by e-mail: in preparation.
Delivering an XRechnung to public authorities
Invoices to the German federal administration fall under the E-Invoicing Ordinance (E-RechV): the Leitweg-ID goes into the buyer reference (BT-10), together with bank details, payment terms and the issuer's e-mail address (§ 5(1) E-RechV). If the authority gave you an order number (BT-13) or a supplier number (BT-29) when placing the order, these belong in the invoice too (§ 5(2) E-RechV). They are submitted through the federal invoice platform (OZG-RE): by web form, upload, e-mail or Peppol. On Peppol the recipient identifier is 0204: plus the Leitweg-ID. States and municipalities partly run their own portals with their own requirements.
What Fakturnaut does: it generates the XRechnung with the Leitweg-ID, validates it against KoSIT's rules before it is issued, and delivers it over Peppol to 0204:<Leitweg-ID>.
What you as the issuer still do yourself:
- ask the authority for the Leitweg-ID (order, contract or contact person),
- register once, free of charge, at the OZG-RE – the platform requires this for Peppol too,
- for states and municipalities, find out the receiving channel of the body concerned,
- watch for a rejection by the platform and resubmit a corrected invoice.
More on the Leitweg-ID in the guide Leitweg-ID: invoices to public authorities.
Self-billed invoices as XRechnung
When your customer issues the invoice for your supply (a Gutschrift under § 14(2) sentence 5 UStG, invoice type 389), that is an e-invoice too and follows the same rules. More in the guide Self-billed invoices as e-invoices.
Self-billing (Gutschriften): in preparation. Access on request: write to us.
Frequently asked questions
Do I need a Leitweg-ID for an XRechnung?
Only for public authorities. XRechnung always requires a buyer reference (BT-10), but for businesses an order number or a placeholder such as "-" is enough.
UBL or CII – which syntax should I generate?
Both are equivalent under EN 16931. If your recipient sets no preference, UBL is common on Peppol. The Fakturnaut API generates both syntaxes from the same data.
Is a PDF with embedded XML an XRechnung?
No. That is ZUGFeRD. In the EN 16931 profile ZUGFeRD is also an e-invoice under the German VAT Act, but not an XRechnung. Many authority portals require XRechnung.
What happens when a new XRechnung release comes out?
KoSIT publishes new versions and validator configurations; the federal government announces changes in the Bundesanzeiger. Fakturnaut adopts them in its validation; your integration stays the same because the API is versioned in its path (/v1).
Can I try the API for free?
Yes. In the sandbox a test key creates valid XRechnungen marked as tests, free of charge and without a contract. Test data is deleted after 30 days.
When must businesses issue e-invoices?
From 1 January 2027 if the total turnover of the previous year was above €800,000, otherwise from 1 January 2028 (§ 27(38) UStG). Businesses have had to be able to receive e-invoices since 2025.
Sources
- § 14 UStG, § 14b UStG and § 27(38) UStG (German)
- Federal E-Invoicing Ordinance: § 5 (German)
- BMF letter of 15 October 2025 and of 15 October 2026 (German)
- FAQ on the e-invoice (Federal Ministry of Finance, German)
- XRechnung and versions and bundles (KoSIT, German)
- Validator configuration for XRechnung (KoSIT)
- Transmission via Peppol and transmission channels (e-rechnung-bund.de, German)
- The European standard EN 16931 (European Commission)
- ZUGFeRD (FeRD)
As of 29 October 2026. This guide is not tax advice.
Try it for free
Create an account and a test key, and generate your first XRechnung in the sandbox – free of charge and without a contract.
More guides
- E-invoicing mandate 2027 and 2028: deadlines and exceptions
- Open and read an XRechnung
- Validate an XRechnung
- Receive e-invoices
- Create an e-invoice for free
- Create a ZUGFeRD invoice
- XRechnung or ZUGFeRD?
- Leitweg-ID: invoices to public authorities
- E-invoices for Shopify and WooCommerce
- Self-billed invoices as e-invoices (XRechnung and ZUGFeRD)
- Self-billing for charging infrastructure and platforms