Présentation des webhooks
Recevez des notifications en temps réel sur les événements e-mail via des webhooks
Les webhooks envoient des notifications HTTP en temps réel à votre serveur lorsque des événements e-mail se produisent : livraisons, rebonds, plaintes, et plus encore. Au lieu d'interroger périodiquement les changements d'état, MailLand transmet les événements à votre endpoint au moment où ils se produisent.
Fonctionnement des webhooks
Configurer un webhook
Enregistrez l'URL de votre endpoint et sélectionnez les événements que vous souhaitez recevoir.
Mail.Land envoie les événements
Lorsqu'un événement se produit (par exemple, un e-mail est livré), MailLand envoie un HTTP POST signé à votre endpoint avec le payload de l'événement.
Votre serveur répond
Renvoyez un code de statut 2xx pour accuser réception. Les réponses non-2xx déclenchent des nouvelles tentatives automatiques.
Créer un webhook
POST https://api.mail.land/v1/webhookscurl -X POST https://api.mail.land/v1/webhooks \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
-H "Content-Type: application/json" \
-d '{
"name": "Production Events",
"webhookUrl": "https://your-app.com/webhooks/mailland",
"products": ["transactional", "marketing"],
"events": ["message.delivered", "message.bounced", "message.deferred", "message.complained"],
"includeFutureEvents": true,
"scope": "all_domains"
}'Champs de la requête
| Champ | Type | Requis | Description |
|---|---|---|---|
name | string | Non | Nom lisible pour ce webhook |
webhookUrl | string | Oui | URL de l'endpoint HTTPS pour recevoir les événements |
products | array | Non | Filtre produit : transactional, marketing, inbound, system |
events | array | Non | Événements spécifiques auxquels s'abonner (voir Événements) |
includeFutureEvents | boolean | Non | Recevoir les nouveaux événements ajoutés aux produits abonnés (défaut : true) |
scope | string | Non | all_domains (défaut) ou selected_domains |
domainIds | array | Non | IDs de domaines pour le filtrage (requis si scope est selected_domains) |
Réponse
Statut : 201 Created
{
"webhook": {
"id": "k3m9x2p7qw4rtz",
"name": "Production Events",
"webhookUrl": "https://your-app.com/webhooks/mailland",
"products": ["transactional", "marketing"],
"events": ["message.delivered", "message.bounced", "message.deferred", "message.complained"],
"includeFutureEvents": true,
"scope": "all_domains",
"domainIds": [],
"isActive": true,
"createdAt": "2026-02-17T10:00:00Z",
"successCount": 0,
"failureCount": 0,
"consecutiveFailures": 0,
"pauseThreshold": 10
},
"secret": "whsec_a1b2c3d4e5f6g7h8i9j0..."
}Le secret n'est affiché qu'une seule fois lors de la création du webhook. Conservez-le en lieu sûr : vous en aurez besoin pour vérifier les signatures des webhooks. Si vous le perdez, vous pouvez le régénérer, ce qui invalide l'ancien secret.
Les URL des webhooks doivent utiliser HTTPS. MailLand valide les URL contre les attaques SSRF : les adresses de réseau privé (127.0.0.1, 10.x, 192.168.x, etc.) sont rejetées. La livraison se fait uniquement en HTTPS sur le port 443 ; une URL sur un autre port, ou pointant vers les serveurs ou noms d'hôte de MailLand, est refusée avec 400 WEBHOOK_DESTINATION_NOT_ALLOWED. Un autre port TLS nécessite une approbation explicite du support MailLand.
Lister les webhooks
GET https://api.mail.land/v1/webhookscurl -X GET https://api.mail.land/v1/webhooks \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."[
{
"id": "k3m9x2p7qw4rtz",
"name": "Production Events",
"webhookUrl": "https://your-app.com/webhooks/mailland",
"products": ["transactional", "marketing"],
"events": ["message.delivered", "message.bounced"],
"isActive": true,
"lastTriggeredAt": "2026-02-17T12:30:00Z",
"lastSuccessAt": "2026-02-17T12:30:00Z",
"successCount": 1542,
"failureCount": 3,
"consecutiveFailures": 0,
"createdAt": "2026-02-10T08:00:00Z"
}
]Retourne jusqu'à 100 webhooks triés par date de création (le plus récent en premier).
Obtenir les détails d'un webhook
GET https://api.mail.land/v1/webhooks/{id}curl -X GET https://api.mail.land/v1/webhooks/k3m9x2p7qw4rtz \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."Retourne la configuration complète du webhook ainsi que les 50 journaux de livraison les plus récents. Consultez la Logique de nouvelles tentatives pour les détails des journaux de livraison.
Mettre à jour un webhook
PUT https://api.mail.land/v1/webhooks/{id}curl -X PUT https://api.mail.land/v1/webhooks/k3m9x2p7qw4rtz \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
-H "Content-Type: application/json" \
-d '{
"name": "All Events",
"events": ["message.delivered", "message.bounced", "message.deferred", "message.complained"],
"isActive": true
}'Tous les champs sont optionnels : incluez uniquement les champs que vous souhaitez modifier.
Tester un webhook
Envoyez un événement de test pour vérifier que votre endpoint fonctionne :
POST https://api.mail.land/v1/webhooks/{id}/testcurl -X POST https://api.mail.land/v1/webhooks/k3m9x2p7qw4rtz/test \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."{
"success": true,
"statusCode": 200,
"statusText": "OK",
"durationMs": 145,
"responseBody": "{\"received\": true}",
"headersSent": {
"X-MLND-Signature": "t=1708171200,v1=abc123...",
"X-MLND-Event-Id": "evt_test_abc123",
"X-MLND-Event-Version": "1",
"X-MLND-Event": "webhook.test",
"X-MLND-Webhook-Id": "k3m9x2p7qw4rtz",
"X-MLND-Attempt": "1"
},
"wouldReceiveRealEvents": true,
"liveEvents": ["message.delivered", "message.bounced"],
"dormantEvents": {},
"subscriptionWarning": null
}L'envoi de test utilise la même signature et le même transport de livraison qu'un événement réel : un succès ici prouve donc votre URL, votre TLS et votre vérification de signature.
Il ne prouve pas votre abonnement : un test est envoyé à la demande, sans passer par le routage de vos événements sélectionnés. Les quatre derniers champs y répondent séparément :
| Champ | Signification |
|---|---|
wouldReceiveRealEvents | Indique si un événement réel peut atteindre ce point de terminaison |
liveEvents | Événements souscrits qui passent le même filtre que le répartiteur applique |
dormantEvents | Événements souscrits qui n'arriveront jamais, chacun avec sa raison |
subscriptionWarning | Renseigné lorsque le point de terminaison est joignable mais définitivement inactif |
Un "success": true accompagné de "wouldReceiveRealEvents": false est le cas important : le point de terminaison fonctionne mais n'est abonné à rien qui puisse être livré.
Si le test échoue, le champ errorType indique la raison : ssrf_blocked (l'URL, ou une redirection depuis celle-ci, pointait vers une destination vers laquelle la plateforme refuse d'envoyer) ou network_error (délai dépassé, échec TLS, connexion refusée ; errorMessage porte le détail).
Régénérer le secret
Si vous perdez ou devez faire tourner votre secret webhook :
POST https://api.mail.land/v1/webhooks/{id}/regenerate-secretcurl -X POST https://api.mail.land/v1/webhooks/k3m9x2p7qw4rtz/regenerate-secret \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."{
"secretKey": "whsec_x9y8z7w6v5u4..."
}La régénération du secret invalide immédiatement l'ancien secret. Mettez à jour le code de vérification de votre serveur avant la prochaine livraison webhook, sinon vous rejetterez des événements valides.
Périmètre de domaine
Par défaut, les webhooks reçoivent les événements pour tous les domaines de votre espace de travail. Pour limiter un webhook à des domaines spécifiques :
{
"webhookUrl": "https://your-app.com/webhooks/mailland",
"scope": "selected_domains",
"domainIds": ["d4n8q1zt5wm3xc", "b7r2mv9k0jy4pw"]
}Seuls les événements liés à ces domaines déclencheront le webhook.
Mise en pause automatique en cas d'échecs
MailLand met automatiquement en pause les webhooks après 10 échecs de livraison consécutifs (configurable via pauseThreshold). Cela évite de gaspiller des ressources sur des endpoints hors ligne.
Lorsqu'un webhook est mis en pause :
- L'horodatage
pausedAtest défini pausedReasondécrit la raison de la mise en pause- Un événement
account.webhook_pausedest envoyé à vos autres webhooks actifs - Une notification in-app est créée
Reprendre un webhook mis en pause
Après avoir résolu le problème, reprenez la livraison :
POST https://api.mail.land/v1/webhooks/{id}/resumecurl -X POST https://api.mail.land/v1/webhooks/k3m9x2p7qw4rtz/resume \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."Cette action efface l'état de pause, réinitialise le compteur d'échecs consécutifs et réactive le webhook (isActive redevient true), de sorte que les événements futurs lui sont à nouveau livrés normalement.
Supprimer un webhook
DELETE https://api.mail.land/v1/webhooks/{id}curl -X DELETE https://api.mail.land/v1/webhooks/k3m9x2p7qw4rtz \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."Retourne 204 No Content. Si le webhook est utilisé par des routes d'e-mail entrant, ces routes seront mises à jour ou désactivées automatiquement.
Réponses d'erreur
| Statut | Code | Description |
|---|---|---|
400 | INVALID_REQUEST | URL, événements ou configuration de périmètre invalides |
403 | PLAN_LIMIT_REACHED | Nombre maximum de webhooks atteint pour votre abonnement |
404 | (corps vide) | L'ID du webhook n'existe pas : renvoyé par get, update, delete, regenerate-secret et resume |
404 | RESOURCE_NOT_FOUND | L'ID du webhook n'existe pas, renvoyé uniquement par /test |
Étapes suivantes
- Événements : référence complète de tous les types d'événements et des payloads
- Vérification de signature : vérifier l'authenticité des webhooks
- Logique de nouvelles tentatives : comprendre le comportement de nouvelles tentatives et la gestion des échecs