Versions and Release Notes
Here you'll find the most important changes in the current and upcoming FactoorSharp versions.
Version 19.1.1
CurrentVersion 19.1.1 fixes several bugs in writing ZUGFeRD 2.0/2.5 and UBL invoices and extends validation for Spanish and Italian invoices.
What's new in detail:
-
Line total amount now calculated correctly for ZUGFeRD 2.5 (BT-131) CoreWhen the line total amount was left unset, ZUGFeRD 2.5 used to write 0 instead of calculating it from unit price and quantity like 2.0, 2.4 and UBL do. Invoices with an explicitly set amount were always correct.
-
VAT in accounting currency now correct in UBL too (BT-111, BT-6) CoreThe VAT amount in the accounting currency was never written to UBL and not reliably recognized when reading it back. Both now work correctly, including for XRechnung in UBL format.
-
No more disallowed exemption reasons in the VAT breakdown (BT-120, BT-121) CoreEN 16931 forbids an exemption reason in the VAT breakdown for the tax categories standard rate, zero rated, IGIC and IPSI. Until now this was only observed for zero rated, and not at all in UBL.
-
ZUGFeRD 2.0 catches up on electronic address and line exemption (BT-34, BT-49, BT-X-96, BT-X-97) CoreThe electronic address was not written for any party in ZUGFeRD 2.0, and the line-level exemption reason was missing as well. Both are now written and read, just like in 2.4 and 2.5.
-
Spain: calculation checks and FACe mode for Facturae ValidationLocal validation now checks Facturae invoices for correct line, batch and invoice totals, the NIF check digit and the signature policy. The new
CheckFACeRequirementsoption additionally checks the stricter reception requirements of the Spanish public-sector entry point FACe.
// Additionally check a Facturae invoice against the reception requirements of FACe // (the entry point for invoices to Spanish public administrations) ValidationResult result = await Validator.ValidateAsync("invoice.xsig", new ValidationOptions { CheckFACeRequirements = true }); ' Additionally check a Facturae invoice against the reception requirements of FACe ' (the entry point for invoices to Spanish public administrations) Dim result As ValidationResult = Await Validator.ValidateAsync("invoice.xsig", New ValidationOptions With { .CheckFACeRequirements = True }) -
Italy: FatturaPA schema updated ValidationThe schema for the "fattura ordinaria" was updated to version 1.2.3; the simplified "fattura semplificata" invoice is now validated as well.
-
Crash after QuestPDF update fixed VisualizationAfter updating QuestPDF, outdated native libraries left behind in the build output could cause a crash while rendering. They are now removed automatically.
Version 19.1.0
Version 19.1.0 renders invoices as HTML, supports advance payments and VAT in a foreign currency, extracts text from PDFs together with its position, and detects the invoice format even more reliably.
What's new in detail:
-
Display invoices as HTML VisualizationInvoices can now be rendered as HTML as well as PDF – either as a standalone page or as a building block you embed directly into your web or desktop application. Delivery note, order reference and product characteristics are now shown too.
// Invoice as a standalone HTML page string html = InvoiceVisualizer.RenderHtml(invoice); // Or as a fragment to embed into an existing page string fragment = InvoiceVisualizer.RenderHtml(invoice, options: new HtmlRenderOptions { Standalone = false }); // The PDF output is now called RenderPdf() InvoiceVisualizer.RenderPdf(invoice, "invoice.pdf"); ' Invoice as a standalone HTML page Dim html As String = InvoiceVisualizer.RenderHtml(invoice) ' Or as a fragment to embed into an existing page Dim fragment As String = InvoiceVisualizer.RenderHtml(invoice, options:=New HtmlRenderOptions With {.Standalone = False}) ' The PDF output is now called RenderPdf() InvoiceVisualizer.RenderPdf(invoice, "invoice.pdf") -
Itemize advance payments (BG-X-45) CoreAdvance payments already received can be listed individually in the EXTENDED profile – with amount, payment date, included VAT and a reference to the related prepayment invoice.
// Advance payment with included VAT and a reference to the prepayment invoice invoice.AddAdvancePayment(2975m, new DateTime(2026, 6, 7)) .SetInvoiceReferencedDocument("PI-2026-0601", new DateTime(2026, 6, 1), InvoiceType.PartialInvoice) .AddIncludedTradeTax(475m, 19m, TaxTypes.VAT, TaxCategoryCodes.S); ' Advance payment with included VAT and a reference to the prepayment invoice invoice.AddAdvancePayment(2975D, New DateTime(2026, 6, 7)) _ .SetInvoiceReferencedDocument("PI-2026-0601", New DateTime(2026, 6, 1), InvoiceType.PartialInvoice) _ .AddIncludedTradeTax(475D, 19D, TaxTypes.VAT, TaxCategoryCodes.S) -
VAT in a foreign currency with exchange rate (BG-X-41) CoreFor invoices in a foreign currency, you now set the VAT accounting currency (BT-6), the VAT amount in that currency (BT-111) and the exchange rate in a single step – exactly as EN 16931 expects.
// Invoice in USD, VAT additionally stated in euros invoice.SetTaxCurrencyExchange(taxTotalInAccountingCurrency: 175.08m, accountingCurrency: CurrencyCodes.EUR, conversionRate: 0.9215m, conversionRateTimestamp: new DateTime(2026, 9, 1)); ' Invoice in USD, VAT additionally stated in euros invoice.SetTaxCurrencyExchange(taxTotalInAccountingCurrency:=175.08D, accountingCurrency:=CurrencyCodes.EUR, conversionRate:=0.9215D, conversionRateTimestamp:=New DateTime(2026, 9, 1)) -
Electronic address for every party (BT-34, BT-49, BT-X-160) CoreNot just seller and buyer, but also the ship-to party and other parties can now carry an electronic address, such as an email address. The information is fully preserved when reading invoices.
// Electronic address of the ship-to party invoice.ShipTo.ElectronicAddress = new ElectronicAddress { Address = "goods-in@customer.com", ElectronicAddressSchemeID = ElectronicAddressSchemeIdentifiers.ElectronicMailSmtp }; ' Electronic address of the ship-to party invoice.ShipTo.ElectronicAddress = New ElectronicAddress With { .Address = "goods-in@customer.com", .ElectronicAddressSchemeID = ElectronicAddressSchemeIdentifiers.ElectronicMailSmtp } -
Extract text from PDFs with its position PDFYou can now extract text runs from the visible content of a PDF together with page, position and font size, for example to pick a value from a specific table column. Plain text extraction also reproduces the page layout much more faithfully.
foreach (PdfTextFragment fragment in PdfUtils.ExtractTextFragments("invoice.pdf")) { // Page, position in points and text Console.WriteLine($"Page {fragment.PageNumber}, x={fragment.X:0}, y={fragment.Y:0}: {fragment.Text}"); } For Each fragment As PdfTextFragment In PdfUtils.ExtractTextFragments("invoice.pdf") ' Page, position in points and text Console.WriteLine($"Page {fragment.PageNumber}, x={fragment.X:0}, y={fragment.Y:0}: {fragment.Text}") Next -
More details for invoice lines (BT-158-1, BT-X-98) CoreItems can now be classified using every classification scheme defined by EN 16931, such as UNSPSC or eCl@ss. In the EXTENDED profile you can also state the total of allowances and charges per line.
// Classify the item by UNSPSC item.AddDesignatedProductClassification(DesignatedProductClassificationClassCodes.TST, classCode: "43211503"); // Total of allowances and charges on this line (EXTENDED only) item.TotalAllowanceChargeAmount = 12.50m; ' Classify the item by UNSPSC item.AddDesignatedProductClassification(DesignatedProductClassificationClassCodes.TST, classCode:="43211503") ' Total of allowances and charges on this line (EXTENDED only) item.TotalAllowanceChargeAmount = 12.5D -
More reliable invoice format detection CoreWhether a file is a ZUGFeRD/Factur-X or a UBL invoice is now determined unambiguously from the structure of the document. As a result, invoices from senders that state no or a not yet known specification identifier (BT-24) can be read as well.
-
Current XRechnung validation rules 2.6.0 ValidationLocal validation now uses the current KoSIT rules 2.6.0 for XRechnung 3.0.2. Please note: a violation of rule BR-TMP-2 is now reported as an error instead of a warning. In addition, invoices whose XML is embedded uncompressed in the PDF are validated, and unreadable attachments show up as a clear validation finding.
-
More thorough checks of amounts and totals ValidationThe built-in invoice check now verifies line amounts, allowances and charges, VAT amounts and the amount due much more precisely against the EN 16931 rules – including advance payments, rounding amounts and price base quantities (BT-149).
-
Bug fixes for valid invoices CoreSeveral bugs that could lead to invalid or incomplete invoices have been fixed: no exemption reason is written for zero-rated supplies (category Z) anymore (BR-Z-10), MINIMUM invoices no longer contain an electronic address that is not allowed there, empty IBAN details are omitted, UBL prices keep all their decimal places, and the receiving advice reference (BT-15) is read and written correctly in UBL.
Version 19.0
Version 19.0 introduces free, local invoice validation, improves how XRechnung price details and PDF attachments are handled, and hardens FactoorSharp against crafted documents.
What's new in detail:
-
Validate invoices offline ValidationInvoices can now be validated directly in your application, with no internet connection and no extra cost per check. The more thorough check with additional online-service tests is still available whenever you need it.
// Default: validation through the online service (with Valitool/VeraPDF extra checks) ValidationResult result = FacturXValidator.Validate("invoice.pdf"); // New: validation runs entirely offline, no internet connection and no quota needed ValidationResult localResult = FacturXValidator.Validate("invoice.pdf", extendedValidation: false); ' Default: validation through the online service (with Valitool/VeraPDF extra checks) Dim result As ValidationResult = FacturXValidator.Validate("invoice.pdf") ' New: validation runs entirely offline, no internet connection and no quota needed Dim localResult As ValidationResult = FacturXValidator.Validate("invoice.pdf", extendedValidation:=False) -
Support for ZUGFeRD 2.5.2 CoreInvoices can now be created in the latest ZUGFeRD format.
-
More flexibility with international formats (BT-24) CoreBesides XRechnung, related formats such as Peppol BIS Billing 3.0 can now be flagged correctly too – handy for businesses with European trading partners.
invoice.SpecificationIdentifier = SpecificationIdentifiers.PeppolBisBilling30; invoice.SpecificationIdentifier = SpecificationIdentifiers.PeppolBisBilling30 -
Reference to goods receipt documents (BT-15-00) CoreInvoices can now be linked to the matching goods receipt document.
invoice.SetReceivingAdviceReferencedDocument("WE-2026-0142"); invoice.SetReceivingAdviceReferencedDocument("WE-2026-0142") -
Add further attachments to a Factur-X PDF PDFExtra documents such as terms and conditions or calculations can now be attached to a Factur-X PDF file.
byte[] terms = File.ReadAllBytes("terms.pdf"); PdfUtils.AddAttachment("invoice.pdf", "terms.pdf", terms); Dim terms As Byte() = File.ReadAllBytes("terms.pdf") PdfUtils.AddAttachment("invoice.pdf", "terms.pdf", terms) -
PDF attachments are now reliably preserved PDFExisting attachments on a PDF invoice, such as delivery notes or calculations which are attached to the original PDF file, are no longer lost when adding Factur-X information and creating the PDF-A/3 file – and their description is now preserved too.
-
More accurate pricing for XRechnung invoices (BT-147, BT-148) CoreFixed a bug where the gross price per line item and line-level discounts were sometimes read incorrectly from XRechnung documents.
-
Correct tax category on line-item discounts (BT-95) CoreThe tax category of a discount or surcharge on an invoice line wasn't written in the correct format when saving to ZUGFeRD 2.5 – this is now fixed.
-
More reliable error messages during online validation ValidationErrors such as oversized files or an exhausted validation quota are now reported more clearly and can be caught individually in your own application.
try { var result = FacturXValidator.Validate("invoice.pdf"); } catch (FileTooLargeException) { // File exceeds the allowed size } catch (QuotaExceededException) { // Validation quota used up } Try Dim result = FacturXValidator.Validate("invoice.pdf") Catch ex As FileTooLargeException ' File exceeds the allowed size Catch ex As QuotaExceededException ' Validation quota used up End Try -
Better protection when reading documents SecurityReading invoice files is now hardened against crafted, malicious files – both against known XML attack techniques and against excessive memory usage on very large files.
Version 18.5
Version 18.5 introduces support for invoicing periods, improves how payment terms are handled, and fixes several bugs around ZUGFeRD 2.0 and 2.5.
Highlights
Version 18.4
Version 18.4 introduces a new visualization component and fixes a number of bugs in working with ZUGFeRD 2.5.
Highlights
Version 18.3
Version 18.3 adds support for ZUGFeRD 2.5 and extends validation to Italian and Spanish invoices.
Highlights
Version 18.2
Version 18.2 extends PDF processing further and improves quota management for validation.
Highlights
Version 18.1
Version 18.1 extends FactoorSharp's PDF processing further and adds signing support for all .NET target platforms.
Highlights
Version 18.0
Version 18.0 is the first published release of FactoorSharp. It forms the stable foundation for working with ZUGFeRD, Factur-X and XRechnung in modern .NET applications.