Companize

API reference

Companize API

Dutch business data - company search and profiles, address validation and VAT validation, in one API.

https://api.companize.nl/v1
curl https://api.companize.nl/v1/companies/69599084 \
  -H "Authorization: Bearer <api-key>"

Full spec: openapi.yaml · version 1.0.0

Companize is three APIs behind one key: company data (search, autocomplete and registry profiles from the Handelsregister, plus an enrichment layer with websites, e-mail addresses, phone numbers, social profiles, employee counts, key financials, SBI codes and registry publications), address validation (postcode + house number lookup, free-text address search and autocomplete over Dutch addresses) and VAT validation (BTW numbers checked live against the EU VIES register and resolved to the company behind them).

Conventions

  • Envelope. Every response is { "data": ..., "meta": ... }. data describes the resource(s); meta describes the *request* (request id, timing, pagination info, and, on metered calls, credit usage). Recency of the data itself (asOf, source, stale) lives *inside* the resource, never in meta.
  • Identifiers are strings. kvkNumber (8 digits), establishmentNumber (12 digits, Handelsregister: vestigingsnummer) and rsin (9 digits) preserve leading zeros and must be treated as strings, never integers.
  • Metering. Autocomplete, basic profile fetches and enrichment are each counted against your plan's monthly allowance. Enrichment responses additionally return Companize-Credits-Cost and Companize-Credits-Remaining. When an allowance is exhausted you receive 402 plan_limit_reached (naming which limit) until the period resets or you upgrade.
  • Unmetered extras. Address validation and VAT validation are included with paid plans and consume no monthly credits; on trial plans they return 402 paid_plan_required. VAT lookups have their own modest rate ceiling to protect the shared VIES upstream, with repeat lookups served from cache and a last-known answer (marked stale: true) when VIES itself is unreachable.
  • Rate limiting. All responses carry RateLimit-Limit, RateLimit-Remaining and RateLimit-Reset. Exceeding the per-second limit returns 429 with Retry-After.
  • Errors. Failures are RFC 9457 application/problem+json documents; each type URI resolves to a documentation page describing that error.

Out of scope for this version (planned)

On-demand fresh re-scrapes (fresh=true), asynchronous batch enrichment, and change-monitoring webhooks are intentionally not part of v1.

Companies

Company registry profiles (by KVK number).

get /companies/{kvkNumber} Get a company's basic profile

Returns the registry profile. Add include=enrichment to also return the enrichment block in one round trip; that consumes one enrichment credit and returns the credit headers. Counts against your basic-fetch allowance.

kvkNumber*
string · path
8-digit KVK number (string; leading zeros significant).
include
string · query
Set to enrichment to embed the enrichment block (metered).
200 response
{
  "data": {
    "kvkNumber": "01234567",
    "legalName": "Acme Amsterdam B.V.",
    "tradeNames": [
      "Acme",
      "Acme Amsterdam"
    ],
    "legalForm": "bv",
    "status": "active",
    "incorporationDate": "2014-03-11",
    "sbiCodes": [
      {
        "code": "62010",
        "description": "Ontwerpen en programmeren van computerprogramma's"
      }
    ],
    "mainEstablishment": {
      "establishmentNumber": "000051435020",
      "isMainEstablishment": true,
      "visitingAddress": {
        "street": "Keizersgracht",
        "houseNumber": "123",
        "postcode": "1015CJ",
        "city": "Amsterdam",
        "country": "NL"
      },
      "postalAddress": {
        "street": "Postbus",
        "houseNumber": "4321",
        "postcode": "1000AB",
        "city": "Amsterdam",
        "country": "NL"
      }
    },
    "establishmentCount": 1,
    "enrichment": null
  },
  "meta": {
    "requestId": "req_a1b2c3",
    "tookMs": 22
  }
}

Addresses

Dutch address autocomplete and postcode + house-number resolution.

get /addresses/autocomplete Autocomplete and resolve Dutch addresses

Typeahead and resolver over Dutch addresses, returning concrete resolved addresses. The query is parsed for an optional postcode, house number and suffix:

  • Damrak - addresses from the lowest house number up
  • Damrak 47 - the one street segment covering 47, as a concrete address
  • 1012 LK 47A - resolve that exact postcode + number, echoing 47A
  • 1012 LK - that postcode's addresses from the lowest house number up

The postcode is normalized (1012 lg -> 1012LG). A house number outside every matching segment's range (or an unknown postcode) returns no results. Included with paid plans; not metered (address calls consume no monthly credits), authenticated and rate-limited.

q*
string · query
Partial address - a street or postcode, optionally a house number (with suffix), optionally a city.
limit
integer · query
200 response
{
  "data": [
    {
      "postcode": "1012 LK",
      "houseNumber": "47",
      "street": "Damrak",
      "city": "Amsterdam",
      "municipality": "Amsterdam",
      "country": "NL"
    }
  ],
  "meta": {
    "requestId": "req_a1b2c3",
    "tookMs": 12
  }
}

Establishments

Establishment (vestiging) profiles.

get /companies/{kvkNumber}/establishments List a company's establishments
kvkNumber*
string · path
8-digit KVK number (string; leading zeros significant).
pageSize
integer · query
Results per page. Capped by your plan's maximum.
page
integer · query
1-based page number. The deepest reachable page is bounded by your plan's pagination ceiling; see the search endpoint.
200 response
{
  "data": [
    {
      "establishmentNumber": "000019625863",
      "kvkNumber": "69599084",
      "isMainEstablishment": true,
      "tradeNames": [
        "Coolblue"
      ],
      "visitingAddress": {
        "street": "Weena 664",
        "houseNumber": "664",
        "postcode": "3012 CN",
        "city": "Rotterdam",
        "country": "NL"
      },
      "postalAddress": null
    }
  ],
  "meta": {
    "requestId": "req_d4e5f6",
    "tookMs": 22,
    "page": 1,
    "pageSize": 25,
    "hasMore": false
  }
}
get /establishments/{establishmentNumber} Get an establishment profile
establishmentNumber*
string · path
12-digit establishment number (string; leading zeros significant). Handelsregister term: vestigingsnummer.
200 response
{
  "data": {
    "establishmentNumber": "000019625863",
    "kvkNumber": "69599084",
    "isMainEstablishment": true,
    "tradeNames": [
      "Coolblue"
    ],
    "visitingAddress": {
      "street": "Weena 664",
      "houseNumber": "664",
      "postcode": "3012 CN",
      "city": "Rotterdam",
      "country": "NL"
    },
    "postalAddress": null
  },
  "meta": {
    "requestId": "req_g7h8i9",
    "tookMs": 18
  }
}

Enrichment

Cached enrichment data. Metered.

get /companies/{kvkNumber}/enrichment Get cached enrichment for a company

Served from the cache. Consumes one enrichment credit, counted against your plan's monthly enrichment allowance. The payload carries its own asOf/source/stale recency markers.

kvkNumber*
string · path
8-digit KVK number (string; leading zeros significant).
200 response
{
  "data": {
    "website": [
      "https://acme.nl"
    ],
    "socialProfiles": {
      "linkedin": "https://linkedin.com/company/acme",
      "facebook": null,
      "instagram": null,
      "x": null
    },
    "email": [
      "info@acme.nl"
    ],
    "phone": [],
    "rsin": "812345678",
    "vat": {
      "number": "NL001234567B01",
      "valid": true,
      "checkedAt": "2026-06-14T09:00:00Z"
    },
    "employees": {
      "count": 48,
      "band": "20-49"
    },
    "financials": [
      {
        "year": 2024,
        "revenue": 1250000,
        "totalAssets": 1680000
      },
      {
        "year": 2023,
        "revenue": 990000,
        "totalAssets": 1420000
      }
    ],
    "people": null,
    "asOf": "2026-06-10T02:00:00Z",
    "source": "cache",
    "stale": false
  },
  "meta": {
    "requestId": "req_d4e5f6",
    "tookMs": 31,
    "creditsCost": 1,
    "creditsRemaining": 1742
  }
}

VAT

VAT (BTW) validation and resolution. Metered.

get /vat/{vatNumber} Validate a VAT (BTW) number and resolve it to a company

Validates a VAT (BTW) number against the EU VIES service and, when the trader name it returns confidently matches a company we hold, resolves it to that KVK entity and records the validation on file (kvkNumber is null when no confident match is found).

Included with paid plans, not metered. Because the result comes from the external VIES service - which can be slow, throttled or temporarily down - this endpoint doesn't consume an allowance. When VIES can't be reached, the last known answer (up to 7 days old) is served instead, marked stale: true in meta with checkedAt reflecting the original check; only when no prior answer exists does the response become 503 vies_unavailable (retry shortly), which is distinct from a number that VIES reports as invalid. Every response carries a disclaimer in meta noting the VIES dependency.

VIES protection. To keep the shared upstream healthy, lookups that reach VIES are capped independently of your plan's rate limit: 1/second per key plus a global ceiling across all keys (429 vies_throttled when exceeded). Results are cached for up to 24 hours, so repeat lookups of the same number are served instantly, don't count toward these caps, and are marked cached: true in meta with checkedAt reflecting the original VIES lookup.

vatNumber*
string · path
200 response
{
  "data": {
    "vatNumber": "NL001234567B01",
    "valid": true,
    "kvkNumber": "01234567",
    "name": "Acme Amsterdam B.V.",
    "countryCode": "NL",
    "source": "VIES",
    "checkedAt": "2026-07-02T10:15:00Z"
  },
  "meta": {
    "requestId": "req_a1b2c3",
    "tookMs": 240,
    "cached": false,
    "disclaimer": "VAT validation is performed against the external EU VIES service and reflects its response. Availability and results depend on VIES and are outside our control."
  }
}

Account

Plan, limits and usage.

get /usage Current period usage and remaining allowances
200 response
{
  "data": {
    "plan": "growth",
    "period": {
      "start": "2026-06-01T00:00:00Z",
      "resetsAt": "2026-07-01T00:00:00Z"
    },
    "autocomplete": {
      "used": 4120,
      "included": 30000
    },
    "basicFetch": {
      "used": 1875,
      "included": 25000
    },
    "enrichment": {
      "used": 412,
      "included": 1500
    }
  },
  "meta": {
    "requestId": "req_g7h8i9"
  }
}
get /me Plan and limits for the authenticated key
200 response
{
  "data": {
    "plan": "growth",
    "rateLimitPerSecond": 15,
    "pageSizeMax": 50
  },
  "meta": {
    "requestId": "req_j1k2l3"
  }
}

Bouw als eerste op Companize

Meld je aan voor de wachtlijst voor vroege toegang, een gratis tier bij de lancering en updates onderweg. Geen spam, alleen het belangrijke nieuws.

We gebruiken je e-mailadres alleen om je over vroege toegang te informeren. Je kunt je altijd afmelden.