EN 16931 Peppol BIS
Peppol BIS Billing 3.0: the 59 rules the network adds to EN 16931, and the identifiers an invoice is claimed under.
An invoice can satisfy the standard and still be refused by Peppol. This says so before it is sent.
Install
dependencies:
en16931: ^0.1.2
en16931_peppol: ^0.1.2
Check an invoice
Claim the profile on the invoice, then check it. The standard and the profile are checked together.
import 'package:en16931/en16931.dart';
import 'package:en16931_peppol/en16931_peppol.dart';
final invoice = Invoice.fromLines(
number: '2026-0042',
issueDate: DateTime(2026, 9, 13),
specificationIdentifier: peppolSpecification,
businessProcess: peppolBillingProcess,
buyerReference: 'PO-77812',
seller: const Seller(
name: 'COMAPPS SRL',
vatIdentifier: 'BE0123456789',
electronicAddress: Identifier('0123456749', scheme: Scheme.belgianEnterprise),
address: Address(city: 'Bruxelles', postalCode: '1000', country: 'BE'),
),
buyer: const Buyer(
name: 'Client SA',
electronicAddress: Identifier('0987654394', scheme: Scheme.belgianEnterprise),
address: Address(city: 'Namur', postalCode: '5000', country: 'BE'),
),
lines: [...],
);
for (final violation in validatePeppol(invoice)) {
print(violation);
}
What Peppol adds
Three things an invoice that passes EN 16931 still gets refused for.
An electronic address on both sides. BT-34 and BT-49 are optional in the standard and required here, because they are how the network delivers.
A shorter list of address schemes. Peppol carries 94 of the schemes the standard allows, so a scheme that is perfectly valid under EN 16931 can still be refused.
A national identifier that is really shaped that way. A Belgian enterprise number under scheme 0208 has to pass the modulo 97 check, a GLN its GS1 check digit, an Australian Business Number its modulus 89. A receiver looks its supplier up by that number, and a mistyped one finds nobody.
isBelgianEnterprise('0123456749'); // true
isBelgianEnterprise('0123456789'); // false
Worth knowing up front
Of the 59 rules, 48 are checked here, 6 cannot be broken by an invoice built
with this model, and 5 are about how the XML is put together rather than what
the invoice says. Those five belong to a syntax package, and
peppolForTheSyntax names them with what they ask.
The rule catalogue is read from the artefacts OpenPeppol publishes, so it is complete by construction. A test fails when a rule has no answer.
What it does not do
It says whether an invoice is ready for the network, and nothing else. The model and the rules of the standard are in en16931, the document is written by en16931_ubl or en16931_cii. Which access point puts it on the network is a separate choice, and does not change the document.
License
Released under the MIT licence.
The rule catalogue is generated from the artefacts OpenPeppol publishes, which carry no licence. None of their content is redistributed: what is taken from them is which rules exist, how severe each is and which terms it bears on.
Libraries
- en16931_peppol
- Peppol BIS Billing 3.0, the profile most of Europe sends invoices under.
