Enrichissement par lots des données d'entreprise de votre CRM
Utilisez l'API de recherche par lots de KVKBase pour enrichir et vérifier à grande échelle les fiches d'entreprises néerlandaises de votre CRM.
Les données d’entreprise se périment plus vite que la plupart des équipes ne le pensent. Les entreprises déménagent, changent de nom commercial, fusionnent avec d’autres entités ou cessent complètement leur activité. Si votre CRM contient des fiches d’entreprises néerlandaises, une part importante d’entre elles est probablement déjà obsolète.
La solution n’est pas d’embaucher quelqu’un pour vérifier chaque fiche à la main. C’est de lancer régulièrement un enrichissement par lots auprès du registre KVK.
Le coût des données périmées
Des données d’entreprise erronées ne sont pas qu’un désagrément : elles ont un impact réel sur l’activité :
- Les équipes commerciales perdent du temps à appeler des entreprises qui ont déménagé ou fermé
- Les campagnes marketing reviennent en échec lorsqu’elles sont envoyées à des adresses obsolètes
- Les factures sont rejetées lorsque la raison sociale ou l’adresse ne correspond pas au registre officiel
- Les audits de conformité échouent lorsque vos fiches ne reflètent pas l’état actuel de vos relations d’affaires
Selon une étude de Gartner, la mauvaise qualité des données coûte en moyenne 12,9 millions de dollars par an aux organisations. Même si vos coûts n’en représentent qu’une fraction, le retour sur investissement d’un enrichissement automatisé des données est difficile à contester.
À quoi ressemble un enrichissement par lots
Le processus est simple :
- Exportez les fiches de vos entreprises néerlandaises (avec leur numéro KVK) depuis votre CRM
- Pour chaque fiche, appelez l’API KVKBase afin d’obtenir les données actuelles
- Comparez la réponse de l’API avec vos données stockées
- Mettez à jour les fiches dont les données ont changé
- Signalez les fiches dont l’entreprise n’est plus active
Vous pouvez l’exécuter comme un nettoyage ponctuel ou le planifier chaque semaine ou chaque mois.
Implémentation en Python
Voici un script complet qui lit un CSV de fiches d’entreprises, les enrichit via l’API KVKBase et écrit les résultats dans un nouveau CSV :
import csv
import time
import requests
API_KEY = "your-api-key"
BASE_URL = "https://api.kvkbase.nl/api/v1"
def lookup_company(kvk_number):
"""Rechercher une seule entreprise par numéro KVK."""
response = requests.get(
f"{BASE_URL}/lookup/{kvk_number}",
headers={"Authorization": f"Bearer {API_KEY}"}
)
if response.status_code == 200:
return response.json()
elif response.status_code == 404:
return {"error": "not_found"}
elif response.status_code == 429:
# Limite de débit atteinte : attendre puis réessayer
retry_after = int(response.headers.get("Retry-After", 60))
time.sleep(retry_after)
return lookup_company(kvk_number)
else:
return {"error": f"status_{response.status_code}"}
def enrich_csv(input_file, output_file):
"""Lire un CSV, enrichir chaque ligne, écrire les résultats."""
with open(input_file, "r") as infile:
reader = csv.DictReader(infile)
fieldnames = reader.fieldnames + [
"api_trade_name",
"api_address",
"api_postal_code",
"api_city",
"api_legal_form",
"api_is_active",
"data_changed"
]
with open(output_file, "w", newline="") as outfile:
writer = csv.DictWriter(outfile, fieldnames=fieldnames)
writer.writeheader()
for i, row in enumerate(reader):
kvk = row.get("kvk_number", "").strip()
if not kvk or len(kvk) != 8:
row["data_changed"] = "invalid_kvk"
writer.writerow(row)
continue
result = lookup_company(kvk)
if "error" in result:
row["data_changed"] = result["error"]
writer.writerow(row)
continue
# Associer les champs de l'API
addr = result.get("address", {})
row["api_trade_name"] = result.get("tradeName", "")
row["api_address"] = f"{addr.get('street', '')} {addr.get('houseNumber', '')}"
row["api_postal_code"] = addr.get("postalCode", "")
row["api_city"] = addr.get("city", "")
row["api_legal_form"] = result.get("legalForm", "")
row["api_is_active"] = str(result.get("isActive", ""))
# Vérifier si quelque chose a changé
changed = (
row.get("company_name", "") != result.get("tradeName", "") or
row.get("city", "") != addr.get("city", "")
)
row["data_changed"] = "yes" if changed else "no"
writer.writerow(row)
# Progression
if (i + 1) % 100 == 0:
print(f"Processed {i + 1} records")
# Limitation de débit : court délai entre les requêtes
time.sleep(0.1)
print(f"Done. Results written to {output_file}")
# Utilisation
enrich_csv("companies.csv", "companies_enriched.csv")
Votre CSV d’entrée doit comporter au moins une colonne kvk_number. Le script ajoute des colonnes pour les données de l’API et un indicateur data_changed, afin de filtrer rapidement les fiches à mettre à jour.
Implémentation en JavaScript / Node.js
Si vous préférez JavaScript, voici l’équivalent :
const fs = require('fs');
const { parse } = require('csv-parse/sync');
const { stringify } = require('csv-stringify/sync');
const API_KEY = process.env.KVKBASE_API_KEY;
const BASE_URL = 'https://api.kvkbase.nl/api/v1';
async function lookupCompany(kvkNumber) {
const response = await fetch(`${BASE_URL}/lookup/${kvkNumber}`, {
headers: { 'Authorization': `Bearer ${API_KEY}` }
});
if (response.status === 200) return response.json();
if (response.status === 404) return { error: 'not_found' };
if (response.status === 429) {
const retryAfter = parseInt(response.headers.get('Retry-After') || '60');
await new Promise(r => setTimeout(r, retryAfter * 1000));
return lookupCompany(kvkNumber);
}
return { error: `status_${response.status}` };
}
async function enrichCsv(inputFile, outputFile) {
const input = fs.readFileSync(inputFile, 'utf-8');
const records = parse(input, { columns: true });
const results = [];
for (let i = 0; i < records.length; i++) {
const row = records[i];
const kvk = (row.kvk_number || '').trim();
if (!kvk || kvk.length !== 8) {
results.push({ ...row, api_trade_name: '', data_changed: 'invalid_kvk' });
continue;
}
const result = await lookupCompany(kvk);
if (result.error) {
results.push({ ...row, api_trade_name: '', data_changed: result.error });
} else {
const addr = result.address || {};
results.push({
...row,
api_trade_name: result.tradeName || '',
api_address: `${addr.street || ''} ${addr.houseNumber || ''}`,
api_postal_code: addr.postalCode || '',
api_city: addr.city || '',
api_is_active: String(result.isActive),
data_changed: row.company_name !== result.tradeName ? 'yes' : 'no'
});
}
if ((i + 1) % 100 === 0) console.log(`Processed ${i + 1} records`);
await new Promise(r => setTimeout(r, 100));
}
fs.writeFileSync(outputFile, stringify(results, { header: true }));
console.log(`Done. Results written to ${outputFile}`);
}
enrichCsv('companies.csv', 'companies_enriched.csv');
Planifier un enrichissement régulier
Un nettoyage ponctuel est utile, mais la vraie valeur vient d’un enrichissement planifié. Voici quelques approches :
Tâche cron
L’option la plus simple. Lancez le script chaque semaine ou chaque mois :
# Exécuter chaque dimanche à 2 h du matin
0 2 * * 0 cd /path/to/scripts && python enrich.py >> /var/log/enrichment.log 2>&1
Pipeline CI/CD
Si votre équipe utilise GitHub Actions ou un outil similaire, vous pouvez exécuter l’enrichissement comme un workflow planifié :
name: CRM Enrichment
on:
schedule:
- cron: '0 2 * * 0' # Chaque dimanche à 2 h UTC
workflow_dispatch: # Autoriser le déclenchement manuel
jobs:
enrich:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.12'
- run: pip install requests
- run: python scripts/enrich.py
env:
KVKBASE_API_KEY: ${{ secrets.KVKBASE_API_KEY }}
Intégration native au CRM
La plupart des CRM prennent en charge les webhooks ou les règles d’automatisation. Vous pouvez déclencher une recherche KVK à chaque création d’une fiche d’entreprise néerlandaise, ou lancer une mise à jour en masse sur toutes les fiches non vérifiées depuis plus de 30 jours.
Gérer les cas particuliers
Quelques situations à anticiper :
- Numéros KVK manquants. Certaines fiches n’ont peut-être aucun numéro KVK. Vous pouvez essayer de chercher par nom d’entreprise avec le point d’accès
/search, mais attendez-vous à des correspondances ambiguës. - Fiches en double. Deux fiches aux données différentes mais au même numéro KVK sont des doublons. Profitez de l’enrichissement pour les fusionner.
- Entreprises inactives. Lorsque l’API renvoie
isActive: false, décidez si vous signalez la fiche, l’archivez ou prévenez le responsable du compte. - Limites de débit. Avec de gros jeux de données (plus de 10 000 fiches), étalez vos requêtes dans le temps. Le délai de 100 ms des exemples ci-dessus donne environ 600 recherches par minute, un rythme sûr pour la plupart des formules.
Mesurer les résultats
Après votre première exécution d’enrichissement, examinez ces indicateurs :
- Fiches mises à jour : combien avaient des données obsolètes
- Entreprises inactives : combien n’étaient plus actives
- Données manquantes complétées : combien de fiches ont gagné de nouveaux champs (adresse, forme juridique, etc.)
- Doublons trouvés : combien de numéros KVK apparaissaient plus d’une fois
Ces chiffres montrent la valeur apportée par un enrichissement régulier et vous aident à justifier l’investissement auprès des parties prenantes.
Pour commencer
Inscrivez-vous sur kvkbase.nl pour obtenir une clé d’API. Commencez par un petit lot de test de 50 à 100 fiches pour valider votre pipeline avant de l’exécuter sur toute votre base. La documentation de l’API détaille les limites de débit, les formats de réponse et les codes d’erreur.