Intégrer les données d'entreprises néerlandaises à votre SaaS
KVKBase Team

Intégrer les données d'entreprises néerlandaises à votre SaaS

Guide pas à pas pour intégrer les données d'entreprises KVK dans votre application SaaS : exemples de code, gestion des erreurs et bonnes pratiques de cache.

apiintégrationsaas

Si votre SaaS s’adresse à des entreprises néerlandaises, vous aurez tôt ou tard besoin d’accéder aux données de la KVK (Kamer van Koophandel), la Chambre de commerce néerlandaise. Que ce soit pour l’onboarding client, la génération de factures ou les contrôles de conformité, un accès fiable aux données KVK est une brique essentielle de toute application B2B sérieuse.

Ce guide vous accompagne dans l’intégration d’une API de données d’entreprises néerlandaises, de zéro jusqu’à la production, avec des exemples de code pratiques et des patterns éprouvés.

Pourquoi vous avez besoin des données d’entreprises néerlandaises

Les entreprises néerlandaises sont identifiées par un numéro KVK à 8 chiffres. Ce numéro donne accès à de nombreuses informations publiques : dénomination légale, noms commerciaux, adresse enregistrée, forme juridique (BV, NV, eenmanszaak), codes d’activité SBI, et plus encore.

Cas d’usage courants :

  • Onboarding client : remplir automatiquement les informations de l’entreprise à partir d’un numéro KVK
  • Conformité des factures : garantir des dénominations légales et des adresses corrects
  • Prévention de la fraude : vérifier qu’une entreprise existe réellement et qu’elle est active
  • Enrichissement des données : maintenir votre CRM ou votre base de données à jour

Étape 1 : obtenir votre clé d’API

Commencez par créer un compte KVKBase sur kvkbase.nl. Après l’inscription, vous recevrez une clé d’API qui authentifie vos requêtes.

Conservez votre clé d’API en lieu sûr. Ne la versionnez jamais et ne l’exposez jamais dans du code côté client.

# Stocker dans une variable d'environnement
export KVKBASE_API_KEY="your-api-key-here"

Étape 2 : effectuer votre première requête

L’opération la plus simple est une recherche par numéro KVK. Voici comment la faire avec curl :

curl -s -H "Authorization: Bearer $KVKBASE_API_KEY" \
  "https://api.kvkbase.nl/api/v1/lookup/12345678" | jq

Et en JavaScript :

const KVKBASE_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 ${KVKBASE_API_KEY}`,
      'Content-Type': 'application/json'
    }
  });

  if (!response.ok) {
    throw new Error(`API error: ${response.status} ${response.statusText}`);
  }

  return response.json();
}

Étape 3 : traiter la réponse

Une réponse typique contient les champs suivants :

{
  "kvkNumber": "12345678",
  "tradeName": "Example BV",
  "legalForm": "Besloten Vennootschap",
  "address": {
    "street": "Voorbeeldstraat",
    "houseNumber": "1",
    "postalCode": "1234AB",
    "city": "Amsterdam"
  },
  "sbiCodes": [
    { "code": "6201", "description": "Ontwikkelen en produceren van software" }
  ],
  "isActive": true
}

Faites correspondre ces champs à votre modèle de données interne. Soyez explicite sur les champs dont vous avez besoin et gérez correctement les champs manquants : toutes les entreprises n’ont pas tous les champs renseignés.

function mapToInternalModel(apiResponse) {
  return {
    companyId: apiResponse.kvkNumber,
    name: apiResponse.tradeName,
    legalForm: apiResponse.legalForm,
    fullAddress: formatAddress(apiResponse.address),
    industryCodes: apiResponse.sbiCodes?.map(s => s.code) || [],
    active: apiResponse.isActive
  };
}

function formatAddress(addr) {
  if (!addr) return null;
  return `${addr.street} ${addr.houseNumber}, ${addr.postalCode} ${addr.city}`;
}

Étape 4 : mettre en place la gestion des erreurs

Une intégration en production doit gérer plusieurs scénarios d’erreur :

async function lookupCompanySafe(kvkNumber) {
  try {
    const response = await fetch(`${BASE_URL}/lookup/${kvkNumber}`, {
      headers: { 'Authorization': `Bearer ${KVKBASE_API_KEY}` }
    });

    switch (response.status) {
      case 200:
        return { success: true, data: await response.json() };
      case 404:
        return { success: false, error: 'Company not found' };
      case 401:
        return { success: false, error: 'Invalid API key' };
      case 429:
        const retryAfter = response.headers.get('Retry-After') || '60';
        return { success: false, error: 'Rate limited', retryAfter: parseInt(retryAfter) };
      default:
        return { success: false, error: `Unexpected error: ${response.status}` };
    }
  } catch (error) {
    return { success: false, error: `Network error: ${error.message}` };
  }
}

Étape 5 : ajouter un cache

Les données d’entreprise ne changent pas souvent. Un cache réduit votre consommation d’API, améliore les temps de réponse et rend votre application plus résiliente en cas d’indisponibilité de l’API.

import NodeCache from 'node-cache';

// TTL : 24 heures pour les entreprises actives
const companyCache = new NodeCache({ stdTTL: 86400 });

async function lookupWithCache(kvkNumber) {
  const cached = companyCache.get(kvkNumber);
  if (cached) return cached;

  const result = await lookupCompanySafe(kvkNumber);
  if (result.success) {
    companyCache.set(kvkNumber, result);
  }

  return result;
}

Pour les systèmes en production, envisagez d’utiliser Redis plutôt qu’un cache en mémoire, surtout si vous exécutez plusieurs instances de serveur.

Étape 6 : respecter les limites de débit

Toute API a des limites. Gérez correctement la limitation de débit avec un backoff exponentiel :

async function lookupWithRetry(kvkNumber, maxRetries = 3) {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    const result = await lookupCompanySafe(kvkNumber);

    if (result.error === 'Rate limited') {
      const delay = result.retryAfter
        ? result.retryAfter * 1000
        : Math.pow(2, attempt) * 1000;
      await new Promise(resolve => setTimeout(resolve, delay));
      continue;
    }

    return result;
  }

  return { success: false, error: 'Max retries exceeded' };
}

Étape 7 : ajouter une fonction de recherche

Au-delà des recherches directes, vous devez souvent chercher des entreprises par nom :

async function searchCompanies(query, limit = 10) {
  const params = new URLSearchParams({ q: query, limit: limit.toString() });
  const response = await fetch(`${BASE_URL}/search?${params}`, {
    headers: { 'Authorization': `Bearer ${KVKBASE_API_KEY}` }
  });

  if (!response.ok) {
    throw new Error(`Search failed: ${response.status}`);
  }

  return response.json();
}

// Utilisation
const results = await searchCompanies('Bol.com');

Tout assembler

Voici une classe de service complète qui regroupe toutes les fonctionnalités :

class KvkService {
  constructor(apiKey) {
    this.apiKey = apiKey;
    this.baseUrl = 'https://api.kvkbase.nl/api/v1';
    this.cache = new NodeCache({ stdTTL: 86400 });
  }

  async lookup(kvkNumber) {
    return this.withCache(`lookup:${kvkNumber}`, () =>
      this.request(`/lookup/${kvkNumber}`)
    );
  }

  async search(query, limit = 10) {
    return this.request(`/search?q=${encodeURIComponent(query)}&limit=${limit}`);
  }

  async withCache(key, fn) {
    const cached = this.cache.get(key);
    if (cached) return cached;
    const result = await fn();
    this.cache.set(key, result);
    return result;
  }

  async request(path) {
    const response = await fetch(`${this.baseUrl}${path}`, {
      headers: { 'Authorization': `Bearer ${this.apiKey}` }
    });
    if (!response.ok) throw new Error(`API error: ${response.status}`);
    return response.json();
  }
}

Prochaines étapes

Une fois l’intégration de base opérationnelle, envisagez de :

  • Ajouter le widget KVKBase à votre frontend pour des recherches d’entreprises instantanées
  • Mettre en place une revalidation périodique des données d’entreprise stockées
  • Combiner les recherches KVK avec la validation de la TVA pour une conformité B2B complète

Avec KVKBase, vous disposez d’une seule API qui couvre les recherches KVK, la recherche d’entreprises et la validation des données : tout ce qu’il faut pour construire une solide intégration B2B néerlandaise.