Documentation

Documentation & getting started

How to integrate Validator, Creator and Reader into your own .NET application – from the NuGet package to the first working call, return values and error handling.

Covers: ZUGFeRD 2.5.2 / Factur-X 1.09.2
  • .NET Framework 4.8
  • .NET 8
  • .NET 10
  • ZUGFeRD 2.5.2 / Factur-X 1.09.2
  • XRechnung 3.0 (CII & UBL)

Quick start

From PDF to compliance verdict in three steps. The example below mirrors the actual flow used by the live demo.

  1. Add the Facturexa.ZugferdValidator package via NuGet. The official rule sets (XML schema and Schematron) are included and found automatically.
  2. Register the license key once at application startup. You receive it by email and can always find it in your customer account.
  3. For each invoice, validate the PDF (or the XML) with a single call.
C#
using Facturexa.ZugferdValidator;

// Once at application startup: register the license key.
ZugferdValidatorLicense.RegisterLicense("…");

// Validate the invoice PDF: PDF container, XML schema and official Schematron in one call.
var result = ZugferdValidator.Validate("invoice.pdf", "INV-2026-0001");

Console.WriteLine(result.IsValid ? "Valid" : "Not compliant");

The complete flow with error handling follows in the Validator section.

Installation & requirements

Each library is a separate NuGet package and can be referenced on its own.

Facturexa.ZugferdValidator
dotnet add package Facturexa.ZugferdValidator
Install-Package Facturexa.ZugferdValidator
Facturexa.ZugferdCreator
dotnet add package Facturexa.ZugferdCreator
Install-Package Facturexa.ZugferdCreator
Facturexa.ZugferdReader
dotnet add package Facturexa.ZugferdReader
Install-Package Facturexa.ZugferdReader
🖥️

Requirements

  • .NET 10, .NET 8 or .NET Framework 4.8
  • Windows, Linux or macOS
  • Validator: Official Schematron\ folder next to the application (copied automatically by the package)
  • Validator: no trimming (PublishTrimmed) and no Native AOT
📦

Available on NuGet

For pricing and license keys see License or Contact.

🧪

Try it without code

The live demo runs the Validator right in your browser, without any integration into your own code.

Deploying the rule sets (Validator)

  • Offline operation: all rule sets (XML schema, Schematron, code lists) ship with the package. No internet connection is needed at runtime and the Validator calls no external service – the license check is local as well. No firewall rule is required.
  • The package copies Official Schematron\ (the Schematron rule sets and, under XSD\, the XML schema) next to your application automatically on build and publish – also for classic ASP.NET (under bin\), single-file, ClickOnce, and when you reference the Validator through your own library or your own NuGet package.
  • After downgrading the package, clean or rebuild the solution once so the older rule set files replace the newer ones in the output folder.
  • Providing the folder yourself: set <FacturexaContentAutoCopy>false</FacturexaContentAutoCopy> in the project, with PackageReference additionally ExcludeAssets="contentFiles" on the package reference, and set SchematronChecker.SchematronDirectory to the folder.

Profiles & versions

ZUGFeRD defines several profiles with different levels of detail. The overview below shows which ones the Validator checks and the Creator generates.

Profile Description Validator Creator
MINIMUM Header data only, not a valid e-invoice format on its own ✔ Yes ✔ Yes
BASIC WL Header data without invoice lines ✔ Yes ✔ Yes
BASIC Core information including invoice lines ✔ Yes ✔ Yes
EN 16931 / COMFORT European core standard – valid e-invoice format ✔ Yes ✔ Yes
EXTENDED Extended data set; from ZUGFeRD 2.5.2 including sub-lines, kits & bundles ✔ Yes ✔ Yes
XRechnung 3.0 (CIUS) German B2G core variant, two-stage EN 16931 + CIUS ✔ Yes (CII + UBL) ✔ Yes (CII)
UBL generation Output XRechnung as UBL instead of CII n/a (already validated) Roadmap

Version

The Creator always writes the current specification: ZUGFeRD 2.5.2 / Factur-X 1.09.2 (effective from 1 September 2026), including the EXTENDED sub-lines for kits and bundles. You do not choose a version in Save(…) – new specifications arrive with a new package version.

Which specification the referenced DLL implements can be queried at runtime: ZugferdCreatorInfo.SupportedSpecification.

Validator: validate a PDF

Register the license key once at application startup. The Validator finds the official rule sets automatically next to the DLL (under bin\ for classic ASP.NET); after that, one call per validation is enough. Pass the complete PDF: the Validator extracts the embedded XML itself, checks the PDF container (PDF/A-3, Factur-X metadata) and then the XML against the XML schema and the official Schematron. A plain XML file works the same way – detected from the content, not the extension. IsValid is true if no stage reports an error; IsPdfValid and IsSchemaValid give the partial verdicts.

C#
using Facturexa.ZugferdValidator;

// Once at application startup.
ZugferdValidatorLicense.RegisterLicense("…");

// PDF or XML: PDF container, XML schema and official Schematron in one call.
var result = ZugferdValidator.Validate("invoice.pdf", "INV-2026-0001");

Console.WriteLine(result.IsValid ? "Valid" : "Not compliant");
Console.WriteLine($"PDF container: {result.IsPdfValid}"); // null for a plain XML
Console.WriteLine($"Rule set: {result.SchematronRuleSet}");

foreach (var error in result.Errors)
    Console.WriteLine($"{error.Stage}: {error}"); // e.g. "Schematron: BR-CO-15 (BT-112): ..."

Further reading: Validator product page · Try the live demo

Creator: create an invoice

Register the license key once at application startup, then set the invoice header, parties, lines and totals, choose a profile and save. Output is currently CII (UBL is on the roadmap).

C#
using Facturexa.ZugferdCreator;

// Once at application startup.
ZugferdCreatorLicense.RegisterLicense("…");

var invoice = new EInvoice
{
    InvoiceNumber = "INV-2026-0001",
    InvoiceDate = DateTime.Today
};

invoice.SetSellerTradeParty("Sample GmbH", "12345", "Berlin", "Musterstraße 1", CountryID.DE);
invoice.AddSellerSpecifiedTaxRegistration("DE123456789", TaxRegistrationSchemeID.VA);
invoice.SetBuyerTradeParty("Customer AG", "54321", "Hamburg", "Kundenweg 2", CountryID.DE);

invoice.AddIncludedSupplyChainTradeLineItem(
    name: "Consulting services", netUnitPrice: 100.00m, unitCode: UnitCode.C62,
    billedQuantity: 3m, lineTotalAmount: 300.00m, taxPercent: 19m);

invoice.AddApplicableTradeTax(300.00m, 19m, 57.00m, TaxTypeCode.VAT, TaxCategoryCode.S);

invoice.LineTotalAmount = 300.00m;
invoice.TaxBasisAmount = 300.00m;
invoice.TaxTotalAmount = 57.00m;
invoice.GrandTotalAmount = 357.00m;
invoice.DuePayableAmount = 357.00m;

using var xmlStream = new MemoryStream();
invoice.Save(xmlStream, InvoiceProfile.Comfort);

Further reading: Creator product page · Try the live demo

Reader: read an invoice

The Reader reads an invoice – as plain XML (CII or UBL) or as a PDF with embedded XML; the format is detected automatically – and returns the fields as an object. Optionally it renders a readable PDF view from it.

C#
using Facturexa.ZugferdReader;

// Read a PDF or XML – the file name helps with format detection.
using var stream = File.OpenRead("invoice.pdf");
var invoice = ZugferdReader.Read(stream, "invoice.pdf");

Console.WriteLine(invoice.InvoiceNumber);
Console.WriteLine(invoice.InvoiceDate?.ToString("yyyy-MM-dd"));
Console.WriteLine(invoice.Seller?.Name);
Console.WriteLine($"{invoice.LineItems.Count} line(s), {invoice.GrandTotalAmount:N2} {invoice.CurrencyCode}");

// Optional: render a readable PDF view of the invoice.
byte[] viewPdf = ZugferdReader.CreatePdf(invoice);
File.WriteAllBytes("invoice-view.pdf", viewPdf);

Further reading: Reader product page · Try the live demo

Return values

The most important fields of the result objects at a glance.

ZugferdValidationResult – Validator.Validate(…)

MemberTypeMeaning
IsValidboolTrue if no stage reports an error (PDF container, XML schema, official Schematron) and the PDF check did not fail.
IsPdfValidbool?Verdict of the PDF check; null if an XML was validated instead of a PDF.
IsSchemaValidboolTrue if the XML schema (XSD) reports no error.
PdfCheckZugferdPdfCheckResultResult of the PDF check with its status lines (see below); null for a plain XML.
PdfFindings / SchemaFindings / SchematronFindingsList<ValidationFinding>Findings of one check stage; every finding states its stage in Stage.
EmbeddedXml / EmbeddedXmlFileNamebyte[] / stringThe validated XML and, for a PDF, the attachment name, e.g. “factur-x.xml” – for example to pass it on to the Reader.
ErrorsList<ValidationFinding>Blocking findings (severity Error).
WarningsList<ValidationFinding>Warnings; they do not prevent sending.
FindingsList<ValidationFinding>All findings, unfiltered.
SchematronRuleSetstringOfficial rule set applied, e.g. “ZUGFeRD 2.5.2 / Factur-X 1.09.2, profile EXTENDED – release date 2026-08-04 (FACTUR-X_EXTENDED.xslt)”. Null if the profile is not covered or the Schematron could not run.
ProfileInfoInvoiceProfileInfoVersion/profile declared by the document itself (BT-24).
GetErrorMessages()List<string>Errors as ready-made message texts including the invoice number.

ZugferdPdfCheckResult – ZugferdValidationResult.PdfCheck

MemberTypeMeaning
OverallValidboolOverall verdict of the PDF check (same as IsPdfValid).
FormatstringPDF/A identification from the XMP metadata, e.g. “PDFA_3_B”, otherwise “unknown”.
FacturXVersionstringFactur-X version from the XMP metadata, e.g. “1.0”.
XmlExtractable / EmbeddingCompliant / FileNameCompliant / XmpCompliantZugferdPdfCheckStatusStatus lines: Yes, No or Unknown.
FindingsList<ValidationFinding>Findings of the PDF check (PDF-CHECK-01 to -16, PDF-XML-MISSING).

Previous API: ZugferdPdfReader.ReadZugferdXml(…) and ZugferdPdfValidator.Validate(…) keep working until version 8.0 but are marked obsolete since 7.4.0. Pass the PDF directly to ZugferdValidator.Validate(…) instead.

InvoiceViewModel – ZugferdReader.Read(…)

MemberTypeMeaning
InvoiceNumberstringInvoice number (BT-1).
InvoiceDateDateTime?Invoice date (BT-2).
Seller / BuyerInvoicePartyViewModelSeller/buyer including .Name and address.
LineItemsList<…>Invoice lines.
GrandTotalAmountdecimal?Invoice total amount with VAT (BT-112).
CurrencyCodestringCurrency (BT-5), e.g. “EUR”.
ProfileUrnstringProfile URN from the CustomizationID.

Error handling & troubleshooting

The most common pitfalls during integration and their cause.

SymptomCause & solution
ZugferdValidatorLicenseException or ZugferdCreatorLicenseException: “No license key found” The key was not registered. Call ZugferdValidatorLicense.RegisterLicense("…") or ZugferdCreatorLicense.RegisterLicense("…") once at application startup, before the first validation or creation.
Finding XSD-ERROR: validation against the XML schema could not be performed The XSD files (Official Schematron\XSD\) were not deployed or the folder is not next to the DLL. Deploy the complete Official Schematron\ folder or set SchematronChecker.SchematronDirectory to its path once. A check that cannot be performed is deliberately reported as an error.
Finding PDF-XML-MISSING, message “The PDF file contains no attachments” The PDF contains no embedded XML – it is not a ZUGFeRD invoice. Use a genuine Factur-X/ZUGFeRD PDF or validate the XML directly.
IsValid == false although the invoice looks valid; the error mentions Saxon/Schematron The Saxon DLL or the Schematron artifacts were not deployed. A check that cannot be performed is deliberately reported as an error. Deploy the artifacts.
After publishing with PublishTrimmed: finding SCHEMATRON-ERROR, message mentions DotNetLocaleHelper The Saxon engine supports neither trimming nor Native AOT. Publish without PublishTrimmed.
ZugferdReaderException / UnsupportedFormatException The file is neither a PDF with embedded XML nor an XML in CII or UBL syntax. Use a supported format; wrap the call to ZugferdReader.Read(…) in try/catch.

Next steps

🔍

Validator

Validate incoming e-invoices.

Product page · Demo
🧾

Creator

Create compliant invoices.

Product page · Demo
📖

Reader

Read and display invoices.

Product page · Demo
Missing a specific API reference, an example for a special case (e.g. kits/bundles, allowances, referenced documents) or a sample repository? Let us know – it helps us extend the documentation where it matters.