Passer au contenu principal
Lekalao appelle votre application quand quelque chose arrive : une inscription, un désabonnement, un rebond, un e-mail transactionnel délivré ou ouvert. Vous créez l’adresse à appeler dans Paramètres → Webhooks sortants (mode d’emploi), ou par programme.

La requête

Un POST JSON par événement et par adresse :
Le corps est le même à chaque tentative : Répondez un code 2xx dans les 15 secondes. Les redirections ne sont pas suivies.

Les événements

Abonnés

subscriber.created, subscriber.confirmed, subscriber.unsubscribed, subscriber.tag_added, subscriber.tag_removed.
tag n’est là que pour les deux événements d’étiquette.
Quelqu’un qui s’inscrit à une liste en double opt-in et ne confirme jamais ne déclenche aucun événement. Ouvrir le lien de confirmation n’est pas confirmer : seul le bouton de la page qu’il ouvre l’est.

Campagnes

campaign.sent, une fois le dernier e-mail d’une campagne parti :

Retours des fournisseurs

mail.bounced et mail.complaint, quand un fournisseur signale un rebond ou une plainte, quel que soit l’e-mail :
type vaut hard_bounce, soft_bounce ou complaint. campaign nomme la campagne de l’e-mail, transactional_mail l’e-mail transactionnel ; les deux sont null pour un e-mail d’automatisation. Un rebond transactionnel n’est jamais mis sur le compte d’une campagne.

E-mails transactionnels

La vie de chaque e-mail envoyé par l’API transactionnelle, le relais SMTP ou le transport Laravel : plus besoin de le relire pour savoir ce qu’il est devenu. data est l’e-mail tel que GET /v1/transactional-mails/{mail} le montre, avec ce que l’événement ajoute :
transactional.failed part pour chaque e-mail du journal qui finit failed, y compris les refus auxquels l’appel a déjà répondu (recipients_suppressed, monthly_quota_exceeded) : un seul gestionnaire voit tous les échecs. failure_code est détaillé dans Erreurs. Un e-mail transactionnel n’appartient à aucune liste : une adresse réglée sur une liste n’en entend pas parler.

Filtrer par liste

Une adresse réglée sur Seulement pour une liste ne reçoit que les événements de cette liste. campaign.sent suit la liste de la campagne.

Enregistrer par programme

Un webhook s’ajoute d’ordinaire à la main, dans Paramètres → Webhooks sortants. Un programme — un connecteur, votre propre back-office — peut le faire par l’API, avec un jeton autorisé à écrire :
La réponse porte le secret du webhook — une seule fois : gardez-le, c’est avec lui que se vérifie la signature. L’adresse doit être publique : une adresse qui pointe à l’intérieur d’un réseau est refusée aussitôt, par un 422. GET /v1/webhooks les liste (sans leurs secrets), DELETE /v1/webhooks/{id} en retire un, et GET /v1/webhooks/samples/{event} montre les data d’un appel avant qu’il ne se soit rien passé. Les webhooks enregistrés ainsi apparaissent dans les paramètres comme les autres, avec leurs livraisons.

Vérifier la signature

Lekalao-Signature ressemble à t=1793479272,v1=6a1f… :
  1. Prenez t, l’heure de la signature, et chaque v1.
  2. Refusez l’appel si t est à plus de 5 minutes de votre horloge : un appel intercepté ne peut pas être rejoué plus tard.
  3. Calculez le HMAC SHA-256, en hexadécimal, de t, d’un point et du corps brut, avec le secret de signature de l’adresse : HMAC(secret, "1793479272.{…corps…}"). Utilisez les octets reçus, avant tout décodage JSON.
  4. Comparez-le, en temps constant, à chaque v1. Une correspondance suffit.
Ne réencodez pas le JSON avant de calculer la signature : un espace ou un autre ordre des clés change le résultat. Et gardez l’horloge de votre serveur à l’heure (NTP) : une horloge décalée de cinq minutes refuse tous les appels.
Les connecteurs n8n et Zapier vérifient tout cela eux-mêmes ; l’extension WordPress offre lekalao_verify_webhook() au thème ou à l’extension qui reçoit les appels.

L’ancien en-tête

Les appels portent aussi X-Lekalao-Signature, le HMAC SHA-256 du seul corps brut, et X-Lekalao-Event, pour les récepteurs écrits avant Lekalao-Signature. Ils fonctionnent toujours, mais rien dans cette signature ne date l’appel : un appel enregistré aujourd’hui peut être rejoué l’an prochain. Passez à Lekalao-Signature ; l’ancien en-tête partira dans une version ultérieure, annoncée dans le journal des modifications.

Nouvelles tentatives et journal

Un appel échoue quand votre serveur répond autre chose qu’un 2xx, répond après 15 secondes, ou ne peut être joint. Lekalao réessaie alors, avec le même corps et le même identifiant d’événement, signé de nouveau : Sept tentatives sur environ 21 heures : une adresse tombée pour la nuit reçoit quand même ce qui s’est passé entre-temps. Après le septième échec, l’appel est Échoué et n’est plus retenté de lui-même. Paramètres → Webhooks sortants → Appels que nous avons faits montre chaque appel avec son statut (En attente, Nouvelle tentative prévue, Délivré, Échoué), son identifiant d’événement, l’heure de la prochaine tentative, et chaque tentative avec le code de votre serveur et sa durée. Renvoyer rappelle une fois de plus, tout de suite, avec le même identifiant d’événement. Une adresse qui n’a répondu que des échecs pendant 3 jours est désactivée, et les propriétaires de l’équipe reçoivent un e-mail. Les appels prévus pour elle s’arrêtent. Une fois votre serveur réparé, réactivez Appeler cette adresse, puis Renvoyer les appels dont vous avez besoin.

Conseils

  • Répondez vite. Mettez le travail en file et répondez 204 tout de suite : une réponse après 15 secondes est un échec, et l’appel revient.
  • Dédoublonnez sur l’identifiant d’événement. Un nouvel essai après un délai auquel vous avez répondu trop tard, ou un Renvoyer, apporte le même Lekalao-Event-Id : gardez quelques jours les identifiants traités, et répondez 2xx à un identifiant déjà connu.
  • Ne comptez pas sur l’ordre. Deux événements rapprochés peuvent arriver à l’envers, et un nouvel essai arrive après des événements plus récents ; created_at dit quand chacun est arrivé. Relisez la ressource par l’API quand l’état compte.
  • Essayez avec une clé de test. Les adresses puits déclenchent chaque événement transactionnel, signé et retenté comme les vrais.
  • En local, exposez votre serveur par un tunnel (ngrok, Cloudflare Tunnel) : Lekalao refuse d’appeler une adresse privée ou localhost.