CRM Company Data Enrichment: Automate with KVK Data
Learn how to automatically enrich CRM records with up-to-date KVK data. Integration methods for HubSpot, Salesforce, and Pipedrive.
CRM Company Data Enrichment: Automate with KVK Data
Your CRM is only as good as the data in it. And data decays fast: companies move, change names, get acquired, or shut down. If your team works with outdated company information, you end up with returned mail, wrong salutations, and missed opportunities.
Automatic enrichment with KVK data keeps your CRM current without manual effort.
Why company data decays
B2B data decays at a significant rate each year. The causes:
- Companies relocate (new address, new postal code)
- Companies change their trade name
- Legal forms change (sole proprietorship becomes a BV)
- Companies merge or get acquired
- Companies are deregistered
If your CRM contains 5,000 company records, hundreds will have outdated information after a year. After two years, the problem has doubled.
The solution: periodic enrichment
Instead of importing data once and hoping it stays accurate, set up a periodic enrichment process. There are two main approaches:
1. Event-driven enrichment
Enrich company data at the moment of interaction:
- A customer logs in: check whether the data is still current
- An employee opens a customer record: enrich in the background
- A new deal is created: fetch the latest details
2. Batch enrichment
Enrich all records periodically in a nightly or weekly batch:
async function enrichAllCompanies() {
const companies = await crm.getCompaniesWithKvkNumber();
for (const company of companies) {
try {
const kvkData = await kvkbase.lookup(company.kvkNumber);
// Check for changes
if (hasChanges(company, kvkData)) {
await crm.updateCompany(company.id, {
name: kvkData.tradeName,
address: formatAddress(kvkData.address),
isActive: kvkData.isActive,
lastEnriched: new Date()
});
console.log(`Updated: ${company.kvkNumber} - ${kvkData.tradeName}`);
}
} catch (error) {
console.error(`Failed: ${company.kvkNumber}`, error.message);
}
// Respect rate limits
await delay(200);
}
}
function hasChanges(existing, fresh) {
return existing.name !== fresh.tradeName
|| existing.address !== formatAddress(fresh.address)
|| existing.isActive !== fresh.isActive;
}
HubSpot integration
HubSpot offers an extensive API for managing company records. Here is how to connect KVK data:
Field mapping
| KVK field | HubSpot field | Type |
|---|---|---|
| kvkNumber | kvk_number (custom) | String |
| tradeName | name | String |
| address.street + houseNumber | address | String |
| address.postalCode | zip | String |
| address.city | city | String |
| vatNumber | vat_number (custom) | String |
| legalForm | legal_form (custom) | String |
| isActive | kvk_active (custom) | Boolean |
HubSpot API example
const hubspot = require('@hubspot/api-client');
async function enrichHubSpotCompany(companyId, kvkNumber) {
const kvkData = await kvkbase.lookup(kvkNumber);
const client = new hubspot.Client({ accessToken: process.env.HUBSPOT_TOKEN });
await client.crm.companies.basicApi.update(companyId, {
properties: {
name: kvkData.tradeName,
address: `${kvkData.address.street} ${kvkData.address.houseNumber}`,
zip: kvkData.address.postalCode,
city: kvkData.address.city,
kvk_number: kvkData.kvkNumber,
vat_number: kvkData.vatNumber || ''
}
});
}
Salesforce integration
Salesforce uses the Account object for company data. The integration follows a similar pattern:
Field mapping
| KVK field | Salesforce field | Object |
|---|---|---|
| tradeName | Name | Account |
| address | BillingStreet, BillingPostalCode, BillingCity | Account |
| kvkNumber | KVK_Number__c (custom) | Account |
| vatNumber | VAT_Number__c (custom) | Account |
Salesforce example (with JSForce)
const jsforce = require('jsforce');
async function enrichSalesforceAccount(accountId, kvkNumber) {
const kvkData = await kvkbase.lookup(kvkNumber);
const conn = new jsforce.Connection({
loginUrl: process.env.SF_LOGIN_URL
});
await conn.login(process.env.SF_USERNAME, process.env.SF_PASSWORD);
await conn.sobject('Account').update({
Id: accountId,
Name: kvkData.tradeName,
BillingStreet: `${kvkData.address.street} ${kvkData.address.houseNumber}`,
BillingPostalCode: kvkData.address.postalCode,
BillingCity: kvkData.address.city,
KVK_Number__c: kvkData.kvkNumber,
VAT_Number__c: kvkData.vatNumber
});
}
Pipedrive integration
Pipedrive uses Organizations for companies:
async function enrichPipedriveOrg(orgId, kvkNumber) {
const kvkData = await kvkbase.lookup(kvkNumber);
await fetch(`https://api.pipedrive.com/v1/organizations/${orgId}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
name: kvkData.tradeName,
address: `${kvkData.address.street} ${kvkData.address.houseNumber}, ` +
`${kvkData.address.postalCode} ${kvkData.address.city}`,
// Custom fields for KVK and VAT
'kvk_number_field_key': kvkData.kvkNumber,
'vat_number_field_key': kvkData.vatNumber,
api_token: process.env.PIPEDRIVE_TOKEN
})
});
}
Best practices for CRM enrichment
1. Use the KVK number as the primary key
The KVK number never changes for a company. Use it as the stable identifier to link records between your CRM and the KVK database.
2. Log all changes
Track when and what changed. This helps with troubleshooting and provides insight into how fast data decays:
async function enrichWithAuditLog(company, kvkData) {
const changes = detectChanges(company, kvkData);
if (changes.length > 0) {
await crm.updateCompany(company.id, mapKvkToCrm(kvkData));
await auditLog.write({
companyId: company.id,
kvkNumber: company.kvkNumber,
changes: changes,
timestamp: new Date()
});
}
}
3. Handle inactive companies
If a company has been deregistered from the KVK, you want to know. Flag these records in your CRM so your team does not try to sell to non-existent companies.
4. Respect rate limits
When batch-enriching thousands of records, build in pauses to avoid overloading the API. A delay of 200ms per request is typically sufficient.
5. Validate before you enrich
Not every record in your CRM has a KVK number, and not every stored number is valid. First filter for records that have a valid 8-digit KVK number.
Conclusion
Automatic CRM enrichment with KVK data is an investment that pays for itself quickly. Your team works with current data, invoices are accurate, and you prevent the silent erosion of your customer database.
With KVKBase as your data source and a simple script for periodic enrichment, you keep your CRM clean — without manual work.