Skip to content
Back to News
Changelog

Dutch invoice rules are now enforced before you send

consoleapinetherlands

The Peppol network enforces nine fatal rules on Dutch suppliers (NL-R-001 through NL-R-009). Until today they were only checked after your invoice was accepted: the API answered 201, and the rejection happened asynchronously on the network — invisible unless you went digging. A Dutch customer hit exactly that wall this week, and frankly, our test coverage for the Netherlands should have caught it first. This release closes the whole family.

Your KVK/OIN is included automatically

When a Dutch supplier's legal-entity identifier is present, NL-R-003 only accepts a KVK or OIN number inside the invoice document. If your legal entity has one registered (scheme 0106 or 0190 on the Peppol identity page), the gateway injects that registered identifier into the outgoing document for you. A payload declaration alone is not enough: the provider renders the supplier identity from the registered legal entity.

Everything else fails fast, with the official rule code

Anything the Dutch rules would reject and we cannot repair now returns an immediate 422 with error: "country_rule_violation", the official rule code (e.g. NL-R-007), a plain-language fix, and a link to the official Peppol documentation for that rule. This covers the missing KVK/OIN, credit notes without an invoice reference, incomplete supplier addresses, missing payment instructions, and the domestic-invoice requirements on the customer side.

POST /v1/validate/server reports the same findings in a new additive countryRules array, so you can catch them before spending a send.

Console warnings at the source

The Peppol identity page now warns when a Dutch legal entity has no KVK/OIN registered, and asks for confirmation before you remove the last one — the one gesture guaranteed to break every subsequent send.

Also fixed: IBAN-only payment details

Invoices that provided paymentIban without an explicit paymentMeans code were rejected by our provider due to an invalid default code on our side. The default is now a proper credit transfer. If you ever worked around this by adding paymentMeans: 30 explicitly, both forms now work.