InvoiceXml.FacturX 1.0.1

Prefix Reserved
dotnet add package InvoiceXml.FacturX --version 1.0.1
                    
NuGet\Install-Package InvoiceXml.FacturX -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="InvoiceXml.FacturX" Version="1.0.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="InvoiceXml.FacturX" Version="1.0.1" />
                    
Directory.Packages.props
<PackageReference Include="InvoiceXml.FacturX" />
                    
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 InvoiceXml.FacturX --version 1.0.1
                    
#r "nuget: InvoiceXml.FacturX, 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 InvoiceXml.FacturX@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=InvoiceXml.FacturX&version=1.0.1
                    
Install as a Cake Addin
#tool nuget:?package=InvoiceXml.FacturX&version=1.0.1
                    
Install as a Cake Tool

Factur-X for .NET

NuGet

Create, validate, embed and read Factur-X e-invoices from C#. InvoiceXml.FacturX is a thin, typed client for the InvoiceXML API: you pass an EN 16931 invoice object and get back a Factur-X PDF/A-3 that has already passed the official rules.

  • Factur-X: hybrid PDF/A-3 with the invoice XML embedded, EN 16931 profile by default, every official profile selectable, including EXTENDED-CTC-FR.
  • French e-invoicing reform: the French BR-FR rules on request, the same set the certified platforms apply. Factur-X is a core format of the reform in force since September 2026 and is accepted by Chorus Pro.
  • Validation of Factur-X PDFs from any producer, with plain-language findings and a field report.
  • Reading of incoming invoices into the same object model, plus extraction of embedded attachments.

Install

dotnet add package InvoiceXml.FacturX

Targets .NET 8 and .NET Standard 2.0 (.NET Framework 4.6.2+, .NET Core, Mono). The only dependency is System.Text.Json on .NET Standard.

Quick start

using InvoiceXml.FacturX;

using var client = new FacturXClient("YOUR_API_KEY");
var pdf = await client.CreateFacturXAsync(new InvoiceDocument
{
    InvoiceNumber = "F-2026-001",
    Currency = CurrencyCode.EUR,
    Seller = new SellerParty { Name = "Atelier Dupont SARL", VatIdentifier = "FR32123456789", PostalAddress = new PostalAddress { City = "Paris", PostCode = "75011", Country = CountryCode.FR } },
    Buyer = new BuyerParty { Name = "Client Exemple SA", PostalAddress = new PostalAddress { City = "Lyon", PostCode = "69002", Country = CountryCode.FR } },
    Lines = { new InvoiceLine { Quantity = 10, UnitCode = UnitCodes.Hour, Item = new ItemInformation { Name = "Prestation de conseil" }, PriceDetails = new PriceDetails { NetPrice = 120m }, VatInformation = new LineVatInformation { CategoryCode = VatCategoryCode.S, Rate = 20 } } },
});
await pdf.SaveAsync("facture.pdf");

Totals, VAT breakdowns, the issue date and default payment terms are filled in by the API when you leave them empty. Get an API key with the 30-day free trial: 100 credits, no credit card required at www.invoicexml.com/signup.

Why InvoiceXML

  • Rule sets updated on their legal effective dates. New EN 16931, Factur-X and French reform rule releases switch server-side on the date they become binding. Your integration and this package stay the same: no package update, no redeploy.
  • Validated before delivery. Every invoice is checked against the official rules before it is returned. Data that cannot yield a compliant invoice is refused with the violated rules and the fields to correct.
  • Zero data retention. Documents are processed in memory and never stored. See security.
  • Processing in Frankfurt. EU-only processing in Frankfurt am Main, Germany, GDPR compliant by design.
  • Integration assistance. Our engineers help you map your data and get to production. Contact us.

Usage

An invoice for the French reform

Add FacturXRuleSets.BrFr and the invoice must also pass the French BR-FR rules. A domestic invoice then carries the SIREN of both parties, the billing mode in BusinessProcessType, and the mandatory payment mentions as coded notes.

var invoice = new InvoiceDocument
{
    InvoiceNumber = "F-2026-0815",
    Currency = CurrencyCode.EUR,
    DueDate = new DateTime(2026, 11, 9),
    BusinessProcessType = "S1", // billing mode: services, simple invoice
    Notes =
    {
        new InvoiceNote("En cas de retard de paiement, une indemnite forfaitaire de 40 euros pour frais de recouvrement sera exigee.", "PMT"),
        new InvoiceNote("Penalites de retard : trois fois le taux d'interet legal.", "PMD"),
        new InvoiceNote("Pas d'escompte pour paiement anticipe.", "AAB"),
    },
    Seller = new SellerParty
    {
        Name = "Atelier Dupont SARL",
        VatIdentifier = "FR32123456789",
        LegalRegistration = new SchemeIdentifier("123456789", "0002"), // SIREN
        PostalAddress = new PostalAddress { Line1 = "12 rue de la Roquette", City = "Paris", PostCode = "75011", Country = CountryCode.FR },
        ElectronicAddress = new SchemeIdentifier("factures@atelier-dupont.fr", "EM"),
    },
    Buyer = new BuyerParty
    {
        Name = "Client Exemple SA",
        VatIdentifier = "FR40303265045",
        LegalRegistration = new SchemeIdentifier("303265045", "0002"),
        PostalAddress = new PostalAddress { Line1 = "5 place Bellecour", City = "Lyon", PostCode = "69002", Country = CountryCode.FR },
        ElectronicAddress = new SchemeIdentifier("comptabilite@client-exemple.fr", "EM"),
    },
    PaymentDetails = new PaymentDetails
    {
        PaymentMeansCode = PaymentMeansCodes.SepaCreditTransfer,
        PaymentAccountIdentifier = "FR7630006000011234567890189",
    },
    Lines =
    {
        new InvoiceLine
        {
            Quantity = 10,
            UnitCode = UnitCodes.Hour,
            Item = new ItemInformation { Name = "Prestation de conseil" },
            PriceDetails = new PriceDetails { NetPrice = 120m },
            VatInformation = new LineVatInformation { CategoryCode = VatCategoryCode.S, Rate = 20 },
        },
    },
};

var pdf = await client.CreateFacturXAsync(invoice, new FacturXOptions
{
    Language = PdfLanguage.Fr,
    Rules = { FacturXRuleSets.BrFr },
});
await pdf.SaveAsync(pdf.FileName ?? "facture.pdf");

Set InvoiceDocument.SpecificationId to a value from FacturXProfiles to create a profile other than EN 16931, for example FacturXProfiles.ExtendedCtcFr or FacturXProfiles.Basic.

Handle a refused invoice

When the data cannot produce a compliant invoice, CreateFacturXAsync throws InvoiceXmlApiException with every violated rule and the JSON path of the field to correct.

try
{
    var pdf = await client.CreateFacturXAsync(invoice);
}
catch (InvoiceXmlApiException ex) when (ex.IsValidationError)
{
    foreach (var finding in ex.Findings)
        Console.WriteLine($"[{finding.Rule}] {finding.Message} ({string.Join(", ", finding.Fields)})");
}

Branded PDFs, or your own layout

var pdf = await client.CreateFacturXAsync(invoice, new FacturXOptions
{
    Language = PdfLanguage.Fr,
    BrandColor = "#0F766E",
    LogoUrl = "https://example.com/logo.png",
});

// Keep your existing PDF layout: the API embeds the generated XML into it.
var hybrid = await client.CreateFacturXAsync(invoice, new FacturXOptions { PdfUrl = "https://example.com/facture-1234.pdf" });

// Or combine a PDF and a CII XML you already have.
var embedded = await client.EmbedFacturXAsync(File.ReadAllBytes("facture.pdf"), File.ReadAllBytes("factur-x.xml"));

Validate incoming invoices

A completed validation always returns a result. An invalid invoice is not an exception: check Valid.

using var file = File.OpenRead("facture-fournisseur.pdf");
var result = await client.ValidateFacturXAsync(file, "facture-fournisseur.pdf", rules: new[] { FacturXRuleSets.BrFr });

if (result.Valid)
{
    Console.WriteLine($"Valid Factur-X, profile {result.Data?.Profile}");
}
else
{
    foreach (var error in result.Errors)
        Console.WriteLine($"[{error.Rule}] ({error.Layer}) {error.Message}");
}

Leave out rules to check against the declared profile only. result.Report lists every invoice field with its value and the findings that concern it, ready for a review screen.

Read invoices and attachments

// Factur-X PDF or CII XML in, the same InvoiceDocument model out.
var received = await client.ExtractJsonAsync(File.ReadAllBytes("facture-fournisseur.pdf"));
Console.WriteLine($"{received.InvoiceNumber} from {received.Seller?.Name}: {received.Totals?.DuePayableAmount} {received.Currency}");

// Embedded supporting documents (timesheets, delivery notes) as one ZIP.
var zip = await client.ExtractAttachmentsAsync(File.ReadAllBytes("facture-fournisseur.pdf"));
await zip.SaveAsync("pieces-jointes.zip");

An extracted InvoiceDocument can be passed straight back to CreateFacturXAsync.

ASP.NET Core and IHttpClientFactory

builder.Services.AddHttpClient<IFacturXClient, FacturXClient>((http, services) =>
    new FacturXClient(http, builder.Configuration["InvoiceXml:ApiKey"]!));

Inject IFacturXClient where you need it, and fake it in your own unit tests. The client never disposes an HttpClient you pass in.

Rate limits and retries

When more requests of your account run at the same time than your plan allows, the API answers HTTP 429 with a Retry-After header. Such a request is not processed and not billed. The client waits the requested interval and retries, up to three times by default:

var client = new FacturXClient(new InvoiceXmlClientOptions
{
    ApiKey = "YOUR_API_KEY",
    MaxRetries = 5,
    MaxRetryDelay = TimeSpan.FromSeconds(60),
});

If the API still answers 429, the client throws InvoiceXmlRateLimitException with the RetryAfter interval. Every method takes a CancellationToken, which also cancels a pending retry wait.

Errors

Any other refused request throws InvoiceXmlApiException with the HTTP StatusCode, the API's numeric ErrorCode (see InvoiceXmlErrorCode), Title, Detail and a TraceId to quote when contacting support. The full list is in the error handling docs.

Endpoints

Method Endpoint Docs
CreateFacturXAsync POST /v1/create/facturx reference
ValidateFacturXAsync POST /v1/validate/facturx reference
EmbedFacturXAsync POST /v1/embed/facturx reference
ExtractJsonAsync POST /v1/extract/json reference
ExtractAttachmentsAsync POST /v1/extract/attachments reference

The complete OpenAPI description is at api.invoicexml.com/v1/openapi, with an interactive explorer at api.invoicexml.com/v1/scalar.

Invoicing German customers too? InvoiceXml.Zugferd.XRechnung covers ZUGFeRD and XRechnung with the same object model.

Support

Questions, or a field you need for your integration? Contact us and we will help you get it working.

License

MIT. See LICENSE.

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 5 10/12/2026
1.0.0 52 10/10/2026