OfficeIMO.Invoicing
3.4.4
Prefix Reserved
dotnet add package OfficeIMO.Invoicing --version 3.4.4
NuGet\Install-Package OfficeIMO.Invoicing -Version 3.4.4
<PackageReference Include="OfficeIMO.Invoicing" Version="3.4.4" />
<PackageVersion Include="OfficeIMO.Invoicing" Version="3.4.4" />
<PackageReference Include="OfficeIMO.Invoicing" />
paket add OfficeIMO.Invoicing --version 3.4.4
#r "nuget: OfficeIMO.Invoicing, 3.4.4"
#:package OfficeIMO.Invoicing@3.4.4
#addin nuget:?package=OfficeIMO.Invoicing&version=3.4.4
#tool nuget:?package=OfficeIMO.Invoicing&version=3.4.4
OfficeIMO.Invoicing
Create, read, edit and convert electronic invoices with one typed .NET model. The core has no external runtime dependencies and supports .NET Standard 2.0, .NET 8, .NET 10 and .NET Framework 4.7.2.
Build and install locally
From the repository root, pack the project into a local feed, then add that package to your application:
dotnet pack OfficeIMO.Invoicing/OfficeIMO.Invoicing.csproj -c Release -o artifacts/invoice-feed
dotnet add path/to/Application.csproj package OfficeIMO.Invoicing --source artifacts/invoice-feed
This package does not depend on a PDF engine or an external validation runtime.
Create invoice XML
using OfficeIMO.Invoicing;
var invoice = new Invoice {
Number = "INV-001",
IssueDate = new DateTime(2026, 9, 10),
DueDate = new DateTime(2026, 10, 10),
Currency = "EUR",
Seller = new InvoiceParty {
Name = "Example Seller",
Address = new InvoiceAddress { CountryCode = "DE" }
},
Buyer = new InvoiceParty {
Name = "Example Buyer",
Address = new InvoiceAddress { CountryCode = "DE" }
}
};
invoice.Seller.TaxRegistrations.Add(
new InvoiceTaxRegistration("DE123456789", InvoiceTaxRegistration.VatScheme));
invoice.Payments.Add(new InvoicePayment {
MeansCode = "58",
Reference = invoice.Number,
Account = new InvoiceBankAccount { Identifier = "DE79000000001234567890" }
});
invoice.Lines.Add(new InvoiceLine {
Id = "1", Name = "Consulting", Quantity = 1m, UnitPrice = 100m,
Tax = new InvoiceTaxCategory { Code = "S", Rate = 19m }
});
byte[] cii = InvoiceSerializer.Write(invoice, new InvoiceXmlOptions(
InvoiceSpecificationRelease.FacturX_1_09_2_Zugferd_2_5_2,
InvoiceSyntax.Cii,
InvoiceProfile.En16931));
byte[] ubl = InvoiceSerializer.Write(invoice,
new InvoiceXmlOptions(
InvoiceSpecificationRelease.En16931_1_3_16,
InvoiceSyntax.Ubl,
InvoiceProfile.En16931));
Serialization checks model arithmetic and the supported target mapping. Identical models and options produce identical UTF-8 bytes. Use OfficeIMO.Invoicing.Validation to check the resulting bytes against an explicit XSD and Schematron release. Successful serialization alone does not establish standards compliance.
Supported authoring contract
| Area | Supported data |
|---|---|
| Syntax and profiles | Factur-X 1.09.2 / ZUGFeRD 2.5.2 CII D22B with MINIMUM, BASIC WL, BASIC, EN 16931 and EXTENDED; EN 16931 1.3.16 and XRechnung 3.0.2 in CII D16B or UBL 2.1; Peppol BIS Billing 3.0.21 in UBL 2.1 |
| Documents | Invoice and credit note; document currency and accounting-currency VAT. UBL credit notes cannot carry a due date or project reference; writing or converting those fields reports unsupported target data. |
| Parties | Seller, buyer, payee, tax representative, addresses, identifiers and contacts within each semantic role. Tax registrations retain their identifier and arbitrary source scheme. Target inspection reports the exact indexed registration when a target permits only VAT, one seller fiscal registration, or a canonical CII VA/FC scheme. |
| Lines | Quantities, price base quantities, net/gross prices, discounts, allowances, charges, item identifiers, classifications and attributes |
| VAT and totals | Category/rate breakdowns, exemptions, document adjustments, prepayments and payable rounding |
| Payments | Ordered payment-means occurrences with their own description, account, reference, direct-debit and masked-card data. UBL preserves card network identifiers; CII reports them as unsupported. Conflicting CII invoice-level references, creditor identifiers or mandates are reported by exact payment index. |
| References | Orders, preceding invoices, contracts, projects, delivery, periods, accounting and supporting documents. CII preserves a sales-order-only reference; UBL reports that it requires the associated purchase-order reference. External locations preserve well-formed absolute URIs, including FTP and URN schemes, without fetching them. |
IBAN classification checks the registered country prefix, national length and character structure, and MOD-97 checksum against the SWIFT IBAN Registry, release 102. Unknown prefixes and country-invalid identifiers remain generic UBL creditor accounts; they cannot be declared as CII IBANs. These checks do not establish that an account exists.
Lower Factur-X profiles intentionally carry less business data. The default
RejectDataLoss projection policy reports each populated source field that the
selected profile omits. AllowProfileDefinedDataLoss permits only that declared
profile reduction and returns the same findings as warnings from InspectTarget.
MINIMUM and BASIC WL carry calculated aggregates without XML line occurrences.
XRechnung is the only national CIUS with an authoring contract because this release includes its CII/UBL syntax mappings, pinned rules and corpus evidence. EXTENDED-CTC-FR remains recognizable for inspection but cannot be selected for authoring or validation. Peppol BIS is a cross-border network usage specification, not a substitute for a national CIUS contract.
Read and edit safely
var parsed = InvoiceParser.Read(File.ReadAllBytes("invoice.xml"));
foreach (var item in parsed.UnmappedData)
Console.WriteLine($"{item.Location}: {item.Message}");
if (parsed.HasCompleteMapping) {
parsed.Invoice.Lines[0].Quantity = 2m;
InvoiceCalculator.UpdateDeclaredAmounts(parsed.Invoice);
File.WriteAllBytes("edited.xml", parsed.Write(new InvoiceXmlOptions(
InvoiceSpecificationRelease.FacturX_1_09_2_Zugferd_2_5_2,
InvoiceSyntax.Cii,
InvoiceProfile.En16931)));
}
Unknown business elements, attributes and unsupported semantic variations are
reported. Rewriting blocks by default when it would discard them. The explicit
allowUnmappedDataLoss option accepts the reported loss; it does not preserve
unknown extensions. GetOriginalBytes() always returns the original bytes,
even after model edits.
Duplicate invoice-currency or accounting-currency VAT totals are reported as unmapped data. UBL parsing retains the first invoice-currency total that includes a VAT breakdown, keeping that group's amount and breakdown together. For CII and accounting-currency amounts, parsing retains the first total. An explicit lossy rewrite uses those retained values; the resulting model must still pass validation.
Declared source line and VAT amounts are preserved. Model checks permit up to
0.02 difference from the unrounded line formula and a conservative 0.01 VAT
rounding difference for taxable categories; zero-tax categories require exactly
zero VAT. Totals must match the resulting amounts exactly. These
checks do not replace release-specific rules. UpdateDeclaredAmounts explicitly
recalculates lines, VAT and totals after financial edits.
Model validation requires a seller business, legal or VAT identifier, and an account for credit-transfer payment codes 30 and 58. VAT checks cover category-specific registration requirements, exemption reasons on the resulting breakdown, and intra-community delivery details. Imported header-only exemption reasons remain valid through recalculation. Outside-scope VAT cannot mix with other categories or carry party VAT identifiers. Official code lists and release-specific rules remain the responsibility of the optional standards validator.
Target checks require a mandate reference for direct-debit codes 49 and 59 in XRechnung and Peppol. XRechnung, and Peppol transactions where both parties are in Germany, also require creditor and debtor identifiers in the direct-debit group; code 59 cannot include transfer accounts or card details in those profiles. Base EN 16931 does not impose those additional profile requirements.
Quantity, price, base-quantity and percentage calculations retain intermediate precision until monetary rounding. Monetary results use two decimal places with ties towards positive infinity; values that exceed decimal capacity are rejected instead of silently losing cents. Caller text must contain valid XML characters. The model permits up to 4 MiB of combined UTF-8 text and 8 MiB of embedded bytes. Parsing and authoring share a 50,000-item budget across collections, including declared or calculated VAT breakdowns. Parsing rejects inputs with more than 1,000 mapping diagnostics. Model validation, target inspection and conversion return at most 999 detailed diagnostics plus a summary that retains the highest omitted severity. Diagnostic codes are bounded to 256 characters; messages and locations to 4,096, with an explicit truncation marker when needed. Serialized XML is limited to 16 MiB while it is written.
Convert CII and UBL
var conversion = InvoiceConverter.Convert(File.ReadAllBytes("invoice.xml"),
new InvoiceXmlOptions(
InvoiceSpecificationRelease.XRechnung_3_0_2_2026_08_31,
InvoiceSyntax.Ubl,
InvoiceProfile.XRechnung));
if (conversion.Succeeded)
File.WriteAllBytes("converted.xml", conversion.Xml!);
else
foreach (var diagnostic in conversion.Diagnostics)
Console.WriteLine($"{diagnostic.Location}: {diagnostic.Message}");
Conversion produces no bytes if observed source data cannot be represented in the target. Examples include a tax-registration scheme the target would relabel, a sales-order-only reference when writing UBL, CII card-network metadata, and conflicting exemption reasons or singleton payment fields. Every diagnostic names the exact source-model path and unsupported target meaning. A changed guideline is reported and requires validation against the target release. This is a bounded semantic conversion, with explicit loss reporting for fields outside the supported contract.
Inspect profile declarations
using OfficeIMO.Invoicing;
var declaration = InvoiceProfileDeclaration.Read(File.ReadAllBytes("invoice.xml"));
Console.WriteLine(declaration.GuidelineId);
if (declaration.Profile is InvoiceProfile profile && profile != InvoiceProfile.PeppolBis)
Console.WriteLine(InvoiceProfiles.GetXmpConformanceLevel(profile));
The catalogue distinguishes MINIMUM, BASIC WL, BASIC, EN 16931, EXTENDED, XRechnung 3.0, EXTENDED-CTC-FR, and Peppol BIS Billing 3.0. Unknown identifiers are returned with a null profile; missing, ambiguous, malformed, or oversized input is rejected. Peppol BIS does not define Factur-X XMP metadata.
The French profile identifier follows AFNOR XP Z12-012. Recognition does not establish French business-rule coverage.
For visible hybrid PDFs, add the optional OfficeIMO.Invoicing.Pdf adapter. The XML engine remains independent of PDF generation.
Measure equivalent workloads
OfficeIMO.Invoicing.Benchmarks
measures XML read, XML write, pinned rules validation and multilingual PDF
generation separately over the same deterministic 25-line invoice. Correctness
checks run outside measurement, and the suite owns explicit Windows, Linux and
macOS elapsed/allocation ceilings.
| Product | Versions 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 is compatible. 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 is compatible. 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. |
-
.NETFramework 4.7.2
- No dependencies.
-
.NETStandard 2.0
- No dependencies.
-
net10.0
- No dependencies.
-
net8.0
- No dependencies.
NuGet packages (2)
Showing the top 2 NuGet packages that depend on OfficeIMO.Invoicing:
| Package | Downloads |
|---|---|
|
OfficeIMO.Invoicing.Pdf
Optional PDF presentation and hybrid CII invoice generation for OfficeIMO.Invoicing. |
|
|
OfficeIMO.Invoicing.Validation
Pinned schema and Schematron validation for OfficeIMO electronic invoices. |
GitHub repositories
This package is not used by any popular GitHub repositories.