La requête
UnPOST 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 :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… :
- Prenez
t, l’heure de la signature, et chaquev1. - Refusez l’appel si
test à plus de 5 minutes de votre horloge : un appel intercepté ne peut pas être rejoué plus tard. - 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. - Comparez-le, en temps constant, à chaque
v1. Une correspondance suffit.
lekalao_verify_webhook() au thème ou à l’extension qui reçoit les appels.
L’ancien en-tête
Les appels portent aussiX-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’un2xx, 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
204tout 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épondez2xxà 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_atdit 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.