Les webhooks couvrent aussi les actions faites dans l’application

Dans beaucoup d’équipes, les collaborateurs travaillent dans l’application web Smart Oversight pendant que le CRM suit les événements de l’API Smart Oversight. Jusqu’à présent, un client créé par un collègue dans l’application n’arrivait pas dans le CRM. Ce n’est plus le cas.
Cet article complète Des webhooks pour les screenings et les alertes.
Avant ce changement
Les événements de screening et d’alerte couvraient déjà tout l’espace de travail. Les événements client, non. L’API n’envoyait client.created et client.updated que pour les modifications passées par elle.
Un client ajouté par un collègue, importé depuis un fichier ou archivé dans l’application restait donc invisible pour votre point de réception, tout comme un niveau de risque modifié à la main. Le CRM gardait une copie incomplète de la base clients, et rien ne le signalait.
Un seul flux, quelle que soit l’origine
Les événements sont maintenant émis par les services qui enregistrent les données, et non plus par l’API. Ces services voient passer chaque modification, qu’elle vienne de l’application web, d’un import de fichier ou de l’API.
Concrètement, client.created part quand un client est créé dans l’application, importé depuis un fichier ou créé par l’API. client.updated part quand un client est modifié dans l’application ou par l’API, quand il est archivé et quand ses indicateurs PPE ou sanctions changent.
Rien ne change pour alert.resolved, screening.completed et screening.failed, qui couvraient déjà les deux origines. alert.resolved part pour chaque décision sur une alerte, qu’elle soit prise dans l’application ou transmise par POST /v2/alerts/{id}/review.
Votre équipe continue donc de travailler dans l’application, et le CRM suit. Personne n’a besoin de saisir un client deux fois.
Un détail change si vous utilisez déjà l’API. L’appel PUT /v2/clients/ext:<external_id>, qui crée ou met à jour un client, envoyait toujours client.updated. Il envoie désormais client.created quand il crée le client, et client.updated quand il modifie un client existant.
Le contenu d’un événement client.updated
Le champ data contient le client tel que GET /v2/clients/{id} le renvoie. L’enveloppe y ajoute l’identifiant de l’événement, son type et sa date de création. Les champs vides n’apparaissent pas.
{
"id": "evt_66f1a2b3c4d5e6f708195900",
"type": "client.updated",
"created_at": "2026-09-02T09:14:07.512Z",
"data": {
"object": "client",
"id": "cli_66f1a2b3c4d5e6f708192a3b",
"kind": "PHYSICAL",
"external_id": "CRM-1042",
"name": "John Doe",
"risk": "MEDIUM",
"management_mode": "MANAGED",
"active": true,
"sanctions": { "international": false, "administrative": false },
"address": {
"line1": "12 Rue de la Gare",
"postal_code": "1611",
"city": "Luxembourg",
"country": "LU"
},
"individual": {
"first_name": "John",
"last_name": "Doe",
"date_of_birth": "1978-04-12",
"nationalities": ["FR"],
"is_pep": false
},
"last_screened_at": "2026-09-01T16:40:12.000Z",
"created_at": "2025-11-03T10:02:44.000Z",
"updated_at": "2026-09-02T09:14:06.981Z"
}
}
data.updated_at donne l’heure de la modification. data.external_id est votre propre référence, fixée à la création du client et impossible à changer ensuite. Elle vaut null quand le client n’en a pas, par exemple s’il a été créé dans l’application sans référence. Le rapprochement se fait alors sur data.id, qu’il vaut mieux conserver dans le CRM.
L’événement ne dit pas qui a fait la modification, ni si elle vient de l’application ou de l’API. Il décrit l’état du client à ce moment-là.
Quand le CRM reçoit ses propres modifications
Quand votre CRM met à jour un client par l’API, un événement client.updated lui revient aussi. Il faut donc éviter les doublons et les boucles.
La livraison se fait « au moins une fois », si bien qu’un même identifiant evt_… peut arriver deux fois. Le plus simple est de garder les identifiants déjà traités et d’ignorer ceux qui reviennent.
L’ordre d’arrivée n’est pas garanti non plus. Conservez pour chaque client le dernier updated_at appliqué et écartez tout contenu qui n’est pas plus récent.
Reste à reconnaître l’écho de vos propres modifications. Si les champs que le CRM reprend ont déjà les mêmes valeurs chez lui, l’événement ne fait que refléter ce qu’il vient d’envoyer, et il suffit d’en accuser réception.
// Appelé après vérification de la signature et réponse 2xx.
async function handle(event) {
if (await processed.has(event.id)) return; // renvoi
await processed.add(event.id);
if (event.type !== 'client.updated') return;
const client = event.data;
const record = await crm.findBySmartOversightId(client.id)
?? (client.external_id && await crm.findByKey(client.external_id));
if (!record) return crm.createFrom(client);
if (client.updated_at <= record.lastUpdatedAt) return; // état plus ancien
if (sameMappedFields(record, client)) return; // notre propre modification
await crm.applyFrom(client); // n’écrit jamais vers Smart Oversight
}
La dernière ligne compte. Un traitement qui réécrirait vers Smart Oversight à chaque événement en déclencherait un nouveau, puis un autre, sans fin. Les événements ne s’appliquent qu’au CRM.
Un historique qui suit les abonnements
Le second changement touche GET /v2/events. Auparavant, l’historique enregistrait tous les événements, avec ou sans abonnement. Il ne garde désormais un événement que si au moins un point de réception de votre espace de travail écoute son type.
Un événement que personne n’écoute n’est donc jamais enregistré, et vous ne le retrouverez pas plus tard. S’abonner à un nouveau type ne remplit pas le passé non plus : l’historique de ce type commence avec l’abonnement.
Si votre outil consulte GET /v2/events?type=client.updated plutôt que de recevoir les notifications, abonnez quand même un point de réception à client.updated. Sans cela, l’historique de ce type reste vide.
Pour un type écouté, l’événement est enregistré même si la notification ne vous parvient pas. L’historique permet donc de rattraper une panne de votre côté.
Pour aller plus loin
La page Intégrations présente ce que couvre aujourd’hui l’API Smart Oversight. Pour voir ces événements dans une synchronisation complète, lisez Connecter votre screening KYC & LCB/FT à votre CRM.
Cet article est publié à titre d’information. Il n’a pas de valeur contractuelle et ne constitue pas un conseil juridique.
Envie de consulter la documentation complète de l’API ?
Recevez le lien par e-mail.