Configuration
Ajoutez sous Intégrations un webhook avec l'adresse https de votre système. Votre secret de signature (whsec_...) ne s'affiche qu'une fois ; conservez-le dans votre système. Le bouton Envoyer un test vous envoie aussitôt un événement de type endpoint.test.
Le webhook reçoit les mêmes alertes que votre compte, selon vos règles de notification, filtrées selon la gravité et les thèmes choisis pour le webhook.
La requête
Un POST par alerte, avec un corps JSON et ces en-têtes :
Content-Typeapplication/json; charset=utf-8User-AgentChecked.be-Webhooks/1.0 (+https://checked.be/nl/developers/webhooks)webhook-id- Identifiant unique du message, égal au champ id. Identique à chaque nouvelle tentative : utilisez-le pour ignorer les doublons.
webhook-timestamp- Moment de cette tentative, en secondes depuis 1970 (UTC).
webhook-signature- La signature :
v1,suivi du HMAC-SHA256 en base64. Voir ci-dessous.
Exemple
Une alerte sur une entreprise fictive, exactement comme Checked l'envoie :
{
"id": "msg_5f0c2d6e9b1a4c7d8e3f2a1b0c9d8e7f",
"type": "alert.created",
"api_version": "2026-09-25",
"created_at": "2026-09-25T07:38:12Z",
"language": "fr",
"data": {
"alert": {
"id": 184223,
"kind": "bs_capital_change",
"label": "Opération sur le capital",
"signal": "kapitaal",
"theme": "financieel",
"theme_label": "Finances",
"severity": "med",
"severity_label": "moyenne",
"title": "Kapitaalverhoging van € 250.000",
"body": "Het kapitaal stijgt van € 18.550 naar € 268.550.",
"created_at": "2026-09-25T07:36:12Z"
},
"company": {
"enterprise_number": "0999999999",
"enterprise_number_display": "0999.999.999",
"name": "Voorbeeld NV",
"dossier_url": "https://checked.be/fr/c/voorbeeld-nv-0999999999"
},
"alerts_url": "https://checked.be/fr/alerts"
}
}Champs
typealert.created(une alerte),digest.created(le résumé quotidien ou hebdomadaire, si vous le cochez) ouendpoint.test(le bouton de test). Ignorez les types inconnus : d'autres peuvent s'ajouter.api_version- La version de ce format. Des champs peuvent s'ajouter ; les champs existants ne changent pas au sein d'une version.
language- La langue des libellés et des liens (nl, fr ou en), selon le réglage du webhook. Le titre et le texte d'une alerte sont en néerlandais, comme dans votre compte.
data.alert.kind- Le type d'alerte, un code fixe.
labelen est le nom,signaletthemela ligne et le thème des règles de notification (null pour un résumé de plusieurs actes). data.alert.severitylow,medouhigh, avecseverity_labeldans la langue choisie.data.company- Le numéro d'entreprise (10 chiffres et dans l'écriture usuelle), le nom (null s'il est inconnu) et le lien vers le dossier sur Checked.be.
Un webhook ne reçoit que ce que l'alerte montre aussi dans votre compte : pas d'adresse e-mail ni d'autres données du compte.
Vérifier la signature
Checked signe selon Standard Webhooks, vous pouvez donc aussi utiliser l'une de leurs bibliothèques. Soi-même :
- Prenez la clé : la partie après whsec_, décodée en base64.
- Calculez le HMAC-SHA256 de
{webhook-id}.{webhook-timestamp}.{body}, avec le corps exactement tel que reçu. - Comparez
v1,suivi de sa valeur base64, en temps constant, avec chaque valeur de webhook-signature (séparées par des espaces). - Refusez un timestamp qui s'écarte de plus de cinq minutes de votre horloge.
import crypto from "node:crypto";
export function verify(secret, headers, body) {
const id = headers["webhook-id"];
const ts = headers["webhook-timestamp"];
if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) return false;
const key = Buffer.from(secret.replace(/^whsec_/, ""), "base64");
const expected = "v1," + crypto.createHmac("sha256", key)
.update(`${id}.${ts}.${body}`).digest("base64");
return headers["webhook-signature"].split(" ").some(sig =>
sig.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected)));
}import base64, hashlib, hmac, time
def verify(secret: str, headers: dict, body: bytes) -> bool:
msg_id = headers["webhook-id"]
ts = headers["webhook-timestamp"]
if abs(time.time() - int(ts)) > 300:
return False
key = base64.b64decode(secret.removeprefix("whsec_"))
signed = f"{msg_id}.{ts}.".encode() + body
expected = "v1," + base64.b64encode(
hmac.new(key, signed, hashlib.sha256).digest()).decode()
return any(hmac.compare_digest(sig, expected)
for sig in headers["webhook-signature"].split(" "))using System.Security.Cryptography;
using System.Text;
static bool Verify(string secret, string id, string ts, string signatures, string body)
{
if (Math.Abs(DateTimeOffset.UtcNow.ToUnixTimeSeconds() - long.Parse(ts)) > 300) return false;
var key = Convert.FromBase64String(secret["whsec_".Length..]);
var hash = HMACSHA256.HashData(key, Encoding.UTF8.GetBytes($"{id}.{ts}.{body}"));
var expected = Encoding.UTF8.GetBytes("v1," + Convert.ToBase64String(hash));
return signatures.Split(' ').Any(s =>
CryptographicOperations.FixedTimeEquals(Encoding.UTF8.GetBytes(s), expected));
}Réponses et nouvelles tentatives
- Répondez en 10 secondes avec un statut 2xx. Faites le travail lourd plutôt ensuite.
- Toute autre réponse, ou l'absence de réponse, entraîne une nouvelle tentative, chaque fois plus tard : après 1, 5, 15 et 30 minutes, puis après 1 à 12 heures. Un message est tenté jusqu'à 6 fois et expire après 3 jours.
- Les messages arrivent dans l'ordre : tant que le plus ancien n'est pas livré, les suivants attendent. Un en-tête Retry-After est respecté (jusqu'à une heure).
- Après 10 échecs consécutifs, le webhook est désactivé et son propriétaire reçoit un e-mail. Une réponse 410 Gone le désactive sans nouvelle tentative.
- Les redirections (3xx) ne sont pas suivies. L'adresse doit utiliser https et être publique ; les adresses d'un réseau interne sont refusées, même si le nom y pointe plus tard.
- Chaque tentative figure dans le journal de livraison du webhook, avec le statut et la durée.