Code Examples

Copy-paste examples for every language and framework. All examples are production-ready.

Company Lookup

Fetch complete company data by KVK number. The most common use case.

curl -X GET "https://api.kvkbase.nl/v1/lookup/12345678" \
  -H "Authorization: Bearer YOUR_API_KEY"
// Using fetch (browser or Node.js 18+)
const response = await fetch(
  "https://api.kvkbase.nl/v1/lookup/12345678",
  {
    headers: {
      Authorization: "Bearer YOUR_API_KEY",
    },
  }
);

if (!response.ok) {
  const { error } = await response.json();
  throw new Error(error.message);
}

const company = await response.json();
console.log(company.name);           // "Acme B.V."
console.log(company.address.city);   // "Amsterdam"
console.log(company.vat?.valid);     // true
import requests

response = requests.get(
    "https://api.kvkbase.nl/v1/lookup/12345678",
    headers={"Authorization": "Bearer YOUR_API_KEY"}
)
response.raise_for_status()

company = response.json()
print(company["name"])              # "Acme B.V."
print(company["address"]["city"])   # "Amsterdam"
print(company["vat"]["valid"])      # True
<?php
$ch = curl_init("https://api.kvkbase.nl/v1/lookup/12345678");
curl_setopt_array($ch, [
    CURLOPT_HTTPHEADER => ["Authorization: Bearer YOUR_API_KEY"],
    CURLOPT_RETURNTRANSFER => true,
]);

$response = json_decode(curl_exec($ch), true);
curl_close($ch);

echo $response["name"];             // "Acme B.V."
echo $response["address"]["city"];  // "Amsterdam"
package main

import (
    "encoding/json"
    "fmt"
    "net/http"
)

func main() {
    req, _ := http.NewRequest("GET",
        "https://api.kvkbase.nl/v1/lookup/12345678", nil)
    req.Header.Set("Authorization", "Bearer YOUR_API_KEY")

    resp, err := http.DefaultClient.Do(req)
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()

    var company map[string]interface{}
    json.NewDecoder(resp.Body).Decode(&company)
    fmt.Println(company["name"]) // "Acme B.V."
}
require "net/http"
require "json"

uri = URI("https://api.kvkbase.nl/v1/lookup/12345678")
req = Net::HTTP::Get.new(uri)
req["Authorization"] = "Bearer YOUR_API_KEY"

res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
  http.request(req)
end

company = JSON.parse(res.body)
puts company["name"]              # "Acme B.V."
puts company["address"]["city"]   # "Amsterdam"
using var client = new HttpClient();
client.DefaultRequestHeaders.Add(
    "Authorization", "Bearer YOUR_API_KEY");

var response = await client.GetAsync(
    "https://api.kvkbase.nl/v1/lookup/12345678");
var json = await response.Content.ReadAsStringAsync();

var company = JsonSerializer.Deserialize<JsonElement>(json);
Console.WriteLine(company.GetProperty("name")); // "Acme B.V."

React Form with Auto-fill

A React component that looks up company data when a user enters a KVK number, with loading and error states.

import { useState, useCallback } from "react";

function KvkLookupForm() {
  const [kvk, setKvk] = useState("");
  const [company, setCompany] = useState(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState("");

  const lookup = useCallback(async () => {
    if (kvk.length !== 8) return;
    setLoading(true);
    setError("");

    try {
      const res = await fetch(
        `https://api.kvkbase.nl/v1/lookup/${kvk}`,
        { headers: { Authorization: "Bearer YOUR_API_KEY" } }
      );
      if (!res.ok) {
        const data = await res.json();
        throw new Error(data.error?.message || "Lookup failed");
      }
      setCompany(await res.json());
    } catch (err) {
      setError(err.message);
      setCompany(null);
    } finally {
      setLoading(false);
    }
  }, [kvk]);

  return (
    <form onSubmit={(e) => { e.preventDefault(); lookup(); }}>
      <label htmlFor="kvk">KVK Nummer</label>
      <input
        id="kvk"
        value={kvk}
        onChange={(e) => setKvk(e.target.value)}
        placeholder="12345678"
        maxLength={8}
        pattern="[0-9]{8}"
      />
      <button type="submit" disabled={loading || kvk.length !== 8}>
        {loading ? "Zoeken..." : "Opzoeken"}
      </button>

      {error && <p className="error">{error}</p>}

      {company && (
        <div className="result">
          <p><strong>{company.name}</strong></p>
          <p>{company.address?.street} {company.address?.houseNumber}</p>
          <p>{company.address?.postalCode} {company.address?.city}</p>
          {company.vat && (
            <p>BTW: {company.vat.number} ({company.vat.valid ? "geldig" : "ongeldig"})</p>
          )}
        </div>
      )}
    </form>
  );
}
<template>
  <form @submit.prevent="lookup">
    <label for="kvk">KVK Nummer</label>
    <input
      id="kvk"
      v-model="kvk"
      placeholder="12345678"
      maxlength="8"
    />
    <button :disabled="loading || kvk.length !== 8">
      {{ loading ? "Zoeken..." : "Opzoeken" }}
    </button>

    <p v-if="error" class="error">{{ error }}</p>

    <div v-if="company" class="result">
      <p><strong>{{ company.name }}</strong></p>
      <p>{{ company.address?.street }} {{ company.address?.city }}</p>
      <p v-if="company.vat">
        BTW: {{ company.vat.number }}
        ({{ company.vat.valid ? "geldig" : "ongeldig" }})
      </p>
    </div>
  </form>
</template>

<script setup>
import { ref } from "vue";

const kvk = ref("");
const company = ref(null);
const loading = ref(false);
const error = ref("");

async function lookup() {
  if (kvk.value.length !== 8) return;
  loading.value = true;
  error.value = "";

  try {
    const res = await fetch(
      `https://api.kvkbase.nl/v1/lookup/${kvk.value}`,
      { headers: { Authorization: "Bearer YOUR_API_KEY" } }
    );
    if (!res.ok) throw new Error((await res.json()).error?.message);
    company.value = await res.json();
  } catch (err) {
    error.value = err.message;
    company.value = null;
  } finally {
    loading.value = false;
  }
}
</script>
<script>
  let kvk = "";
  let company = null;
  let loading = false;
  let error = "";

  async function lookup() {
    if (kvk.length !== 8) return;
    loading = true;
    error = "";

    try {
      const res = await fetch(
        `https://api.kvkbase.nl/v1/lookup/${kvk}`,
        { headers: { Authorization: "Bearer YOUR_API_KEY" } }
      );
      if (!res.ok) throw new Error((await res.json()).error?.message);
      company = await res.json();
    } catch (err) {
      error = err.message;
      company = null;
    } finally {
      loading = false;
    }
  }
</script>

<form on:submit|preventDefault={lookup}>
  <label for="kvk">KVK Nummer</label>
  <input id="kvk" bind:value={kvk} placeholder="12345678" maxlength="8" />
  <button disabled={loading || kvk.length !== 8}>
    {loading ? "Zoeken..." : "Opzoeken"}
  </button>

  {#if error}<p class="error">{error}</p>{/if}

  {#if company}
    <div class="result">
      <p><strong>{company.name}</strong></p>
      <p>{company.address?.street} {company.address?.city}</p>
    </div>
  {/if}
</form>

Drop-in Widget

The fastest integration — one script tag auto-fills your form when a user types a KVK number.

<!DOCTYPE html>
<html>
<head>
  <title>Registration Form</title>
</head>
<body>
  <form>
    <label>KVK Number</label>
    <input type="text" id="kvk" placeholder="Enter KVK number">

    <label>Company Name</label>
    <input type="text" id="name" readonly>

    <label>Address</label>
    <input type="text" id="address" readonly>

    <label>City</label>
    <input type="text" id="city" readonly>

    <label>Postal Code</label>
    <input type="text" id="postal" readonly>

    <label>VAT Number</label>
    <input type="text" id="vat" readonly>
  </form>

  <!-- One script tag does everything -->
  <script
    src="https://widget.kvkbase.nl/v1.js"
    data-api-key="YOUR_API_KEY"
    data-target-kvk="#kvk"
    data-target-name="#name"
    data-target-address="#address"
    data-target-city="#city"
    data-target-postal="#postal"
    data-target-vat="#vat">
  </script>
</body>
</html>
// Listen for widget events
document.addEventListener("kvkbase:found", (e) => {
  console.log("Company found:", e.detail);
  // {
  //   kvkNumber: "12345678",
  //   name: "Acme B.V.",
  //   address: { street: "Herengracht", city: "Amsterdam", ... },
  //   vat: { number: "NL123456789B01", valid: true }
  // }
});

document.addEventListener("kvkbase:error", (e) => {
  console.error("Lookup failed:", e.detail.message);
});
/* Customize the widget appearance */
:root {
  --kvkbase-primary: #2563eb;     /* Main color */
  --kvkbase-success: #16a34a;     /* Valid VAT checkmark */
  --kvkbase-error: #dc2626;       /* Error states */
  --kvkbase-font: "Inter", sans-serif;
  --kvkbase-border-radius: 8px;
}

Next.js API Route

Server-side lookup in a Next.js API route. Keeps your API key secure on the server.

// app/api/kvk/[number]/route.ts
import { NextResponse } from "next/server";

export async function GET(
  request: Request,
  { params }: { params: { number: string } }
) {
  const response = await fetch(
    `https://api.kvkbase.nl/v1/lookup/${params.number}`,
    {
      headers: {
        Authorization: `Bearer ${process.env.KVKBASE_API_KEY}`,
      },
    }
  );

  if (!response.ok) {
    const error = await response.json();
    return NextResponse.json(error, { status: response.status });
  }

  const company = await response.json();
  return NextResponse.json(company);
}
# views.py
import requests
from django.conf import settings
from django.http import JsonResponse

def kvk_lookup(request, kvk_number):
    response = requests.get(
        f"https://api.kvkbase.nl/v1/lookup/{kvk_number}",
        headers={
            "Authorization": f"Bearer {settings.KVKBASE_API_KEY}"
        },
        timeout=10,
    )

    if not response.ok:
        return JsonResponse(
            response.json(),
            status=response.status_code
        )

    return JsonResponse(response.json())

# urls.py
# path("api/kvk/<str:kvk_number>/", kvk_lookup)
<?php
// app/Http/Controllers/KvkController.php
namespace App\Http\Controllers;

use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Http;

class KvkController extends Controller
{
    public function lookup(string $kvkNumber): JsonResponse
    {
        $response = Http::withToken(config("services.kvkbase.key"))
            ->get("https://api.kvkbase.nl/v1/lookup/{$kvkNumber}");

        if ($response->failed()) {
            return response()->json(
                $response->json(),
                $response->status()
            );
        }

        return response()->json($response->json());
    }
}

// routes/api.php
// Route::get("/kvk/{number}", [KvkController::class, "lookup"]);
// routes/kvk.js
import express from "express";
const router = express.Router();

router.get("/lookup/:kvkNumber", async (req, res) => {
  try {
    const response = await fetch(
      `https://api.kvkbase.nl/v1/lookup/${req.params.kvkNumber}`,
      {
        headers: {
          Authorization: `Bearer ${process.env.KVKBASE_API_KEY}`,
        },
      }
    );

    const data = await response.json();
    res.status(response.status).json(data);
  } catch (error) {
    res.status(500).json({
      error: { code: "INTERNAL", message: "KVK lookup failed" }
    });
  }
});

export default router;

Batch Lookup (CSV Processing)

Process a CSV file of KVK numbers and enrich each row with company data. Respects rate limits with delays.

import csv
import time
import requests

API_KEY = "YOUR_API_KEY"
BASE_URL = "https://api.kvkbase.nl/v1"

def enrich_csv(input_file, output_file):
    with open(input_file) as infile, open(output_file, "w", newline="") as outfile:
        reader = csv.DictReader(infile)
        fieldnames = reader.fieldnames + [
            "company_name", "address", "city",
            "postal_code", "vat_number", "vat_valid"
        ]
        writer = csv.DictWriter(outfile, fieldnames=fieldnames)
        writer.writeheader()

        for row in reader:
            kvk = row.get("kvk_number", "").strip()
            if len(kvk) != 8:
                writer.writerow(row)
                continue

            try:
                resp = requests.get(
                    f"{BASE_URL}/lookup/{kvk}",
                    headers={"Authorization": f"Bearer {API_KEY}"},
                    timeout=10,
                )

                if resp.ok:
                    data = resp.json()
                    row["company_name"] = data.get("name", "")
                    addr = data.get("address") or {}
                    row["address"] = f"{addr.get('street', '')} {addr.get('houseNumber', '')}"
                    row["city"] = addr.get("city", "")
                    row["postal_code"] = addr.get("postalCode", "")
                    vat = data.get("vat") or {}
                    row["vat_number"] = vat.get("number", "")
                    row["vat_valid"] = str(vat.get("valid", ""))

                # Respect rate limits
                time.sleep(0.2)  # 5 req/sec max

            except Exception as e:
                print(f"Error for {kvk}: {e}")

            writer.writerow(row)

enrich_csv("contacts.csv", "contacts_enriched.csv")
import fs from "fs";
import { parse } from "csv-parse/sync";
import { stringify } from "csv-stringify/sync";

const API_KEY = process.env.KVKBASE_API_KEY;
const delay = (ms) => new Promise((r) => setTimeout(r, ms));

async function enrichCSV(inputPath, outputPath) {
  const input = fs.readFileSync(inputPath, "utf-8");
  const records = parse(input, { columns: true });

  const enriched = [];
  for (const row of records) {
    const kvk = row.kvk_number?.trim();
    if (kvk?.length === 8) {
      try {
        const res = await fetch(
          `https://api.kvkbase.nl/v1/lookup/${kvk}`,
          { headers: { Authorization: `Bearer ${API_KEY}` } }
        );
        if (res.ok) {
          const data = await res.json();
          row.company_name = data.name || "";
          row.city = data.address?.city || "";
          row.vat_number = data.vat?.number || "";
          row.vat_valid = String(data.vat?.valid || "");
        }
        await delay(200); // Respect rate limits
      } catch (e) {
        console.error(`Error for ${kvk}:`, e.message);
      }
    }
    enriched.push(row);
  }

  fs.writeFileSync(outputPath, stringify(enriched, { header: true }));
  console.log(`Enriched ${enriched.length} rows`);
}

enrichCSV("contacts.csv", "contacts_enriched.csv");