Skip to content
Langue: Français

API pour les développeurs

Webhooks : événements, contenu et signature

Mis à jour le 1 novembre 2026 8 min de lecture

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

Page Webhooks sans webhook et le bouton « + Nouveau webhook »
La page Webhooks de l’espace de travail
  1. Ouvrez « Webhooks » dans la navigation
  2. Cliquez sur « + Nouveau webhook »
  3. Saisissez l’URL cible et choisissez les événements
  4. Facultatif : saisissez une description et choisissez le statut
  5. Cliquez sur « Créer un webhook »
  6. À 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
  7. 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énementDans le tableau de bordQuandContenu de data
page.publishedPage publiéeUne page a été publiée – dans le tableau de bord, via l’API ou par un assistant IApage_id, version, checksum, published_by_user_id (null pour les clés API et les assistants IA)
form.submittedFormulaire envoyéUn visiteur a envoyé un formulaire sur l’une de vos pagesform_id, form_name, submission_id, page_id, block_id, submitted_at, values (clé du champ → valeur), consent (clé de consentement → true/false)
domain.verifiedDomaine vérifiéUn domaine personnalisé a été vérifié avec succèsdomain_id, hostname, verification_method, status
domain.disabledDomaine 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êteContenu
Content-Typeapplication/json
X-LinkHarbor-EventNom de l’événement, par exemple page.published
X-LinkHarbor-Delivery-IdID unique de cette livraison (UUID), identique à id dans le corps
X-LinkHarbor-TimestampHeure d’envoi en secondes Unix
X-LinkHarbor-Signaturesha256= suivi de la signature HMAC-SHA256 en hexadécimal
X-LinkHarbor-Signature-Versionv1
Exemple de contenu pour page.published
{
  "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 :

  1. Construire le message : horodatage, point, ID de livraison, point, corps brut – soit timestamp.delivery_id.body
  2. Calculer un HMAC-SHA256 sur ce message avec le secret de signature comme clé
  3. 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é.

Node.js (Express) : recevoir et vérifier un webhook
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 : recevoir et vérifier un webhook
<?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 :

Simuler une livraison de test signée
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.

Vous n’avez rien trouvé ?

Dites-nous ce dont vous avez besoin, et notre équipe support vous aidera personnellement.

Contacter le support