Eunormia.Sdk 1.0.1

dotnet add package Eunormia.Sdk --version 1.0.1
                    
NuGet\Install-Package Eunormia.Sdk -Version 1.0.1
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Eunormia.Sdk" Version="1.0.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Eunormia.Sdk" Version="1.0.1" />
                    
Directory.Packages.props
<PackageReference Include="Eunormia.Sdk" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Eunormia.Sdk --version 1.0.1
                    
#r "nuget: Eunormia.Sdk, 1.0.1"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Eunormia.Sdk@1.0.1
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Eunormia.Sdk&version=1.0.1
                    
Install as a Cake Addin
#tool nuget:?package=Eunormia.Sdk&version=1.0.1
                    
Install as a Cake Tool

Eunormia.Sdk

Offline conversion to ZUGFeRD / Factur-X (PDF/A-3, EN 16931) for .NET — with the full double gate: veraPDF (PDF/A-3B) and EN-16931 Schematron. Only output that passes both gates is ever returned.

The package bundles the validated Java engine together with a trimmed JRE — no infrastructure at the consumer (no installed Java, no Docker, no server). dotnet add package, done.

Why

No existing .NET package does this: the common libraries (ZUGFeRD-csharp, FacturX-csharp/Securibox, Dangl.XRechnung …) create/read XML and embed it into an already-conforming PDF/A. Eunormia takes an arbitrary input PDF and enforces conformance (font embedding → base-14 substitution → rasterization as escalation) and returns only after passing the veraPDF and EN-16931 gate. veraPDF has no .NET port — real PDF/A-3B validation in .NET exists only by wrapping the Java engine; that is exactly what this package encapsulates.

Quick start

using Eunormia.Sdk;

var converter = new EunormiaConverter(new EunormiaOptions
{
    LicenseKey = "…",   // from the eunormia dashboard; without it -> watermark
    Profile    = ZugferdProfile.EN16931,
    Language   = "en"
});

EunormiaResult r = await converter.ConvertAsync(invoiceJson, pdfBytes);

File.WriteAllBytes(r.FileName, r.Pdf);
Console.WriteLine($"veraPDF={r.VeraPdfPassed} EN16931={r.En16931Passed} " +
                  $"watermarked={r.Watermarked} license={r.LicenseStatus}");
  • Without a valid license the result carries a watermark (conversion + gates still run in full).
  • Business/technical errors surface as EunormiaException (status, stage, localized Details).
  • Without pdfBytes a default template is rendered. For CII-XML passthrough: ConvertXmlAsync(ciiXml, pdfBytes).

Typed model (optional)

Instead of a JSON string you can pass the strongly-typed Invoice model — same schema, with IntelliSense and compile-time safety:

var invoice = new Invoice
{
    Number    = "RE-2026-0042",
    IssueDate = "2026-07-21",
    Seller = new Party { Name = "Muster GmbH", Street = "Musterstraße 1",
                         Zip = "4020", City = "Linz", Country = "AT", VatId = "ATU12345678" },
    Buyer  = new Party { Name = "Beispiel GmbH", Street = "Beispielweg 2",
                         Zip = "80331", City = "München", Country = "DE" },
    Items  = new() { new LineItem { Name = "Consulting", Quantity = 16m,
                                    Unit = "HUR", UnitPrice = 120m, VatPercent = 20m } }
};

EunormiaResult r = await converter.ConvertAsync(invoice, pdfBytes);

The JSON-string overload stays available as an escape hatch (e.g. to bring your own model or set fields outside the schema). On the receiving side, ReadResult.GetInvoice() returns the same typed model.

Receiving: validate & read

// Check an incoming e-invoice against the double gate (veraPDF + EN 16931):
ValidationResult v = await new EunormiaValidator().ValidateAsync(incomingPdf);
if (!v.Valid) foreach (var f in v.En16931.Failures) Console.WriteLine(f);

// Read the header data:
ReadResult r = await new EunormiaReader().ReadAsync(incomingPdf);
Console.WriteLine($"{r.Header?.Number}  {r.Header?.Currency}  {r.Standard}");
string embeddedCiiXml = r.Xml;

This covers both directions: creating invoices (guaranteed conformant) and receiving them (validate + deserialize) — all offline.

License & watermark

The SDK is fully functional without a license — generated invoices then carry only a sample watermark. A license key removes it. Verification runs completely offline (no phone-home, no telemetry).

How to get a key:

  1. Create an account at eunormia.com.
  2. Dashboard → "Offline license"Generate license → copy the key.
  3. Set it in the SDK — either as EunormiaOptions.LicenseKey or via the environment variable EUNORMIA_LICENSE.

For pilot/trial access and commercial terms: eunormia.com. Use is subject to the bundled license (LICENSE.txt).

Target platforms

  • Frameworks: net8.0 and netstandard2.0 (the latter covers .NET Framework 4.6.1+ incl. 4.8).
  • RIDs: currently win-x64 only. On other platforms (Linux/macOS) the SDK throws a clear EunormiaException — further RIDs (linux-x64, osx-arm64) follow additively, built per platform.
  • Package size: ~116 MB (win-x64) — dominated by the engine core (Mustang, PDFBox, veraPDF, FOP/Batik, Saxon, ICU4J) + trimmed JRE, not by the SDK code.

Architecture (in brief)

EunormiaConverter starts the bundled JRE (runtimes/<rid>/native/jre) as a child process and invokes eunormia-core.jar (entry point at.eunormia.cli.OfflineCli); communication is JSON over stdin/stdout. The runtime is unpacked from a packed runtime.zip into runtimes/<rid>/native/ during the consumer's build (see build/Eunormia.Sdk.targets).

Building / packing yourself

Prerequisites: the portable Java toolchain under service/tools/ (see service/README), a .NET SDK (≥ 8), and 7-Zip (included in the toolchain).

# Build the runtime (slim core.jar + trimmed JRE) and pack the NuGet:
cd dotnet
./pack-nuget.sh win-x64        # -> dotnet/nupkg-out/Eunormia.Sdk.<ver>.nupkg

# Sample against the local runtime:
dotnet run --project sample -- \
  ../service/dist/win-x64 ../service/harness/harness-invoice.json \
  ../service/testdata/embedded-ttf.pdf

Feature set

Create (ZUGFeRD/Factur-X, double gate veraPDF + EN 16931) · Receive (validate + deserialize) · optional official add-on checks KoSIT (XRechnung/DE) and FR-CTC (France) · daemon mode (UseDaemon) against cold-start latency · signed conformance certificate (EmitCertificate) · Ed25519 offline license (watermark gate). Both TFMs (net8.0, netstandard2.0).

Platforms: currently win-x64 only; further RIDs (Linux/macOS) to follow.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.1 125 7/21/2026