Configurer et sécuriser les webhooks

Configurer les webhooks dans la PSB : topics, sécurisation HMAC SHA256 et IP-whitelisting.

Les webhooks sont le moyen principal de recevoir des notifications en temps réel de la PSB. Lors de chaque événement pertinent (une facture reçue, un changement de statut, une confirmation de livraison), la PSB envoie une requête HTTP POST vers votre endpoint avec les détails de l'événement.

Comment fonctionnent les webhooks dans la PSB ?

Vous enregistrez un webhook (un "hook") dans la PSB avec une URL et un topic. La PSB envoie ensuite tous les événements de ce topic vers votre URL. Chaque événement contient les données pertinentes sous forme de payload JSON.

Créer un webhook

Pas d'interface disponible : il n'est actuellement pas possible de configurer un hook via l'interface utilisateur de la plateforme. Les hooks sont configurés via l'API ou via le support eConnect. Une interface self-service pour les hooks est prévue dans la feuille de route (planifiée pour le T4 2026) et fera partie de Control (Platform 2.0) : les utilisateurs pourront alors créer, modifier et supprimer des hooks eux-mêmes. D'ici là, aucun article pas-à-pas pour la configuration manuelle des hooks via l'API n'est prévu.

Enregistrez un hook via l'API :

POST /api/v1/hook

Les principaux éléments de configuration :

ChampDescriptionurlL'endpoint HTTPS vers lequel la PSB envoie les événementstopicLe type d'événement que vous souhaitez écouter (par ex. InvoiceReceived)secretUne clé secrète pour la vérification de signature HMAC

Attention : évitez de supprimer et recréer rapidement des hooks pour le même partyId et le même topic. En raison de race conditions dans le traitement des tâches, il peut arriver que temporairement aucun hook actif n'existe, ce qui empêche la livraison des événements. Attendez un instant après la suppression d'un hook avant d'en créer un nouveau, ou utilisez une mise à jour au lieu de supprimer puis recréer.

Ajouter un topic à un hook existant

Vous souhaitez ajouter un topic supplémentaire (par ex. InvoiceReceived) à un hook existant ? Mettez à jour la configuration webhook existante via l'API /hook habituelle afin que le topic souhaité figure dans le tableau topics :

{
  "topics": ["InvoiceReceived"]
}

Mettez à jour le hook existant plutôt que de le supprimer et de le recréer. Supprimer et recréer introduit une race condition où les événements peuvent ne pas être livrés temporairement (voir l'avertissement ci-dessus).

Pas en libre-service pour les clients non techniques. L'ajout d'un topic à un hook existant est une opération technique : la personne qui l'effectue doit savoir où le webhook doit pointer (l'URL de l'endpoint) et comprendre ce qu'est un webhook. Un client non technique ne peut généralement pas le faire de manière autonome. Faites appel à quelqu'un ayant des connaissances techniques (l'IT du client ou le support eConnect).

Topics fréquemment utilisés
TopicQuandInvoiceReceivedUne facture d'achat a été reçueInvoiceSentUne facture de vente a été envoyée avec succèsInvoiceSentErrorUne facture de vente n'a pas pu être livréeInvoiceSentRetryUne tentative de renvoi a été lancéeInvoiceResponseReceivedUne Invoice Response (messages de statut) a été reçueMessageLevelStatusReceivedUn message de statut MLS a été reçu de la partie expéditriceMessageLevelStatusSentUn message de statut MLS a été envoyé avec succèsOrderReceivedUn bon de commande a été reçu
Message Level Status (MLS)

Le MLS (Message Level Status) est le successeur de l'ancien MLR et fournit à la partie expéditrice un retour sur la réception et le traitement d'un document. Le MLS n'est pas activé par défaut et doit être configuré par party via la capability reviews dans la configuration SMP. Une fois le MLS activé, la PSB le gère automatiquement : en tant que Service Provider récepteur, la PSB renvoie un message MLS à l'expéditeur après réception et livraison.

Lorsque vous envoyez vous-même des documents via la PSB, vous recevez le retour MLS de la partie réceptrice sous forme d'événement webhook sur le topic MessageLevelStatusReceived. En tant que Service Provider récepteur, un webhook distinct avec le topic MessageLevelStatusSent suit dès que la PSB envoie en votre nom un MLS au SP expéditeur. Utilisez ce topic pour vérifier que vos propres réponses MLS sortantes sont bien livrées.

MessageLevelStatusSent n'est pas une confirmation de facture envoyée. Ce topic concerne un MLS que la PSB envoie en réponse à un document reçu (vous, en tant que SP récepteur, renvoyez la notification de statut à l'expéditeur d'origine), pas une facture électronique que vous avez envoyée vous-même. En cas de nombreuses notifications MessageLevelStatusSent avec peu de factures envoyées : vérifiez si le hook écoute le wildcard *sent au lieu de spécifiquement InvoiceSent (voir Topics wildcard).

Le payload contient entre autres :

ChampDescriptiondocumentIdIdentifiant unique du message MLSrefToDocumentIdIdentifiant du document originaldetails.statusCodeStatut Peppol : AP (accepted), RE (rejected), AB (acknowledged)details.descriptionExplication du récepteur

Pour recevoir des messages MLS, le hook Peppol doit contenir le champ mlsType. Les valeurs possibles sont ALWAYS_SEND (toujours renvoyer un MLS) et FAILURE_ONLY (uniquement en cas de rejet).

Conseil : vous pouvez récupérer le document MLS complet via GET /api/v1-beta/{partyId}/generic/{documentId}/download, mais le payload du webhook contient généralement suffisamment d'informations.

Sécuriser les webhooks avec HMAC

La PSB sécurise toutes les livraisons de webhooks avec des signatures HMAC SHA256. À chaque requête, la PSB envoie le header :

X-EConnect-Signature: sha256={handtekening}
Implémenter la vérification

Pour vérifier la signature :

  1. Prenez le payload JSON brut de la requête.
  2. Calculez le hash HMAC SHA256 avec votre clé secrète (la même que celle spécifiée lors de la création du hook).
  3. Comparez votre hash calculé avec la valeur du header X-EConnect-Signature.
  4. S'ils correspondent, la requête est authentique.
Prévention des replay attacks

Vérifiez également le champ sentOn dans le payload. Si ce timestamp est antérieur de plus de 5 minutes, rejetez la requête. Cela prévient les replay attacks où une requête interceptée est rejouée ultérieurement.

Options de sécurité supplémentaires

En plus de la vérification HMAC, la PSB propose des couches de sécurité supplémentaires :

  • IP-whitelisting : limitez les requêtes entrantes aux IP de production de la PSB (104.40.188.59 et 104.47.148.207)
  • Authentification OAuth webhook : la PSB peut s'authentifier auprès de votre endpoint avec des credentials OAuth2
  • Mutual SSL : utilisez des certificats clients pour une authentification TLS mutuelle
Ordre de priorité

Si vous avez configuré plusieurs hooks, la PSB détermine quel hook utiliser selon :

  1. Les hooks au niveau PartyId ont priorité sur les hooks au niveau environment
  2. Les topics spécifiques ont priorité sur les wildcards
  3. Si plusieurs hooks avec des filtres correspondent au même topic : le filtre le plus long (en nombre de caractères) gagne -- par exemple, un filtre avec une clause && supplémentaire gagne sur un filtre plus court sans cette clause. Cela évite une double livraison sans obliger les filtres à s'exclure mutuellement.
  4. En cas de priorité égale : le hook-id sert de critère de départage
Topics wildcard

En plus des topics spécifiques, vous pouvez utiliser des motifs wildcard pour capturer plusieurs types d'événements avec un seul hook.

MotifCorrespond àSend*Tous les topics avec le préfixe Send*sent / *SentTous les topics se terminant par Sent : InvoiceSent, InvoiceResponseSent, OrderSent, MessageLevelStatusSent, HookSent*ReceivedTous les événements de réception (InvoiceReceived, OrderReceived, InvoiceResponseReceived, etc.)Invoice*Tous les événements liés aux factures

Send* n'est pas identique à *sent. Send* correspond aux topics commençant par Send ; ce motif n'existe pas parmi les topics PSB standards. Pour capturer tous les événements « sent » (InvoiceSent, MessageLevelStatusSent, HookSent, etc.), utilisez *sent. InvoiceSentRetry et InvoiceSentError ne se terminent pas par Sent et ne sont donc pas couverts par le suffixe *sent.

Résolution des problèmes

Voici les problèmes courants avec les webhooks et comment les résoudre.

SymptômeCauseSolutionLes webhooks n'arrivent pasEndpoint inaccessible (délai 100 sec.)HTTPS + certificat SSL valide requis ; désactiver la protection CSRF sur l'endpoint webhookWebhook rejeté comme non sécuriséLa validation X-EConnect-Signature échoueVérifier le calcul HMAC SHA256 : payload × secret → chaîne hexadécimale avec le préfixe sha256=Attaque par rejeu bloquéeLe champ sentOn est plus ancien que 5 minutesL'endpoint traite trop lentement ou l'horloge est mal réglée« No such host is known » (erreur DNS)Le nom d'hôte de l'endpoint webhook n'est plus résolvable, p. ex. après le renommage de l'environnement ERP ou l'expiration d'un enregistrement DNSVérifier et restaurer l'enregistrement DNS du domaine de l'endpoint ; puis récupérer les événements manqués via le endpoint batchHookSentError (échec définitif)Le PSB a réessayé pendant 5 jours sans réponse 2xxVérifier les journaux de l'endpoint ; surveiller le topic HookSentError (voir ci-dessous) ; récupérer les événements manqués via le endpoint batchEndpoint hors ligne / HTTP 404 répété (acceptation ou production)Endpoint client temporairement désactivé (développement, maintenance) ou réellement inaccessibleVérifier d'abord si l'interruption est intentionnelle et temporaire (voir ci-dessous) ; ce n'est pas un incident de la plateforme eConnectAnciennes factures relivréesL'API ne renvoie pas 2xx à la première réceptionL'endpoint doit toujours renvoyer 2xx, même pour le traitement asynchroneTraitement en double lors d'un renouvellementPas de vérification d'idempotenceUtiliser le header X-EConnect-Delivery (UUID unique) pour la déduplicationFacture reçue mais n'arrive nulle part ; aucune erreur webhook visibleLe PSB a reçu la facture d'achat (topic InvoiceReceived), mais aucun hook n'est enregistré sur ce topic (jamais configuré, ou supprimé entre-temps)Vérifier d'abord la configuration du hook : InvoiceReceived figure-t-il dans les topics ? Sans hook sur ce topic, aucun HookSentError n'apparaît, donc l'absence de message d'erreur ne prouve pas que le hook est actifNombreux e-mails MessageLevelStatusSent malgré peu de factures envoyéesLe mail-hook (mailto:) ou webhook HTTP écoute le wildcard *sent au lieu de InvoiceSentModifier la configuration du topic vers InvoiceSent (même modification sur le mail-hook et sur le webhook HTTP) ; voir Topics wildcard
Facture reçue mais non livrée (pas de hook InvoiceReceived)

Le PSB peut recevoir une facture d'achat sans la transmettre à la partie destinataire. Le topic InvoiceReceived signifie que le PSB a reçu la facture ; sans hook sur ce topic, rien n'est envoyé à un endpoint.

  • L'absence d'erreurs webhook ne prouve pas que le hook fonctionne. HookSentError n'existe que si un hook est configuré et échoue à livrer.
  • Un hook peut avoir été supprimé entre-temps. Une livraison réussie antérieure vers la même partie/endpoint prouve que le hook a existé, pas qu'il est toujours présent. Vérifier donc d'abord la configuration actuelle du hook plutôt que de traiter cela comme une configuration initiale.
  • Un accusé de réception côté expéditeur n'équivaut pas à une livraison au logiciel destinataire.

Corrigez un hook manquant en mettant à jour le hook existant plutôt qu'en le supprimant et le recréant.

Surveiller et récupérer depuis HookSentError

Le PSB envoie des événements webhook (p. ex. InvoiceReceived lors de la réception d'une facture électronique) à l'endpoint configuré. Si cet endpoint est inaccessible - en raison d'un délai d'attente, d'une erreur SSL ou d'une erreur DNS comme No such host is known - le PSB réessaie avec un recul exponentiel pendant 5 jours (délai 100 sec. par tentative). Chaque tentative génère un événement HookSentRetry ; après 5 jours sans réponse 2xx, HookSentError est émis comme statut final et le PSB cesse de réessayer.

Conséquence : une facture électronique reçue ne sera pas livrée au client tant que l'endpoint est inaccessible, sans que le client s'en aperçoive directement. Actions recommandées :

  • Mettre en place une surveillance : abonner un hook (p. ex. un mail-hook) au topic HookSentError afin qu'un échec de livraison définitif soit signalé activement plutôt que de passer inaperçu. Envisager également HookSentRetry pour une détection précoce.
  • Corriger la cause racine : en cas d'erreur DNS, vérifier et restaurer l'enregistrement DNS du domaine de l'endpoint ; en cas de délais, faire répondre l'endpoint plus rapidement (2xx en 100 sec., traitement lourd de manière asynchrone).
  • Récupérer les événements manqués : les événements échoués pendant l'interruption peuvent être récupérés via le endpoint batch. La fenêtre de 5 jours signifie qu'une réparation rapide dans ce délai peut encore rattraper la livraison normale.

Première ligne : interruption côté client vs. problème technique (acceptation et production)

HookSentError, un HTTP 404 répété ou « endpoint hors ligne »/« environnement d'acceptation désactivé » peut aussi provenir du fait que le client désactive temporairement l'endpoint d'acceptation ou de production (développement, maintenance). Ce n'est pas un incident de la plateforme eConnect.

  1. Confirmer le symptôme : HookSentError, endpoint hors ligne ou HTTP 404 sur l'endpoint webhook configuré par le client. Souvent visible sous la forme exacte Response status code does not indicate success: 404 (Not Found) (généralement une HttpRequestException .NET lors de la requête hook sortante). Il s'agit d'un 404 provenant de l'endpoint du client lui-même (hors ligne ou chemin incorrect), pas de l'erreur Peppol PartyId not found lors de l'envoi (404 SMP), ni d'un 404 de ressource REST issu de la gestion des erreurs de l'API.
  2. Demander si l'interruption est intentionnelle et temporaire (développeurs/client).
  3. Confirmé temporaire → noter, aucune action supplémentaire côté eConnect jusqu'à ce que l'endpoint soit de nouveau opérationnel. Une fois que l'endpoint renvoie de nouveau du 2xx, les événements manqués peuvent être récupérés via le endpoint batch.
  4. Non intentionnel ou inconnu → suivre le runbook standard HookSentError ci-dessus (DNS/SSL/délai, journaux, surveillance, récupération batch).
Bonnes pratiques
  • Utilisez toujours HTTPS pour votre endpoint webhook
  • Implémentez un traitement idempotent : dans de rares cas, la PSB peut livrer un événement plusieurs fois
  • Retournez rapidement un code de statut 2xx : la PSB considère toute réponse non-2xx comme une erreur et réessaiera l'événement
  • Journalisez tous les événements reçus pour le débogage et l'audit
  • Utilisez un système de file d'attente (queue) de votre côté si le traitement prend du temps ; confirmez d'abord la réception, puis traitez ensuite
Questions fréquentes
Comment vérifier un webhook entrant avec HMAC SHA256 ?

Prenez le corps JSON brut de la requête, calculez le hash HMAC SHA256 avec le secret que vous avez indiqué lors de la création du hook et comparez-le avec la valeur dans le header X-EConnect-Signature (après le préfixe sha256=). Si les valeurs correspondent, vous savez que la requête provient de la PSB et n'a pas été modifiée en transit.

Pourquoi faut-il vérifier le champ sentOn dans le payload ?

Vérifiez que sentOn n'a pas plus de 5 minutes. Si l'horodatage est trop ancien, refusez la requête. Cela empêche les attaques par rejeu, où une requête interceptée est soumise à nouveau ultérieurement, même si la signature est techniquement valide.

Comment éviter les problèmes de traitement idempotent et de retries ?

Implémentez un traitement idempotent de votre côté, car la PSB peut dans de rares cas livrer un événement plusieurs fois. Retournez également rapidement un statut HTTP 2xx : toute autre réponse est considérée comme une erreur et déclenche un nouvel essai. Pour un traitement lourd, confirmez d'abord la réception, puis traitez via une file d'attente.

Que signifie HookSentError ou un endpoint qui semble hors ligne en acceptation ou en production ?

HookSentError survient après que le PSB a tenté pendant 5 jours sans réponse 2xx. Un HTTP 404 répété ou le message indiquant que l'endpoint est hors ligne provient souvent du fait que le client désactive temporairement l'endpoint d'acceptation ou de production (développement, maintenance) — ce n'est pas un incident de la plateforme eConnect. Confirmer d'abord si l'interruption est intentionnelle et temporaire ; si oui, aucune action supplémentaire n'est nécessaire jusqu'à ce que l'endpoint soit de nouveau accessible. Les événements manqués peuvent toujours être récupérés via le endpoint batch dans la fenêtre de 5 jours.

Pourquoi reçois-je de nombreux e-mails MessageLevelStatusSent alors que j'envoie peu de factures ?

C'est un comportement attendu si le mail-hook (mailto:) ou le webhook HTTP écoute le wildcard *sent au lieu de spécifiquement InvoiceSent. MessageLevelStatusSent n'est pas une confirmation d'une facture envoyée par vous-même, mais d'un MLS que la PSB envoie en réponse à un document reçu, et il relève du motif *sent avec InvoiceSent, OrderSent et HookSent. Si vous ne voulez des notifications qu'à l'envoi de factures, modifiez la configuration du topic vers InvoiceSent. InvoiceSentRetry et InvoiceSentError ne se terminent pas par Sent et ne sont donc pas couverts par *sent.


Vous préférez récupérer les documents en masse ? Consultez le batch hook.

Voir les endpoints webhook

En lien
Articles associés