Configurez des webhooks dans le tableau de bord, recevez les livraisons et vérifiez la signature HMAC – avec des exemples curl, Node.js et PHP.
Un webhook envoie une requête HTTP à votre serveur dès que quelque chose se passe dans votre espace de travail – par exemple quand une page est publiée. Vous n’avez ainsi pas à demander sans cesse si quelque chose a changé. Chaque livraison est signée pour que votre serveur puisse distinguer les vrais messages des faux.
Prérequis
- Propriétaire ou admin dans l’espace de travail – l’entrée de menu « Webhooks » n’apparaît que pour ces rôles
- À partir de Creator Pro ; avec Creator Free, il est indiqué « Les webhooks sont disponibles à partir de Creator Pro. »
- Jusqu’à 5 webhooks avec Creator Pro, 25 avec Creator Agency, 100 avec Enterprise (ajustable)
- Un serveur joignable à une adresse https publique
Vous gérez les webhooks uniquement dans le tableau de bord. Ils ne peuvent pas être créés ni modifiés avec des clés API.
Créer un webhook
- Ouvrez « Webhooks » dans la navigation
- Cliquez sur « + Nouveau webhook »
- Saisissez l’URL cible et choisissez les événements
- Facultatif : saisissez une description et choisissez le statut
- Cliquez sur « Créer un webhook »
- À l’étape « Terminé », copiez le secret de signature (« Secret de signature – visible uniquement maintenant ») et conservez-le sur votre serveur – il n’est affiché qu’à ce moment
- Testez le webhook avec « Tester ». Le résultat reste sur la carte jusqu’au test suivant : « Livré avec succès » ou « Non livré » avec le code HTTP (ou « aucune réponse »), la durée et le début de la réponse
- « URL cible (https://…) »
- Jusqu’à 2048 caractères. https uniquement, pas d’identifiants dans l’URL, pas d’adresses localhost ni de noms internes comme .local, .internal ou .lan. Le nom doit pointer vers des adresses IP publiques ; LinkHarbor le vérifie à nouveau avant chaque livraison.
- « Événements »
- Au moins un événement. Chaque groupe a « Tout sélectionner » et « Tout désélectionner ».
- « Description »
- Facultative, jusqu’à 255 caractères – par exemple, à quoi sert le webhook.
- « Statut »
- « Actif » ou « Désactivé ». Les webhooks désactivés ne reçoivent aucune livraison.
Événements
| Événement | Dans le tableau de bord | Quand | Contenu de data |
|---|---|---|---|
| page.published | Page publiée | Une page a été publiée – dans le tableau de bord, via l’API ou par un assistant IA | page_id, version, checksum, published_by_user_id (null pour les clés API et les assistants IA) |
| form.submitted | Formulaire envoyé | Un visiteur a envoyé un formulaire sur l’une de vos pages | form_id, form_name, submission_id, page_id, block_id, submitted_at, values (clé du champ → valeur), consent (clé de consentement → true/false) |
| domain.verified | Domaine vérifié | Un domaine personnalisé a été vérifié avec succès | domain_id, hostname, verification_method, status |
| domain.disabled | Domaine désactivé | Un domaine personnalisé a été désactivé dans le tableau de bord (pas lors d’une rétrogradation) | domain_id, hostname, status |
| webhook.test | – (bouton « Tester ») | Vous cliquez sur « Tester » | message (texte dans la langue du compte de la personne qui lance le test ; ne vous y fiez pas) |
form.submitted contient les valeurs exactement telles que le visiteur les a envoyées, mais jamais son adresse IP ni son navigateur. La livraison se fait en arrière-plan : le visiteur ne l’attend pas, et une livraison échouée n’empêche pas l’envoi.
Structure d’une livraison
LinkHarbor envoie chaque livraison sous forme de POST avec un corps JSON et ces en-têtes :
| En-tête | Contenu |
|---|---|
| Content-Type | application/json |
| X-LinkHarbor-Event | Nom de l’événement, par exemple page.published |
| X-LinkHarbor-Delivery-Id | ID unique de cette livraison (UUID), identique à id dans le corps |
| X-LinkHarbor-Timestamp | Heure d’envoi en secondes Unix |
| X-LinkHarbor-Signature | sha256= suivi de la signature HMAC-SHA256 en hexadécimal |
| X-LinkHarbor-Signature-Version | v1 |
{
"id": "3f1c2a9e-8d4b-4a51-9f0e-6b7c1d2e3f40",
"event": "page.published",
"created_at": "2026-11-01T09:30:12+00:00",
"data": {
"page_id": 42,
"version": 8,
"checksum": "9b1e5c…",
"published_by_user_id": 7
}
} Les nouvelles livraisons reçoivent un nouvel id ainsi que les champs redelivery_of (l’ID de la livraison répétée) et delivery_root (l’ID de la première livraison de cette chaîne).
Vérifier la signature
Chaque webhook a son propre secret de signature (32 caractères hexadécimaux). Vous ne le voyez qu’une seule fois : à la dernière étape de la création du webhook et juste après « Secret ↺ ». Copiez-le immédiatement sur votre serveur – LinkHarbor ne l’affiche plus ensuite. LinkHarbor l’utilise pour calculer la signature ainsi :
- Construire le message : horodatage, point, ID de livraison, point, corps brut – soit timestamp.delivery_id.body
- Calculer un HMAC-SHA256 sur ce message avec le secret de signature comme clé
- Envoyer le résultat sous forme de chaîne hexadécimale avec le préfixe sha256=
Votre serveur doit vérifier la signature avec une comparaison à temps constant, refuser les livraisons dont l’horodatage date de plus de 300 secondes et conserver les ID de livraison au moins aussi longtemps pour reconnaître les répétitions. Important : c’est le corps brut qui est signé, exactement tel qu’il arrive – pas un JSON que vous auriez réencodé.
import crypto from 'node:crypto';
import express from 'express';
const app = express();
const SECRET = process.env.LH_WEBHOOK_SECRET;
const seen = new Set(); // en production : une base de données ou Redis avec expiration
app.post('/webhooks/linkharbor', express.raw({ type: 'application/json' }), (req, res) => {
const ts = req.get('X-LinkHarbor-Timestamp') || '';
const id = req.get('X-LinkHarbor-Delivery-Id') || '';
const sig = req.get('X-LinkHarbor-Signature') || '';
if (!/^\d+$/.test(ts) || Math.abs(Date.now() / 1000 - Number(ts)) > 300) {
return res.status(400).send('timestamp');
}
const expected = 'sha256=' + crypto
.createHmac('sha256', SECRET)
.update(ts + '.' + id + '.')
.update(req.body) // corps brut sous forme de Buffer
.digest('hex');
const a = Buffer.from(expected);
const b = Buffer.from(sig);
if (a.length !== b.length || !crypto.timingSafeEqual(a, b)) {
return res.status(401).send('signature');
}
const event = JSON.parse(req.body.toString('utf8'));
const key = event.delivery_root || event.id; // reconnaître les nouvelles livraisons d’une même chaîne
if (!seen.has(key)) {
seen.add(key);
// traiter ici, idéalement de façon asynchrone dans une file d’attente
}
res.sendStatus(200);
});
app.listen(3000); <?php
$secret = getenv('LH_WEBHOOK_SECRET');
$body = file_get_contents('php://input');
$ts = $_SERVER['HTTP_X_LINKHARBOR_TIMESTAMP'] ?? '';
$id = $_SERVER['HTTP_X_LINKHARBOR_DELIVERY_ID'] ?? '';
$sig = $_SERVER['HTTP_X_LINKHARBOR_SIGNATURE'] ?? '';
if (!ctype_digit($ts) || abs(time() - (int)$ts) > 300) {
http_response_code(400);
exit('timestamp');
}
$expected = 'sha256=' . hash_hmac('sha256', $ts . '.' . $id . '.' . $body, $secret);
if (!hash_equals($expected, $sig)) {
http_response_code(401);
exit('signature');
}
$event = json_decode($body, true);
// Reconnaître les livraisons en double via $event['delivery_root'] ?? $event['id'],
// puis traiter.
http_response_code(200); Tester votre endpoint avec curl
Ce script envoie une livraison de test correctement signée à votre propre serveur – pratique avant de créer le webhook dans LinkHarbor :
SECRET="your-signing-secret"
URL="https://example.com/webhooks/linkharbor"
TS=$(date +%s)
ID=$(uuidgen | tr 'A-Z' 'a-z')
BODY='{"id":"'"$ID"'","event":"webhook.test","created_at":"2026-11-01T09:30:12+00:00","data":{"message":"Ceci est un événement de test pour ce webhook."}}'
SIG="sha256=$(printf '%s' "$TS.$ID.$BODY" | openssl dgst -sha256 -hmac "$SECRET" -hex | sed 's/^.* //')"
curl -X POST "$URL" \
-H "Content-Type: application/json" \
-H "X-LinkHarbor-Event: webhook.test" \
-H "X-LinkHarbor-Delivery-Id: $ID" \
-H "X-LinkHarbor-Timestamp: $TS" \
-H "X-LinkHarbor-Signature: $SIG" \
-H "X-LinkHarbor-Signature-Version: v1" \
-d "$BODY" Réponse, délai d’attente et nouvelle livraison
- Toute réponse avec un statut 2xx compte comme un succès ; les redirections (3xx) ne sont pas suivies
- Votre serveur a 10 secondes pour répondre, et au maximum 5 secondes pour établir la connexion
- Tous les webhooks d’un même événement se partagent 25 secondes au total ; ceux qui n’ont pas été traités d’ici là sont marqués comme échoués et peuvent être relivrés
- LinkHarbor ne réessaie pas automatiquement les livraisons échouées
- Vous pouvez renvoyer à la main les livraisons échouées, mais pas une livraison qui a réussi entre-temps. La nouvelle livraison a un nouvel id et un nouveau created_at
- Au maximum 3 tentatives sont autorisées par événement, première livraison comprise ; ensuite, il se retrouve sous « Messages en échec » et ne peut plus être renvoyé
Les livraisons dans le tableau de bord
« Livraisons » ouvre le journal d’un webhook. Il comporte trois onglets :
- « Toutes les livraisons »
- Toutes les livraisons, avec des filtres par événement, statut (« Succès (2xx) », « Erreur client (4xx) », « Erreur serveur (5xx) », « Échecs ») et « Limite ». « ↺ Réessayer » relivre une livraison échouée, tant qu’il n’y a pas de livraison ultérieure réussie. Un clic sur une ligne affiche la requête, la réponse, le corps et le JSON brut.
- « Relectures »
- Chaînes de nouvelles livraisons avec le résultat « Rétabli » ou « Toujours en échec » et le nombre de tentatives.
- « Messages en échec »
- Livraisons pour lesquelles toutes les tentatives autorisées ont échoué – la première livraison et les nouvelles livraisons ensemble. L’onglet est en lecture seule : elles ne peuvent plus être relivrées. Vérifiez votre endpoint ; les nouveaux événements sont ensuite livrés normalement. Si vous avez besoin des données, récupérez-les via l’API.
Si une nouvelle livraison n’aboutit pas, le tableau de bord en donne la raison :
- « Non renvoyé : cet événement a déjà échoué … fois, aucune autre tentative n’est possible. Vous le trouverez sous “Messages en échec”. »
- Les 3 tentatives ont été épuisées.
- « Non renvoyé : cet événement a entre-temps été livré avec succès. »
- Une livraison ultérieure de la même chaîne a déjà réussi.
Vérification dans le tableau de bord
Sous « Vérification », vous trouvez deux aides :
- « Kit de vérification »
- « Charger le kit » affiche l’algorithme, les noms des en-têtes, le format du message signé et la tolérance recommandée de 300 secondes. Le secret lui-même n’est pas inclus.
- « Vérifier la signature »
- Saisissez l’ID de livraison, l’horodatage, la signature et le corps brut d’une livraison reçue. LinkHarbor vous indique alors « Signature valide » ou « Signature invalide ». Copiez l’horodatage et la signature depuis les en-têtes X-LinkHarbor-Timestamp et X-LinkHarbor-Signature. La vérification ne fonctionne que pour les livraisons des 5 dernières minutes ; pour les plus anciennes, elle indique « Signature invalide » même si la signature est correcte.
Renouveler le secret, désactiver, supprimer
- « Secret ↺ » génère un nouveau secret de signature et l’affiche une fois ; l’ancien cesse immédiatement de fonctionner, et votre serveur doit utiliser le nouveau
- Sous « Modifier », réglez le statut sur « Désactivé » pour suspendre les livraisons
- L’icône de corbeille supprime le webhook ; tant que vous ne fermez pas le message, vous pouvez annuler avec « Annuler »
Lors d’un passage à une offre inférieure, les webhooks au-delà de la nouvelle limite sont désactivés, et avec Creator Free tous. Ils sont conservés ; après une mise à niveau, LinkHarbor réactive automatiquement les webhooks désactivés jusqu’à la limite de la nouvelle offre – y compris ceux que vous aviez désactivés vous-même.
Cela pourrait aussi vous être utile
Vous n’avez rien trouvé ?
Dites-nous ce dont vous avez besoin, et notre équipe support vous aidera personnellement.