Skip to main content
Introducing packages.sweber.dev
Documentation menuValidating invoices

Validating invoices

validateInvoice in detail - input types, options, the result object and how to show errors to people.

import { validateInvoice } from "@sweberdev/summand";

const result = validateInvoice(input, options);

Input

InputTreated as
stringInvoice XML
Uint8Array or ArrayBuffer starting with %PDF-ZUGFeRD / Factur-X PDF; the embedded XML is validated
other Uint8Array or ArrayBufferXML, decoded by its BOM or the encoding of the XML declaration (UTF-8 by default)

validateInvoice is synchronous and never throws for bad input: malformed XML, a PDF without invoice, or a document that is not an invoice come back as an error in the result.

Options

OptionDefaultEffect
ruleSets"auto"Rule sets to apply, e.g. ["en16931-ubl"]. "auto" picks them from the syntax and profile, see Profiles.
xrechnungfalseApply the XRechnung rules even if the invoice does not declare XRechnung. Useful when you receive invoices as a German public buyer.
extended"lenient"ZUGFeRD / Factur-X EXTENDED: report EN 16931 violations as warnings ("lenient") or as errors ("strict").
leitwegIdtrueWarn when the buyer reference looks like a Leitweg-ID but has wrong check digits.
includeXmlfalseReturn the validated XML in result.xml (handy for PDFs).

The result

FieldContent
validtrue when errors is empty
syntax"ubl-invoice", "ubl-creditnote" or "cii"
profileid, label, the specification identifier (BT-24) and whether the profile is EN 16931 compliant
sourcetype ("xml" or "pdf"), the name of the embedded file and the conformance level from the PDF metadata
ruleSetsApplied rule sets with name, version, source and licence
errors, warnings, infosMessages, see below
summaryInvoice number, type, dates, currency, buyer reference, seller and buyer (name, VAT ID, country), totals and the number of lines
durationMsTime taken

Each message has:

FieldExample
id"BR-CO-15", "BR-DE-15", "UBL-CR-646", "SUM-PDF"
severity"error", "warning" or "info"
messageThe rule's text as published (EN 16931 rules in English, XRechnung rules in German)
locationXPath of the element, e.g. /Invoice/cac:InvoiceLine[2]/cac:Price
lineLine in the XML
ruleSet"en16931-ubl", "xrechnung-cii", … or "summand"
evaluationErrorSet when the rule could not be evaluated, e.g. an amount that is not a number. The rule then counts as failed.

Rule ids starting with SUM- are Summand's own checks:

IdMeaning
SUM-XMLThe XML is not well-formed
SUM-FORMATNot a UBL or CII invoice, or ZUGFeRD 1.0
SUM-PDFThe PDF cannot be read or has no embedded invoice
SUM-PROFILEMINIMUM or BASIC WL (error), or an unknown specification identifier (warning)
SUM-EXTENDEDInfo that EXTENDED violations were reported as warnings
SUM-PDF-LEVELThe PDF metadata declares a different profile than the XML
SUM-LEITWEGThe buyer reference looks like a Leitweg-ID but its check digits are wrong

Showing errors to people

Rule texts are written for developers. For an upload form, a short summary and the first few messages usually work best:

const result = validateInvoice(bytes);
if (!result.valid) {
  return {
    title: `This ${result.profile?.label ?? "file"} is not a valid e-invoice`,
    details: result.errors.slice(0, 5).map((e) => `${e.id}: ${e.message}`),
  };
}

Summand Pro renders the invoice and the report as a readable HTML page.

Errors in rules and the engine

If a rule fires where you think it should not, compare with the KoSIT validator and open an issue with the invoice (anonymised). The bundled rule sets are listed in Rule sets.