Surveillance des entreprises

Surveillez des entreprises néerlandaises par numéro KvK et soyez averti dès que quelque chose change : une nouvelle adresse, un changement de nom, une faillite, une dissolution. Les alertes sont envoyées par e-mail, par webhook signé, ou les deux. Vous pouvez tout gérer depuis le tableau de bord ou via l'API.

Ne consomme aucun jeton Les requêtes de surveillance ne sont pas décomptées. En revanche, chaque offre payante inclut un certain nombre d'emplacements de surveillance. La surveillance n'est pas disponible avec l'offre gratuite : ces requêtes renvoient 403 monitoring_requires_paid_plan.

Fonctionnement

  • Chaque entreprise surveillée est vérifiée une fois par jour, à partir des mêmes données que /v1/lookup.
  • La première vérification sert de référence et ne déclenche jamais d'alerte.
  • Un changement n'est signalé que si la source a répondu avec une valeur les deux fois. Une indisponibilité temporaire de la source n'apparaît jamais comme un changement.
  • L'historique des alertes est conservé pendant 90 jours.

Champs pouvant déclencher une alerte

ChampSignification
nameRaison sociale
addressRue, code postal et ville
legalFormForme juridique (BV, NV, VOF, ...)
statusactive ou dissolved (dissoute)
insolvencynone, bankrupt ou surseance
sbiCodesCodes d'activité (SBI)
directorsDirigeants, uniquement lorsque la source de données les fournit
vatValidité VIES du numéro de TVA connu

Vous pouvez limiter les alertes à un sous-ensemble de champs dans les paramètres. Si aucun n'est sélectionné, vous les recevez tous.

Limites

OffreEmplacements de surveillance
Gratuit0 (non disponible)
Starter10
Pro100
Business1 000
  • Un emplacement correspond à une entreprise surveillée, quel que soit le nombre de vérifications.
  • Si votre offre passe sous le nombre d'entreprises que vous surveillez, les plus anciennes restent actives et les autres sont mises en pause, jamais supprimées. Elles reprennent lorsque vous passez à une offre supérieure.
  • L'ajout en masse accepte 500 numéros au maximum par requête.
  • 50 alertes par jour au maximum sont envoyées immédiatement par e-mail. Les suivantes sont regroupées dans le résumé quotidien.
  • Les webhooks sont envoyés au maximum une fois par seconde et par compte.
  • Si la capacité de surveillance est temporairement saturée, l'ajout d'une entreprise renvoie 503 monitoring_capacity. Réessayez plus tard.

Points d'accès

Tous les points d'accès utilisent votre clé d'API habituelle, Authorization: Bearer YOUR_API_KEY, et la limite de débit par minute habituelle.

Point d'accèsDescription
GET /v1/monitor/watchesListe les entreprises surveillées, avec limit et cursor. Renvoie watches (chacune avec kvkNumber, label, name, paused, createdAt, lastCheckedAt), slots: { used, limit } et nextCursor (null sur la dernière page).
POST /v1/monitor/watchesAjoute une entreprise (kvkNumber, label facultatif) ou plusieurs (kvkNumbers, 500 maximum). Les deux renvoient results et slots. Une requête en masse répond 200 avec un résultat par numéro (added, exists, invalid, over_limit ou not_found). Un ajout unique renvoie à la place une erreur en cas d'échec : 400 numéro invalide, 404 introuvable, 403 monitoring_slot_limit lorsqu'il ne reste plus d'emplacement. Un ajout unique réussi renvoie 201 (added) ou 200 (exists).
PATCH /v1/monitor/watches/{kvk}Modifie le libellé.
DELETE /v1/monitor/watches/{kvk}Arrête la surveillance d'une entreprise.
GET /v1/monitor/alertsHistorique des alertes, renvoyé sous la forme alerts plus nextCursor. Filtrez avec kvkNumber et since ; paginez avec limit et cursor.
GET /v1/monitor/settingsLit les paramètres d'e-mail, de remise, de champs et de webhook. Renvoie emailEnabled, delivery, fields, webhookUrl, webhookConfigured, webhookDisabled et lang. Le secret du webhook n'est jamais renvoyé.
PUT /v1/monitor/settingsMet à jour les paramètres. L'enregistrement d'une URL de webhook pour la première fois renvoie aussi webhookSecret, une seule fois.
POST /v1/monitor/settings/webhook-secretGénère un nouveau secret de webhook. La réponse (webhookSecret) est la seule occasion où il est affiché.
POST /v1/monitor/webhook/testEnvoie un événement company.test signé à l'URL de votre webhook. Répond { delivered, status, reason } : delivered vaut true uniquement si votre point de terminaison a répondu par un 2xx, sinon reason en donne la cause.
bash
# Surveiller une entreprise
curl -X POST https://api.kvkbase.nl/v1/monitor/watches \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"kvkNumber": "12345678", "label": "client 1042"}'

# En surveiller plusieurs à la fois (500 maximum par requête)
curl -X POST https://api.kvkbase.nl/v1/monitor/watches \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"kvkNumbers": ["12345678", "87654321"]}'

Alertes par e-mail

L'e-mail est envoyé à l'adresse de votre compte, en néerlandais, en anglais ou en français selon la langue de votre tableau de bord. Choisissez le mode immédiat (un e-mail par changement détecté, jusqu'à 20 changements listés par e-mail) ou résumé (un e-mail par jour à 07:00 UTC, regroupé par entreprise).

Webhooks

Indiquez une URL HTTPS dans les paramètres et KVKBase envoie un POST par événement. Seul le HTTPS sur le port 443 ou 8443 est accepté. Les URL contenant une adresse IP privée ou de bouclage littérale, ou un nom d'hôte local tel que localhost ou *.local, sont rejetées. Les redirections ne sont pas suivies.

Charge utile

json
{
  "id": "evt_7c1f0b6e2a",
  "type": "company.changed",
  "createdAt": "2026-10-04T05:23:11.000Z",
  "kvkNumber": "12345678",
  "name": "Acme B.V.",
  "changes": [
    { "field": "address", "from": "Herengracht 100, 1015 BS Amsterdam", "to": "Keizersgracht 5, 1015 CC Amsterdam" },
    { "field": "status", "from": "active", "to": "dissolved" }
  ]
}

type vaut company.changed pour les changements réels et company.test pour le bouton de test. Chaque changement est de la forme { field, from, to }, où from et to peuvent valoir null.

En-têtes

En-têteValeur
X-KVKBase-EventLe type d'événement
X-KVKBase-TimestampHeure Unix en secondes à laquelle la requête a été signée
X-KVKBase-Signaturev1= suivi du HMAC-SHA256 hexadécimal de <timestamp>.<raw body> calculé avec votre secret de webhook

Vérifier la signature

Le secret commence par whsec_. Il est affiché une fois lors de sa création et de nouveau lorsque vous le renouvelez, conservez-le donc immédiatement. Vérifiez toujours la signature sur le corps brut de la requête, comparez en temps constant et rejetez les requêtes dont l'horodatage date de plus de quelques minutes.

javascript
import { createHmac, timingSafeEqual } from "node:crypto";

// rawBody doit être exactement les octets reçus, avant tout parsing JSON.
export function verify(rawBody, headers, secret) {
  const timestamp = headers["x-kvkbase-timestamp"];
  const received = (headers["x-kvkbase-signature"] || "").replace(/^v1=/, "");

  // Rejeter les requêtes anciennes pour qu'une requête interceptée ne puisse pas être rejouée.
  if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return false;

  const expected = createHmac("sha256", secret)
    .update(timestamp + "." + rawBody)
    .digest("hex");

  return (
    received.length === expected.length &&
    timingSafeEqual(Buffer.from(received), Buffer.from(expected))
  );
}
php
<?php
$secret    = getenv('KVKBASE_WEBHOOK_SECRET');
$rawBody   = file_get_contents('php://input');
$timestamp = $_SERVER['HTTP_X_KVKBASE_TIMESTAMP'] ?? '';
$received  = preg_replace('/^v1=/', '', $_SERVER['HTTP_X_KVKBASE_SIGNATURE'] ?? '');

$expected = hash_hmac('sha256', $timestamp . '.' . $rawBody, $secret);

if (abs(time() - (int) $timestamp) > 300 || !hash_equals($expected, $received)) {
    http_response_code(401);
    exit;
}

$event = json_decode($rawBody, true);
http_response_code(200);
python
import hashlib
import hmac
import time


def verify(raw_body: bytes, headers: dict, secret: str) -> bool:
    timestamp = headers.get("X-KVKBase-Timestamp", "")
    received = headers.get("X-KVKBase-Signature", "").removeprefix("v1=")

    # Rejeter les requêtes anciennes pour qu'une requête interceptée ne puisse pas être rejouée.
    if abs(time.time() - int(timestamp or 0)) > 300:
        return False

    expected = hmac.new(
        secret.encode(),
        timestamp.encode() + b"." + raw_body,
        hashlib.sha256,
    ).hexdigest()

    return hmac.compare_digest(expected, received)

Nouvelles tentatives et désactivation automatique

  • Répondez par n'importe quel 2xx dans les 5 secondes. Toute autre réponse, un dépassement de délai ou une redirection compte comme une tentative échouée.
  • Une remise échouée est retentée jusqu'à 3 tentatives au total, avec des délais croissants entre les tentatives.
  • Après 20 remises échouées consécutives, le webhook est désactivé automatiquement et vous recevez un e-mail. Enregistrer à nouveau l'URL dans les paramètres le réactive. Un seul succès remet le compteur à zéro.
  • Dans de rares cas, un événement peut arriver en double. Utilisez l'id de l'événement pour dédoublonner.

Erreurs

La surveillance utilise le même format d'erreur que le reste de l'API. Les codes propres à cette fonctionnalité :

StatutCodeSignification
403monitoring_requires_paid_planL'offre gratuite n'inclut aucun emplacement de surveillance.
403monitoring_slot_limitTous les emplacements de surveillance de votre offre sont utilisés (ajout unique).
503monitoring_capacityLa surveillance est temporairement saturée. Réessayez plus tard.