E-Invoicing 2026: How KVK Data Prevents Errors in Your Invoice Workflow
Mandatory e-invoicing is coming for more Dutch businesses. Use KVK data via the KVKBase API to automatically validate invoice details and prevent costly mistakes.
E-invoicing is no longer optional for a growing number of Dutch businesses. Government bodies and large buyers are making it mandatory, and the EU is accelerating adoption through the Peppol network. At the same time, one of the most common causes of invoice problems remains surprisingly simple: incorrect company details.
An invoice sent to the wrong address, an outdated business name, or a VAT number that is no longer valid can delay payment by weeks. With the KVKBase API, you can always retrieve the most up-to-date details at the moment of invoicing, directly from the Dutch Trade Register.
Why e-invoicing raises the bar for data quality
With a standard PDF invoice, a small error in the company name might only be noticed when a payment reminder bounces. E-invoicing via Peppol or UBL works differently. The invoice is processed automatically by machines. If the name or address does not match what the recipient has in their system, the invoice can be rejected immediately.
This means that data that was good enough for paper-based processes for years has suddenly become critical. A customer who changed their company name two years ago, a branch that relocated, a KVK number now linked to a different legal entity: you need to know about these changes before you send an invoice.
What a valid e-invoice requires
A valid e-invoice requires several fields that must be accurate at all times:
- Full registered company name (as registered with the KVK)
- Registered office address (street, house number, postcode, city)
- KVK number (8 digits, valid)
- VAT number (NL + 9 digits + B01/B02, valid in VIES)
- Legal form (relevant for legal context and salutation)
All of these fields can be retrieved in real time from the KVKBase API. Here is an example of how to do this when creating an invoice:
import os
import requests
API_KEY = os.environ["KVKBASE_API_KEY"]
BASE_URL = "https://api.kvkbase.nl/api/v1"
def get_invoice_data(kvk_number: str) -> dict:
"""Retrieve current invoice details for a company."""
response = requests.get(
f"{BASE_URL}/kvk/{kvk_number}",
headers={"x-api-key": API_KEY}
)
response.raise_for_status()
data = response.json()
address = data.get("adres", {})
return {
"kvk_number": kvk_number,
"company_name": data.get("naam"),
"legal_form": data.get("rechtsvorm"),
"street": address.get("straat"),
"house_number": address.get("huisnummer"),
"postcode": address.get("postcode"),
"city": address.get("stad"),
"active": data.get("actief", True),
}
# Use when creating an invoice
invoice_data = get_invoice_data("12345678")
if not invoice_data["active"]:
raise ValueError(f"Company {invoice_data['company_name']} is no longer active in the KVK register")
print(f"Invoice data for: {invoice_data['company_name']}")
print(f"Address: {invoice_data['street']} {invoice_data['house_number']}, {invoice_data['postcode']} {invoice_data['city']}")
Live validation when entering a KVK number
In many accounting and invoicing systems, you type the KVK number of a new customer. At that point, you can validate immediately and auto-fill the remaining fields. This eliminates typos and ensures the invoice is complete from the start.
// Frontend validation on KVK number input
async function validateAndFillCompany(kvkNumber) {
if (kvkNumber.length !== 8 || isNaN(kvkNumber)) {
showError("Please enter a valid 8-digit KVK number");
return;
}
const response = await fetch(`/api/kvk-lookup?kvk=${kvkNumber}`);
if (!response.ok) {
showError("Company not found in the KVK register");
return;
}
const data = await response.json();
if (!data.active) {
showWarning(`${data.company_name} has been deregistered from the KVK register`);
return;
}
// Auto-fill the form
document.getElementById("company_name").value = data.company_name;
document.getElementById("street").value = `${data.street} ${data.house_number}`;
document.getElementById("postcode").value = data.postcode;
document.getElementById("city").value = data.city;
document.getElementById("kvk_number").value = kvkNumber;
showSuccess("Company details retrieved from the KVK register");
}
Syncing data for existing customers
You validate new customers during onboarding, but existing customers matter just as much. Addresses change, names are updated, branches close. A periodic sync ensures you never invoice against stale data.
from typing import List
import time
def sync_customer_data(customers: List[dict]) -> List[dict]:
"""
Sync customer data with current KVK information.
Returns a list of customers whose data has changed.
"""
updated = []
for customer in customers:
kvk = customer.get("kvk_number")
if not kvk:
continue
try:
fresh = get_invoice_data(kvk)
changes = {}
field_map = {
"company_name": "name_in_crm",
"street": "street_in_crm",
"postcode": "postcode_in_crm",
"city": "city_in_crm",
}
for api_field, crm_field in field_map.items():
api_val = (fresh.get(api_field) or "").strip()
crm_val = (customer.get(crm_field) or "").strip()
if api_val and api_val.lower() != crm_val.lower():
changes[crm_field] = {
"old": crm_val,
"new": api_val,
}
if changes:
updated.append({
"kvk_number": kvk,
"company": fresh["company_name"],
"changes": changes,
})
time.sleep(0.2) # Respect rate limits
except Exception as e:
print(f"Error syncing {kvk}: {e}")
return updated
# Example usage
changes = sync_customer_data(my_customer_list)
for change in changes:
print(f"Customer {change['company']} has updated details: {change['changes']}")
Linking the VAT number to KVK data
For e-invoicing, you need both the KVK number and the VAT number. The KVKBase API gives you the KVK number as your starting point. The corresponding VAT number can then be validated through VIES. Together, they give you a complete picture of your customer’s fiscal and legal status.
An automated invoicing flow looks like this:
- Customer enters their KVK number during checkout or onboarding
- API retrieves name, address, and legal form
- VIES check validates the provided VAT number
- All fields are filled in automatically
- On each invoice, the system checks whether the details are still current
Connecting to Peppol and UBL
If you send invoices via the Peppol network, you are required to fill in several fields correctly. For Dutch companies, the Peppol endpoint ID is typically based on the VAT number or KVK number. Make sure both are accurate before sending an invoice.
The KVKBase API provides the necessary base data. The translation into a UBL invoice structure is handled by your invoicing software, but the source of truth for company details should always be the KVK Trade Register.
Summary
E-invoicing raises the bar for company data quality. With the KVKBase API, you retrieve up-to-date details directly from the Trade Register, at onboarding, at every invoice, and periodically as a sync. This prevents rejections, delays, and disputes over incorrect invoice information.
- Sign up via the KVKBase dashboard and request an API key
- Validate at onboarding, sync periodically
- Combine with VIES VAT validation for a complete picture
Also read: Prefill Dutch Business Details at Checkout for a concrete implementation of autofill in your order process.