Netherlands ๐ณ๐ฑ
E-invoicing requirements and best practices for the Netherlands.
Overviewโ
| Aspect | Details |
|---|---|
| B2G Mandate | Required for central government since 2017 |
| B2B Status | Encouraged, rapidly growing |
| Preferred CIUS | Peppol BIS 3.0 (NLCIUS optional) |
| Primary Scheme | 0106 (KVK) |
| Government Portal | DigiInkoop |
Identifier Schemesโ
KVK Number (0106) โ Recommendedโ
The Chamber of Commerce (Kamer van Koophandel) number:
# Format: 8 digits
participant = {
"scheme": "0106",
"identifier": "12345678", # KVK number
"name": "Example BV",
"country": "NL"
}
Validation:
- Exactly 8 digits
- No check digit
- Look up at kvk.nl
OIN (0190) โ Governmentโ
Overheidsidentificatienummer for government entities:
# Format: 20 digits
participant = {
"scheme": "0190",
"identifier": "00000001234567890000",
"name": "Rijksoverheid Department",
"country": "NL"
}
When to use:
- Sending to Dutch government (B2G)
- Central and local government entities
Government E-invoicing (B2G)โ
DigiInkoopโ
All invoices to the Dutch central government go through DigiInkoop:
- Register your KVK on Peppol
- Send to government OIN via Peppol
- Invoice delivered to DigiInkoop
- Processed by the receiving ministry
Required Fields for B2Gโ
<!-- Buyer reference (required for government) -->
<cbc:BuyerReference>123456789</cbc:BuyerReference>
<!-- Order reference -->
<cac:OrderReference>
<cbc:ID>PO-2024-00123</cbc:ID>
</cac:OrderReference>
<!-- Contract reference (if applicable) -->
<cac:ContractDocumentReference>
<cbc:ID>CONTRACT-2024-001</cbc:ID>
</cac:ContractDocumentReference>
Common Government OINsโ
| Entity | OIN |
|---|---|
| Rijksoverheid (general) | Check DigiInkoop |
| Belastingdienst | Look up per department |
Invoice Requirementsโ
Standard Fieldsโ
<Invoice>
<!-- Dutch company must have KVK -->
<cac:AccountingSupplierParty>
<cac:Party>
<cbc:EndpointID schemeID="0106">12345678</cbc:EndpointID>
<!-- VAT number if applicable -->
<cac:PartyTaxScheme>
<cbc:CompanyID>NL123456789B01</cbc:CompanyID>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:PartyTaxScheme>
<cac:PartyLegalEntity>
<cbc:RegistrationName>Company BV</cbc:RegistrationName>
<cbc:CompanyID schemeID="0106">12345678</cbc:CompanyID>
</cac:PartyLegalEntity>
</cac:Party>
</cac:AccountingSupplierParty>
</Invoice>
Registration number: KVK or OINโ
Give a Dutch party's Chamber of Commerce number (KVK, 8 digits) as registration_number, or, for a
government body, its OIN (20 digits). Spaces, dots and dashes are dropped. GoRoute writes it as the
party's legal registration identifier (cac:PartyLegalEntity/cbc:CompanyID) and as its party
identifier (cac:PartyIdentification/cbc:ID), under scheme 0106 for a KVK number and 0190 for
an OIN. A Dutch seller's legal registration identifier must carry one of those two schemes
(NL-R-003), and so must a Dutch buyer's when the seller is Dutch too (NL-R-005).
A party with no registration_number and a 0106 or 0190 Peppol ID gets that number as its
legal registration identifier. The VAT number (btw-id) is never used: it does not contain the KVK
number.
Any other value is not read as a KVK number or an OIN: an RSIN (9 digits), a branch number
(12 digits), a KVK number that lost its leading zero, or one written with a "KvK" label. If a Dutch
seller's registration_number is such a value and its Peppol ID gives neither number,
POST /api/v1/invoices answers validation_failed with BUS_048, and nothing is sent. Between two
Dutch parties the same applies to the buyer's. Correct the number, or leave registration_number
out. A document sent without these checks (for example by a marketplace or ERP connector, or in a
batch upload) goes out with no legal registration identifier for that party instead. The number is
still written as its party identifier.
VAT Requirementsโ
Dutch VAT format: NL + 9 digits + B + 2 digits
# Valid Dutch VAT examples
valid_vat = [
"NL123456789B01",
"NL987654321B02"
]
BTW Codesโ
The Code column is the VAT category, which is a different field from the percentage: the
category says why a rate applies, the percentage says what it is. Both Dutch positive rates
are category S carrying their own percentage.
| Code | Rate | Description |
|---|---|---|
| S | 21% | Standard rate |
| S | 9% | Reduced rate |
| Z | 0% | Zero rate (exports) |
| E | 0% | Exempt |
| G | 0% | Free export item, VAT not charged |
| K | 0% | Intra-community supply of goods or services within the EEA |
AA is rejected, and G is not intra-communityEarlier revisions of this page gave AA for the 9% rate and labelled G "intra-community".
AA is not a permitted VAT category at all โ EN 16931 allows only AE, B, E, G, K,
L, M, O, S and Z
(UNCL5305) โ and rules BR-CL-17
and BR-CL-18 reject anything else. G is "free export item, VAT not charged" and needs an
exemption reason (BR-G-10). An intra-community supply inside the EEA is K, and it carries
its own requirements: the seller's and the buyer's VAT identifiers (BR-IC-02), a delivery date
or invoicing period (BR-IC-11), and a deliver-to country (BR-IC-12).
Payment detailsโ
A Dutch seller's invoice with an amount due must carry a payment instruction (NL-R-007),
whoever the buyer is. An invoice sent with no payment details at all is written as a credit
transfer: into the seller's account on file (seller.bank_account), or, when there is none,
with code 1, "instrument not defined".
Between a Dutch seller and a Dutch buyer, the payment means code must be 30, 48, 49, 57, 58 or 59
(NL-R-008), and a credit transfer (30) must name the account to pay into (BR-61). So for an
invoice between two Dutch parties paid by credit transfer, or sent with no payment details, give
the account in payment.bank_account.iban, or keep it on the seller as seller.bank_account.
Cash, cheque and other have no code that NL-R-008 allows, so such an invoice can't be paid that
way: use a credit transfer, a card or a direct debit. In either case POST /api/v1/invoices
answers validation_failed with BUS_045, and nothing is sent.
A credit note between two Dutch parties is sent without a payment instruction when its own would break NL-R-008: no account of its own, or paid out in cash or by cheque. NL-R-007 does not ask for one on a credit note. Its due date and payment reference are then left out too, because a credit note carries both only inside that instruction. The seller's own account is never written on a credit note.
Self-billing documents are not checked against the Dutch rules, neither the payment rules above nor the registration number rules: the Peppol self-billing rules have no national rules.
Example Invoiceโ
<?xml version="1.0" encoding="UTF-8"?>
<Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2"
xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2">
<cbc:CustomizationID>urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0</cbc:CustomizationID>
<cbc:ProfileID>urn:fdc:peppol.eu:2017:poacc:billing:01:1.0</cbc:ProfileID>
<cbc:ID>NL-INV-2024-00123</cbc:ID>
<cbc:IssueDate>2024-01-15</cbc:IssueDate>
<cbc:DueDate>2024-02-15</cbc:DueDate>
<cbc:InvoiceTypeCode>380</cbc:InvoiceTypeCode>
<cbc:DocumentCurrencyCode>EUR</cbc:DocumentCurrencyCode>
<!-- For government invoices -->
<cbc:BuyerReference>PO-12345</cbc:BuyerReference>
<!-- Dutch Seller -->
<cac:AccountingSupplierParty>
<cac:Party>
<cbc:EndpointID schemeID="0106">12345678</cbc:EndpointID>
<cac:PartyName>
<cbc:Name>Voorbeeld BV</cbc:Name>
</cac:PartyName>
<cac:PostalAddress>
<cbc:StreetName>Kalverstraat 1</cbc:StreetName>
<cbc:CityName>Amsterdam</cbc:CityName>
<cbc:PostalZone>1012AB</cbc:PostalZone>
<cac:Country>
<cbc:IdentificationCode>NL</cbc:IdentificationCode>
</cac:Country>
</cac:PostalAddress>
<cac:PartyTaxScheme>
<cbc:CompanyID>NL123456789B01</cbc:CompanyID>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:PartyTaxScheme>
<cac:PartyLegalEntity>
<cbc:RegistrationName>Voorbeeld BV</cbc:RegistrationName>
<cbc:CompanyID schemeID="0106">12345678</cbc:CompanyID>
</cac:PartyLegalEntity>
</cac:Party>
</cac:AccountingSupplierParty>
<!-- Dutch Buyer -->
<cac:AccountingCustomerParty>
<cac:Party>
<cbc:EndpointID schemeID="0106">87654321</cbc:EndpointID>
<cac:PartyName>
<cbc:Name>Klant BV</cbc:Name>
</cac:PartyName>
<cac:PostalAddress>
<cbc:StreetName>Damrak 100</cbc:StreetName>
<cbc:CityName>Amsterdam</cbc:CityName>
<cbc:PostalZone>1012LP</cbc:PostalZone>
<cac:Country>
<cbc:IdentificationCode>NL</cbc:IdentificationCode>
</cac:Country>
</cac:PostalAddress>
<cac:PartyLegalEntity>
<cbc:RegistrationName>Klant BV</cbc:RegistrationName>
</cac:PartyLegalEntity>
</cac:Party>
</cac:AccountingCustomerParty>
<!-- Payment with Dutch IBAN -->
<cac:PaymentMeans>
<cbc:PaymentMeansCode>30</cbc:PaymentMeansCode>
<cac:PayeeFinancialAccount>
<cbc:ID>NL12ABCD3456789012</cbc:ID>
<cbc:Name>Voorbeeld BV</cbc:Name>
</cac:PayeeFinancialAccount>
</cac:PaymentMeans>
<cac:TaxTotal>
<cbc:TaxAmount currencyID="EUR">21.00</cbc:TaxAmount>
<cac:TaxSubtotal>
<cbc:TaxableAmount currencyID="EUR">100.00</cbc:TaxableAmount>
<cbc:TaxAmount currencyID="EUR">21.00</cbc:TaxAmount>
<cac:TaxCategory>
<cbc:ID>S</cbc:ID>
<cbc:Percent>21</cbc:Percent>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:TaxCategory>
</cac:TaxSubtotal>
</cac:TaxTotal>
<cac:LegalMonetaryTotal>
<cbc:LineExtensionAmount currencyID="EUR">100.00</cbc:LineExtensionAmount>
<cbc:TaxExclusiveAmount currencyID="EUR">100.00</cbc:TaxExclusiveAmount>
<cbc:TaxInclusiveAmount currencyID="EUR">121.00</cbc:TaxInclusiveAmount>
<cbc:PayableAmount currencyID="EUR">121.00</cbc:PayableAmount>
</cac:LegalMonetaryTotal>
<cac:InvoiceLine>
<cbc:ID>1</cbc:ID>
<cbc:InvoicedQuantity unitCode="HUR">10</cbc:InvoicedQuantity>
<cbc:LineExtensionAmount currencyID="EUR">100.00</cbc:LineExtensionAmount>
<cac:Item>
<cbc:Name>Adviesuren</cbc:Name>
<cac:ClassifiedTaxCategory>
<cbc:ID>S</cbc:ID>
<cbc:Percent>21</cbc:Percent>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:ClassifiedTaxCategory>
</cac:Item>
<cac:Price>
<cbc:PriceAmount currencyID="EUR">10.00</cbc:PriceAmount>
</cac:Price>
</cac:InvoiceLine>
</Invoice>
Validationโ
GoRoute validates against Dutch requirements:
response = requests.post(
"https://app.goroute.ai/peppol-api/api/v1/documents/validate",
headers={"X-API-Key": "your_api_key"},
json={
"document": invoice_xml, # UBL XML string
"profile": "peppol-bis3"
}
)
# Dutch-specific checks include:
# - KVK number format validation
# - Dutch VAT number format
# - OIN format for government
# - IBAN format for Dutch banks
B2B Adoptionโ
While not mandated, B2B e-invoicing is growing rapidly:
- Large enterprises: Most accept Peppol
- SME: Growing adoption via accounting software
- Recommended: Register on Peppol to receive invoices
Resourcesโ
Next Stepsโ
Further readingโ
- Networks we bridge to
- 2026 e-invoicing mandate tracker โ every country, one page
- How to choose a Peppol Access Point
- One API for multi-country e-invoicing
Ready to build? The free developer sandbox gives you test credentials and a registered participant, provisioned within 24 hours on business days. Recorded ERP integration walkthroughs are on the tutorials page.