Freelancer Verification via the KVK API: Check If a Dutch Contractor Is Registered
KVKBase Team

Freelancer Verification via the KVK API: Check If a Dutch Contractor Is Registered

Working with Dutch freelancers? Use the KVKBase API to verify KVK registration status before paying invoices or starting contracts — automate compliance in minutes.

kvkapifreelancerverificationcompliancewet-dba

If your business works with Dutch freelancers (zzp’ers), you have a legal obligation to verify that they are genuinely self-employed. Since 2025, the Dutch Tax Authority (Belastingdienst) has actively enforced the Wet DBA (Deregulation Assessment of Employment Relations Act), meaning that companies using unregistered or incorrectly classified freelancers face back-payments of payroll tax and social security contributions.

The first step in any zzp compliance check is simple: is the freelancer actually registered at the Dutch Chamber of Commerce (KVK)? With the KVKBase API, you can automate this check and integrate it directly into your vendor onboarding flow.

Why KVK Verification Matters for Freelancers

Paying an invoice from someone who is not registered as a business can be reclassified as an employment relationship. The consequences include:

  • Back-payment of wage tax (loonbelasting)
  • Social security premium assessments
  • Potential fines for non-compliance

A verified KVK registration does not by itself prove legal self-employment, but it is a required baseline. Without it, you are already on uncertain legal ground.

What the KVKBase API Returns

For freelancer verification, these are the critical fields:

FieldMeaning
naamRegistered business name
rechtsvormLegal form (Eenmanszaak, BV, VOF, etc.)
actiefWhether the business is currently active
startdatumRegistration date
sbiCodeIndustry classification
adresCurrent registered address

A sole trader (rechtsvorm: "Eenmanszaak", actief: true) is the most common structure for Dutch freelancers.

Implementation: Freelancer Verification in Python

import os
import requests

API_KEY=os.env..._URL = "https://api.kvkbase.nl/api/v1"

def verify_freelancer(kvk_number: str) -> dict:
    """
    Verify whether a freelancer is actively registered with the KVK.
    Raises HTTPError if the KVK number does not exist.
    """
    response = requests.get(
        f"{BASE_URL}/kvk/{kvk_number}",
        headers={"x-api-key": API_KEY},
        timeout=10,
    )
    response.raise_for_status()
    data = response.json()

    result = {
        "kvk_number": kvk_number,
        "name": data.get("naam"),
        "legal_form": data.get("rechtsvorm"),
        "active": data.get("actief", False),
        "start_date": data.get("startdatum"),
        "sbi_code": data.get("sbiCode"),
        "verified": False,
        "reason": None,
    }

    if not result["active"]:
        result["reason"] = "Business is no longer registered at the KVK"
        return result

    if not result["legal_form"]:
        result["reason"] = "Legal form unknown"
        return result

    result["verified"] = True
    return result


# Usage
freelancer = verify_freelancer("12345678")

if freelancer["verified"]:
    print(f"✓ {freelancer['name']} ({freelancer['legal_form']}) — active registration confirmed")
else:
    print(f"✗ Verification failed: {freelancer['reason']}")

Not every legal form is equally suitable for freelance work. A sole trader (Eenmanszaak) or private limited company (BV) are the most common. A general partnership (VOF) involves multiple partners, which may require additional scrutiny about who actually performs the work.

ACCEPTED_LEGAL_FORMS = {
    "Eenmanszaak",
    "Besloten Vennootschap",
    "BV",
}

def is_valid_freelancer_form(freelancer: dict) -> bool:
    return freelancer["legal_form"] in ACCEPTED_LEGAL_FORMS

Adjust the set based on your own policy. Some companies also accept VOF entities; others prefer to work exclusively with sole traders or BVs.

Integrating Into Your Vendor Onboarding Flow

The check integrates naturally into a new supplier onboarding process:

def onboard_freelancer(name: str, kvk_number: str, email: str) -> str:
    """
    Onboard a freelancer after KVK verification.
    Returns: 'approved', 'manual_review', or 'rejected'.
    """
    try:
        data = verify_freelancer(kvk_number)
    except requests.HTTPError as e:
        if e.response.status_code == 404:
            return "rejected"  # KVK number does not exist
        raise

    if not data["verified"]:
        log_manual_review(kvk_number, name, data["reason"])
        return "manual_review"

    if not is_valid_freelancer_form(data):
        log_manual_review(kvk_number, name, f"Unusual legal form: {data['legal_form']}")
        return "manual_review"

    save_freelancer({
        "name": data["name"],
        "kvk_number": kvk_number,
        "legal_form": data["legal_form"],
        "email": email,
        "verified_at": datetime.utcnow().isoformat(),
    })

    return "approved"

Periodic Re-certification

A one-time check at onboarding is not enough. Businesses can de-register at any time. Build periodic re-certification into your system for all active freelancers:

from datetime import datetime, timedelta
import time

def recertify_all_freelancers(freelancers: list, max_age_days: int = 90) -> list:
    """
    Check all freelancers to see if their KVK registration is still active.
    Returns a list of freelancers with issues.
    """
    cutoff = datetime.utcnow() - timedelta(days=max_age_days)
    flagged = []

    for f in freelancers:
        last_verified = datetime.fromisoformat(f.get("verified_at", "2000-01-01"))
        if last_verified > cutoff:
            continue  # Recently checked, skip

        result = verify_freelancer(f["kvk_number"])
        time.sleep(0.2)  # Respect rate limits

        if not result["verified"]:
            flagged.append({
                "name": f["name"],
                "kvk_number": f["kvk_number"],
                "issue": result["reason"],
            })

    return flagged

# Run daily or weekly
problems = recertify_all_freelancers(get_all_active_freelancers())
for p in problems:
    send_alert(f"Freelancer {p['name']} ({p['kvk_number']}): {p['issue']}")

Wet DBA: What Employers Need to Know

The Dutch Tax Authority has been enforcing Wet DBA since 2025. A KVK registration does not guarantee correct labour classification, but it is a mandatory starting point. Combine the KVK check with:

  • An approved model agreement (modelovereenkomst)
  • Evidence of genuine independence in the work (no fixed workplace, no authority relationship)
  • The freelancer working for multiple clients

The KVK verification via the KVKBase API is the technical layer. The legal assessment remains a human judgement call.

Summary

  • Verify every new freelancer’s KVK number before starting work or paying invoices
  • Check for actief: true and an appropriate rechtsvorm
  • Build periodic re-certification for existing vendors (every 90 days is a sensible interval)
  • Automate this as part of your vendor onboarding pipeline

Also read: KVK Data for Customer Onboarding for a broader implementation of KVK verification in your client intake process, and KVK Company Status Monitoring for real-time alerts when registration statuses change.