Brevo API et webhooks : ce que les développeurs doivent vraiment savoir
Brevo API et webhooks — voilà un sujet qui m’a coûté quelques nuits blanches au début. J’avais besoin d’intégrer Brevo dans une app SaaS : créer des contacts à l’inscription, déclencher des séquences selon le comportement in-app, tracker les ouvertures et clics pour adapter le scoring. La documentation Brevo est correcte, mais elle ne couvre pas les cas tordus. Ce guide compile tout ce que j’aurais voulu avoir dès le départ.
Architecture de l’API Brevo : ce qu’il faut comprendre d’abord
L’API Brevo est une API REST classique avec authentification par clé API (header api-key). La version courante est v3 (stable, en production). Il existe aussi une v3beta pour certaines fonctionnalités avancées.
📧 Essayez Brevo gratuitement
La plateforme email marketing tout-en-un : emails, SMS, automation et CRM. Plan gratuit jusqu’à 300 emails/jour.
Essayer Brevo gratuitement →Quelques points d’architecture importants avant de commencer :
- Rate limiting : 400 requêtes/minute sur le plan Gratuit, 3 000/minute sur Business. Gérez vos retry avec exponential backoff.
- Pagination : toutes les listes retournent un champ
countet acceptent les paramètreslimit(max 1000) etoffset. - Idempotency : la création de contacts est idempotente — si un contact existe déjà, l’appel met à jour ses données plutôt que de retourner une erreur.
- SDK officiels : Node.js, Python, PHP, Ruby, Java, Go. Tous disponibles sur le GitHub de Brevo. Je recommande d’utiliser le SDK plutôt que des appels HTTP raw — il gère la sérialisation et les erreurs.
Authentification et setup initial
La clé API se génère dans Paramètres → API et intégrations → Clés API. Créez une clé par environnement (dev, staging, prod) — vous pourrez les révoquer indépendamment.
Installation SDK Node.js
npm install @getbrevo/brevo
Configuration de base
const SibApiV3Sdk = require('@getbrevo/brevo');
const defaultClient = SibApiV3Sdk.ApiClient.instance;
const apiKey = defaultClient.authentications['api-key'];
apiKey.apiKey = process.env.BREVO_API_KEY;
Gestion des contacts par API
La gestion des contacts est l’usage le plus fréquent de l’API Brevo. Voici les patterns les plus utiles.
Créer ou mettre à jour un contact (upsert)
const contactsApi = new SibApiV3Sdk.ContactsApi();
const createContact = new SibApiV3Sdk.CreateContact();
createContact.email = 'user@example.com';
createContact.attributes = {
PRENOM: 'Jean',
NOM: 'Dupont',
PLAN: 'pro',
DATE_INSCRIPTION: new Date().toISOString()
};
createContact.listIds = [5]; // ID de votre liste
createContact.updateEnabled = true; // Active l'upsert
try {
await contactsApi.createContact(createContact);
} catch (error) {
console.error('Brevo error:', error.response?.body);
}
Point important : updateEnabled: true est la clé. Sans ça, un contact déjà existant retourne une erreur 400. Avec, il est mis à jour silencieusement.
Mettre à jour les attributs d’un contact
Cas fréquent : un utilisateur change de plan, passe en trial, convertit. Mettez à jour ses attributs Brevo pour que les segments et automations réagissent en temps réel.
const updateContact = new SibApiV3Sdk.UpdateContact();
updateContact.attributes = {
PLAN: 'premium',
DATE_UPGRADE: new Date().toISOString(),
MRR: 49
};
await contactsApi.updateContact('user@example.com', updateContact);
Ajouter/retirer d’une liste
// Ajouter à une liste
const addToList = new SibApiV3Sdk.AddContactToList();
addToList.emails = ['user@example.com'];
await contactsApi.addContactToList(listId, addToList);
// Retirer d'une liste
const removeFromList = new SibApiV3Sdk.RemoveContactFromList();
removeFromList.emails = ['user@example.com'];
await contactsApi.removeContactFromList(listId, removeFromList);
Déclencher des emails transactionnels par API
Les emails transactionnels (confirmation, facture, notification) se déclenchent via l’API sendTransacEmail. C’est rapide, fiable, et intégralement loggé dans le dashboard Brevo.
const transacApi = new SibApiV3Sdk.TransactionalEmailsApi();
const sendSmtpEmail = new SibApiV3Sdk.SendSmtpEmail();
sendSmtpEmail.to = [{ email: 'user@example.com', name: 'Jean Dupont' }];
sendSmtpEmail.templateId = 12; // ID du template dans Brevo
sendSmtpEmail.params = {
PRENOM: 'Jean',
PLAN: 'Pro',
LIEN_FACTURE: 'https://app.monsite.com/factures/inv_123'
};
sendSmtpEmail.tags = ['facture', 'mensuel'];
await transacApi.sendTransacEmail(sendSmtpEmail);
Le champ tags est crucial pour filtrer dans les logs et calculer les taux de livraison par type d’email.
Les webhooks Brevo : recevoir les événements en temps réel
Les webhooks sont la partie la plus puissante de l’intégration Brevo. Ils vous permettent de réagir en temps réel aux actions de vos contacts : ouverture, clic, désabonnement, bounce, spam.
Configurer un webhook
Dans Brevo : Paramètres → API et intégrations → Webhooks → Ajouter un webhook
Vous pouvez aussi créer des webhooks via l’API :
const webhooksApi = new SibApiV3Sdk.WebhooksApi();
const createWebhook = new SibApiV3Sdk.CreateWebhook();
createWebhook.url = 'https://api.monsite.com/webhooks/brevo';
createWebhook.description = 'Tracking comportemental emails';
createWebhook.events = ['opened', 'clicked', 'unsubscribed', 'hardBounce', 'complaint'];
createWebhook.type = 'marketing'; // ou 'transactional'
await webhooksApi.createWebhook(createWebhook);
Les événements disponibles
Voici les événements webhook que vous pouvez écouter :
- opened : email ouvert (basé sur pixel de tracking)
- clicked : lien cliqué dans l’email
- delivered : email accepté par le serveur destinataire
- hardBounce : adresse invalide (email purgé automatiquement)
- softBounce : boîte pleine ou serveur temporairement indisponible
- unsubscribed : désabonnement
- complaint : signalement spam — action immédiate recommandée
- invalid_email : format d’adresse invalide
- blocked : contact en liste noire Brevo
Recevoir et traiter un webhook
// Express.js handler
app.post('/webhooks/brevo', express.json(), async (req, res) => {
// Répondre 200 immédiatement pour éviter les retries
res.sendStatus(200);
const event = req.body;
// Traitement asynchrone
await handleBrevoEvent(event);
});
async function handleBrevoEvent(event) {
const { event: type, email, date, messageId, link } = event;
switch (type) {
case 'opened':
await updateUserEngagement(email, { lastOpened: date });
break;
case 'clicked':
await trackLink(email, link, messageId);
await incrementEngagementScore(email, 3);
break;
case 'unsubscribed':
await markUserUnsubscribed(email);
await pauseAutomations(email);
break;
case 'hardBounce':
await markEmailInvalid(email);
await notifySupport(email, 'hard_bounce');
break;
case 'complaint':
await blockUser(email);
await alertOps(email, 'spam_complaint'); // À traiter en priorité
break;
}
}
Règle absolue : répondez 200 immédiatement avant tout traitement. Brevo retente les webhooks échoués (timeout ou erreur 5xx) jusqu’à 72h. Si votre handler est lent, vous allez créer des duplicates. Mettez le traitement dans une queue asynchrone (Bull, BullMQ, SQS). Pour approfondir ce sujet, consultez notre guide sur Taux de clic email marketing.
Tracking comportemental avancé avec les événements Brevo
Au-delà des webhooks emails, Brevo permet de tracker des événements comportementaux depuis votre app. C’est ce qui permet de créer des automations vraiment puissantes : « déclencher une séquence email si l’utilisateur n’a pas complété l’étape X en 48h ».
Envoyer un événement comportemental
// Tracker un événement dans votre app
const trackApi = new SibApiV3Sdk.TrackingApi();
await trackApi.createDoiContact({
email: 'user@example.com',
eventData: {
event: 'onboarding_step_completed',
properties: {
step: 3,
stepName: 'first_campaign_sent',
timestamp: Date.now()
}
}
});
Ces événements deviennent disponibles dans Brevo Marketing Automation comme déclencheurs de workflows. En pratique, j’utilise ça pour :
- Déclencher un email « Félicitations » après la première action clé dans l’app
- Identifier les utilisateurs bloqués (pas de connexion en 7 jours) et déclencher un email de réactivation
- Segmenter automatiquement les utilisateurs par niveau d’engagement
Pour aller plus loin sur les automations et workflows dans Brevo, consultez notre guide sur les automations avancées Brevo avec scoring.
Gestion des listes et segmentation par API
Pour les équipes data qui veulent synchroniser leur CRM ou data warehouse avec Brevo :
Créer des listes programmatiquement
const listsApi = new SibApiV3Sdk.ListsApi();
const createList = new SibApiV3Sdk.CreateList();
createList.name = `Segment_${segmentName}_${Date.now()}`;
createList.folderId = 2; // Dossier de destination
const { id: newListId } = await listsApi.createList(createList);
Import massif de contacts
Pour des imports massifs (100k+ contacts), utilisez l’endpoint d’import par fichier plutôt que les appels individuels :
const importContacts = new SibApiV3Sdk.RequestContactImport();
importContacts.fileBody = 'EMAIL;PRENOM;NOM;PLAN\nuser@test.com;Jean;Dupont;pro\n';
importContacts.listIds = [5, 12];
importContacts.notifyUrl = 'https://api.monsite.com/webhooks/import-complete';
importContacts.newList = { listName: 'Import-2025-01' };
await contactsApi.importContacts(importContacts);
Le traitement est asynchrone — Brevo vous notifie via le notifyUrl quand l’import est terminé avec un résumé (contacts créés, mis à jour, erreurs).
Meilleures pratiques et pièges à éviter
Gérer les erreurs correctement
L’API Brevo retourne des codes HTTP standard + un body JSON avec les détails. Les erreurs les plus fréquentes :
- 400 invalid_parameter : vérifiez les types de données (date en ISO 8601, booléen pas en string)
- 400 duplicate_parameter : contact déjà existant → ajoutez
updateEnabled: true - 403 permission_denied : votre clé API n’a pas les droits nécessaires (vérifiez les scopes)
- 429 rate_limit_exceeded : implémentez exponential backoff avec jitter
Variables d’attributs : nommage et types
Les attributs contacts Brevo sont case-sensitive et ont des types stricts. Un attribut de type DATE doit recevoir une valeur au format YYYY-MM-DD — pas un timestamp Unix. Un attribut de type NUMBER doit recevoir un nombre, pas une chaîne. Ces erreurs de typage sont silencieuses dans certains cas et causent des bugs difficiles à debugger.
Synchronisation bidirectionnelle
Si vous synchronisez Brevo avec votre CRM, attention à la boucle infinie : webhook Brevo → mise à jour CRM → mise à jour Brevo → webhook Brevo… Ajoutez un champ source dans vos mises à jour et ignorez les mises à jour qui viennent de Brevo lui-même.
Pour approfondir l’intégration des webhooks Brevo dans un contexte de production, consultez notre guide sur les webhooks et événements API Brevo.
Résumé : les endpoints les plus utiles
POST /v3/contacts— Créer/mettre à jour un contactPUT /v3/contacts/{email}— Mettre à jour les attributsPOST /v3/contacts/lists/{listId}/contacts/add— Ajouter à une listePOST /v3/smtp/email— Envoyer un email transactionnelPOST /v3/webhooks— Créer un webhookGET /v3/contacts/{email}— Récupérer un contactPOST /v3/contacts/import— Import massifGET /v3/smtp/statistics/events— Statistiques emails transactionnels
La documentation officielle est disponible sur developers.brevo.com — elle est correctement maintenue et inclut un outil de test interactif. Utilisez-le pour tester vos appels avant de les coder.