# Netherlands KvK → Company Markdown Profile (`ingenious_quip_bxq/netherlands-kvk-markdown`) Actor

Dutch company profiles from the official KvK Handelsregister API (api.kvk.nl): name, KvK, RSIN, legal form, address, SBI, status, establishments as Markdown cards + JSON. Bring your own KvK API key. No scraping, no contacts. Failures free. 256 MB.

- **URL**: https://apify.com/ingenious_quip_bxq/netherlands-kvk-markdown.md
- **Developed by:** [新世紀書僮](https://apify.com/ingenious_quip_bxq) (community)
- **Categories:** Business, Developer tools, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.00 / 1,000 kvk company profiles

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Netherlands KvK → Company Markdown Profile

Turn Dutch **KvK numbers, RSINs, establishment numbers or company names** into clean **Markdown company cards + JSON rows** using the **official KvK Handelsregister REST API** (`api.kvk.nl`) with **your own KvK API key**.

- **Official API only.** Zoeken v2, Basisprofiel v1, Vestigingen and Vestigingsprofiel v1. No HTML scraping of the KvK website, no proxies, no headless browser.
- **Bring your own key (BYOK).** Your key is a secret input, used only as the `apikey` header to `api.kvk.nl`, never logged.
- **Lightweight.** 256 MB by default. A typical company takes 1–2 seconds.
- **Markdown-first.** Each company gets a ready-to-paste card (name, KvK, RSIN, legal form, addresses, SBI codes, status, working persons, establishments). `REPORT.md` holds all cards plus a summary table.
- **Failures are free.** A missing or invalid key (HTTP 401), an invalid number, "not found", rate limiting after retries and KvK 5xx errors are never charged.
- **No contact harvesting.** Email, phone, fax and website fields are dropped. Phone numbers and emails in free-text address lines are replaced with placeholders. The KvK *non-mailing* indicator is shown on each card.

### How to get a KvK API key

Apify does not provide this key and neither does this Actor. You sign the KvK agreement yourself:

1. Open the **KVK Developer Portal → Apply for APIs**: <https://developers.kvk.nl/apply-for-apis> (docs: <https://developers.kvk.nl/documentation>).
2. You need a **Dutch KvK registration** (foreign governments excepted) and an **authorised signer** for the agreement. KvK reviews each request, which can take **up to 7 business days**.
3. KvK bills you directly: **EUR 6.40 / month per key** plus **EUR 0.02 per Basisprofiel, Vestigingsprofiel or Naamgeving query**. Zoeken is free. See <https://developers.kvk.nl/pricing>.
4. Paste the key into the **`kvkApiKey`** input (it is stored as a secret).

You are responsible for using KvK data under your own KvK agreement and terms of use.

**Want to try it first?** Turn on **`useKvkTestEnvironment`**. The Actor then queries KvK's public **test environment** (`api.kvk.nl/test`) with the test key that KvK publishes. The data is fictitious, for example KvK `68750110`, `69599084`, `90003942`, or a name search for `test`. **Test-environment profiles are not charged.**

### Input

| Field | Default | Notes |
|---|---|---|
| `kvkApiKey` | — | **Secret. Required for live data.** Without it, KvK answers 401. Those rows are free. |
| `kvkNumbers` | — | 8-digit KvK numbers. `6875 0110` and `KvK: 68.75.01.10` are also accepted. |
| `rsins` | — | 9-digit RSINs, resolved through the free Zoeken API. |
| `vestigingsnummers` | — | 12-digit establishment numbers, resolved through Zoeken. |
| `companyNames` + `searchCity` | — | Official Zoeken name search (whole-word match). `maxSearchResultsPerName` defaults to 3. |
| `includeBasisprofiel` | `true` | 1 paid KvK query per company. Off = light card from the free Zoeken API only. |
| `includeEstablishments` | `true` | 1 paid KvK query per company: establishment counts and list. |
| `includeVestigingsprofiel` | `false` | 1 paid KvK query: full-time/part-time working persons for the main (or requested) establishment. |
| `includeInactive`, `includeGeoData` | `false` | Map to the KvK `inclusiefInactieveRegistraties` and `geoData` parameters. |
| `maxItems` | 50 | Maximum number of successful (charged) profiles. |
| `maxConcurrency` / `maxRetries` | 2 / 3 | Retries cover 429, 5xx, timeouts and KvK IPD1002/IPD1003. 400/401/404 are never retried. |

Example:

```json
{
  "kvkApiKey": "YOUR_KVK_API_KEY",
  "kvkNumbers": ["68750110"],
  "companyNames": ["Bakkerij"],
  "searchCity": "Utrecht",
  "maxItems": 20
}
```

### Output

**Dataset**: one row per company, with views *Overview* and *Failed (not charged)*:
`kvkNumber`, `name`, `statutoryName`, `tradeNames[]`, `legalForm`, `legalFormExtended`, `rsin`, `registrationStatus` (active/inactive), `registrationDate`, `startDate`, `endDate`, `sbiActivities[]` (`code`, `description`, `main`), `mainSbiCode`, `visitingAddress`, `postalAddress`, `address`, `city`, `postcode`, `employeesTotal`, `mainEstablishment`, `establishments` (`total`, `commercial`, `nonCommercial`, `list[]`), `establishmentProfile`, `nonMailing`, `kvkBillableQueries`, `markdown`, `status`, `errorClass`, `httpStatus`, `hint`.

**Key-value store**: `REPORT.md` (table + one card per company), `REPORT.json`, and `SUMMARY`. `SUMMARY` includes `kvkBillableQueries` and `kvkEstimatedCostEur`, so you can reconcile with your KvK invoice.

Example card (KvK test data):

```markdown
#### Test BV Donald — KvK 68750110

- **Legal form:** Besloten vennootschap · RSIN `857587973`
- **Status:** **active** · registered 2017-05-19 · started 2017-05-19
- **Visiting address:** Hizzaarderlaan 3 A 8823SJ Lollum
- **Postal address:** Postbus 200 1000AE Rommeldam
- **SBI activities:** `01241` Teelt van appels en peren (main)
- **Main establishment:** `000037178598` Test BV Donald · commercial
- **Establishments:** 2 total (2 commercial, 0 non-commercial)
```

### Pricing (pay per event)

| Event | Price |
|---|---|
| Actor start | $0.001 per run |
| `kvk-profile` | **$0.004** per successful company profile |

Failed lookups and test-environment profiles are free. Example: 50 companies = $0.001 + 50 × $0.004 = **$0.201** on Apify. KvK's own fees (EUR 0.02 per paid query) are billed to you by KvK under your agreement.

### Error classes

`missing_key` (401, no key) · `api_key_invalid` (401) · `forbidden` (403) · `invalid_input` (bad number, KvK IPD0004/0006/0010) · `not_found` (404, IPD0005/IPD5200) · `temporarily_unavailable` (IPD1002/1003) · `rate_limited` (429) · `kvk_server_error` (5xx) · `timeout` · `network`. **None are charged.** After the first 401, the Actor stops calling KvK and marks the remaining inputs with the same error.

### Not included

There are no lead lists, email/phone/website contacts, owner or director personal data, scraping of kvk.nl pages, or Mutatieservice. Use KvK's own products when you need legally certain extracts.

### Source code

Open source (AGPL-3.0): https://github.com/xbox002000/netherlands-kvk-markdown

# Changelog

This Actor's version history is a separate document: https://apify.com/ingenious_quip_bxq/netherlands-kvk-markdown/changelog.md

# Actor input Schema

## `kvkApiKey` (type: `string`):

Your own KvK Handelsregister API key (sent as the `apikey` header to api.kvk.nl). Required for live data — without it KvK answers HTTP 401 and rows are marked failed (free). Apply at https://developers.kvk.nl/apply-for-apis. KvK bills you directly (EUR 6.40/month + EUR 0.02 per Basisprofiel/Vestigingsprofiel query; Zoeken free).

## `kvkNumbers` (type: `array`):

8-digit KvK (Chamber of Commerce) numbers. Spaces/dots allowed (e.g. `6875 0110`).

## `rsins` (type: `array`):

9-digit RSIN (legal entity number). Resolved to a KvK number via the free KvK Zoeken API.

## `vestigingsnummers` (type: `array`):

12-digit establishment numbers. Resolved via Zoeken; with Vestigingsprofiel enabled, that establishment's profile is attached.

## `companyNames` (type: `array`):

Trade or statutory names searched with the official KvK Zoeken API (whole-word matching). Each match becomes one profile (charged).

## `searchCity` (type: `string`):

Restrict company-name search to this plaats (city), e.g. `Amsterdam`.

## `maxSearchResultsPerName` (type: `integer`):

Distinct KvK registrations profiled per company name.

## `includeBasisprofiel` (type: `boolean`):

1 KvK query per company (EUR 0.02 on your KvK bill): legal form, RSIN, SBI codes, registration dates, main establishment and addresses. Off = light card from the free Zoeken API only (name, street, city).

## `includeEstablishments` (type: `boolean`):

1 extra KvK query per company: number of (non-)commercial establishments and their addresses.

## `includeVestigingsprofiel` (type: `boolean`):

1 extra KvK query per company: full-time / part-time working persons and establishment SBI codes for the main (or requested) establishment.

## `includeInactive` (type: `boolean`):

Adds inclusiefInactieveRegistraties=true to Zoeken lookups (RSIN / vestigingsnummer / name).

## `includeGeoData` (type: `boolean`):

Adds geoData=true (GPS + BAG id) to addresses when KvK knows them.

## `maxEstablishmentsListed` (type: `integer`):

How many establishments are listed in the card (counts are always complete).

## `maxItems` (type: `integer`):

Stop after this many successful profiles (each charged once).

## `maxConcurrency` (type: `integer`):

Parallel KvK requests.

## `maxRetries` (type: `integer`):

Retries on HTTP 429 / 5xx / timeouts / KvK IPD1002-IPD1003 (temporarily unavailable). 400/401/404 are never retried.

## `requestTimeoutSecs` (type: `integer`):

Per-request timeout.

## `useKvkTestEnvironment` (type: `boolean`):

Try the Actor without a key: queries KvK's public test environment (api.kvk.nl/test) with KvK's published test key. Data is fictitious (e.g. KvK 68750110, 69599084, 90003942). Profiles are NOT charged. Your own key is not used.

## Actor input object example

```json
{
  "kvkNumbers": [
    "68750110"
  ],
  "maxSearchResultsPerName": 3,
  "includeBasisprofiel": true,
  "includeEstablishments": true,
  "includeVestigingsprofiel": false,
  "includeInactive": false,
  "includeGeoData": false,
  "maxEstablishmentsListed": 20,
  "maxItems": 50,
  "maxConcurrency": 2,
  "maxRetries": 3,
  "requestTimeoutSecs": 30,
  "useKvkTestEnvironment": false
}
```

# Actor output Schema

## `results` (type: `string`):

kvkNumber, name, legalForm, rsin, address, city, SBI, registrationStatus, establishments, markdown, errorClass.

## `reportMarkdown` (type: `string`):

Summary table plus one Markdown company card per KvK registration.

## `reportJson` (type: `string`):

All company rows (without markdown) + summary.

## `summary` (type: `string`):

profilesOk, profilesFailed, byClass, apiKeyProvided, keyHint, kvkBillableQueries, charged, durationSecs.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "kvkNumbers": [
        "68750110"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("ingenious_quip_bxq/netherlands-kvk-markdown").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "kvkNumbers": ["68750110"] }

# Run the Actor and wait for it to finish
run = client.actor("ingenious_quip_bxq/netherlands-kvk-markdown").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "kvkNumbers": [
    "68750110"
  ]
}' |
apify call ingenious_quip_bxq/netherlands-kvk-markdown --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,ingenious_quip_bxq/netherlands-kvk-markdown"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/PeaeJPkf7TBRNfnDp/builds/tyJqZUZ73LkbnLIR5/openapi.json
