Suppressions
Votre espace de travail possède une liste de suppression : un ensemble d'adresses e-mail auxquelles nous ne livrons pas. Les rebonds définitifs et les plaintes pour spam y sont ajoutés automatiquement, et vous pouvez aussi ajouter des adresses vous-même. Envoyer de façon répétée à des adresses qui rebondissent ou signalent du spam peut faire bloquer votre domaine par les fournisseurs de messagerie, c'est pourquoi nous arrêtons ces envois avant qu'ils ne quittent la plateforme.
Un désabonnement ne figure pas sur cette liste. Il enregistre la préférence déclarée du destinataire plutôt qu'un fait de délivrabilité, et se trouve donc dans l'onglet Preferences à la place. Consultez Liens de désabonnement pour comprendre son fonctionnement.
Gérez la liste dans Email > Suppressions, via les suppressions API, ou avec bird email suppressions.

Les trois motifs et ce qu'ils bloquent
Chaque enregistrement possède un reason indiquant pourquoi l'adresse est listée, et une politique applies_to contrôlant quelles catégories il bloque :
| Motif | applies_to | Catégorie marketing | Catégorie transactionnelle |
|---|---|---|---|
| hard_bounce | all | Bloqué | Bloqué |
| complaint | non_transactional | Bloqué | Autorisé |
| manual | all | Bloqué | Bloqué |
Cette répartition découle de la signification de chaque motif :
- hard_bounce : l'adresse n'existe pas. L'envoi est inutile quelle que soit la catégorie, donc tout est bloqué.
- complaint : une déclaration concernant du courrier indésirable. Une personne ayant signalé votre newsletter comme spam peut encore avoir besoin d'une réinitialisation de mot de passe ou d'une confirmation de commande, donc seuls les envois non transactionnels sont bloqués.
- manual : une décision délibérée de votre part ou de celle de votre équipe. Nous ne la remettons pas en question, donc une suppression manuelle bloque toutes les catégories, y compris les transactionnelles.
Une adresse contient un enregistrement par motif, de sorte qu'un rebond définitif et une plainte antérieure coexistent comme des enregistrements distincts, et la livraison reste bloquée tant qu'un enregistrement bloquant subsiste. Nous appliquons le blocage par défaut sur tout ce que nous ne reconnaissons pas : si un enregistrement revient avec un applies_to que votre intégration n'a jamais vu, traitez-le comme bloquant toutes les catégories, ce que nous faisons nous-mêmes.
Note: reason: unsubscribe is deprecated on the suppressions API. Unsubscribes now record a preference instead of a suppression, so ?reason=unsubscribe matches nothing.
Comment les adresses sont ajoutées automatiquement
Nous ajoutons des suppressions en réponse aux signaux des destinataires, un rebond ou une plainte ne nécessite donc aucune action de votre part :
| Déclencheur | Suppression résultante |
|---|---|
| Rebond définitif (email.bounced) | reason: hard_bounce, origin: bounce_event, applies_to: all |
| Rebond définitif hors bande (email.out_of_band_bounce) | reason: hard_bounce, origin: bounce_event, applies_to: all |
| Plainte pour spam (email.complained) | reason: complaint, origin: complaint_event, applies_to: non_transactional |
Un désabonnement, que ce soit via le lien dans le corps du message ou le bouton de désabonnement en un clic, n'apparaît pas ici : il enregistre une préférence dans l'onglet Preferences au lieu d'ajouter une ligne à cette liste.
Seul un rebond de classe hard entraîne une suppression, et le tableau de classification indique quelles valeurs bounce_class sont considérées comme définitives. Deux résultats qui ressemblent à des échecs laissent l'adresse envoyable :
- Rebonds temporaires et reports (email.deferred, ou email.bounced avec bounce_type: "soft") : des échecs transitoires comme une boîte aux lettres pleine. Nous réessayons.
- Rejets côté envoi : les échecs de génération et les rejets de politique sont des problèmes liés à l'envoi plutôt qu'à l'adresse. Ils produisent des événements email.rejected et aucune suppression.
Les signaux répétés pour une adresse déjà supprimée pour le même motif ne modifient pas l'enregistrement d'origine, y compris son created_at. L'enregistrement conserve source_email_id et source_recipient_id, qui relient une suppression automatique au message et au destinataire exacts qui l'ont provoquée. Ces deux champs répondent à la question du support "why did this person stop getting our email", et ils sont null pour les ajouts manuels.
Chaque ajout, automatique ou manuel, déclenche un événement email_suppression.created vers votre point de terminaison webhook avec le suppression_id, l'adresse supprimée email, le reason et le workspace_id, afin que votre propre système puisse reproduire la liste sans interrogation périodique :
Exemple de code
{
"type": "email_suppression.created",
"timestamp": "2026-07-23T14:52:03.192524705Z",
"data": {
"email": "user@example.com",
"reason": "manual",
"suppression_id": "sup_01ky7qckqrf06r38g49b9kxdbc",
"workspace_id": "ws_01ky7m21hjffh9s8kq76gyb1xf"
}
}Gérer les suppressions via le API
Le API permet d'ajouter, de lister, de consulter et de supprimer des enregistrements individuels. Les adresses sont mises en minuscules avant le stockage et la recherche, et n'apparaissent jamais dans un chemin d'URL, car un chemin se retrouve dans les journaux d'accès et une adresse e-mail est une donnée personnelle. Pour trouver l'enregistrement d'une adresse, filtrez la liste avec ?email=.
Les exemples SDK accèdent aux suppressions via la méthode de requête brute de chaque client, qui gère l'authentification, les nouvelles tentatives et l'URL de base de la même manière qu'un appel typé. La forme de la réponse est celle que vous déclarez.
Ajouter une adresse
type Suppression = { id: string; email: string; reason: string };
const suppression = await bird.request<Suppression>({
method: "POST",
path: "/v1/email/suppressions",
body: { email: "user@example.com" },
});client.post("/v1/email/suppressions", body={"email": "user@example.com"})var suppression struct {
Id string `json:"id"`
Email string `json:"email"`
Reason string `json:"reason"`
}
if err := client.Post(context.Background(), "/v1/email/suppressions", map[string]any{
"email": "user@example.com",
}, &suppression); err != nil {
log.Fatal(err)
}$suppression = $bird->post('/v1/email/suppressions', body: [
'email' => 'user@example.com',
]);curl -X POST https://us1.platform.bird.com/v1/email/suppressions \
-H "Authorization: Bearer $BIRD_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "email": "user@example.com" }'Sur le CLI, bird email suppressions couvre list et remove ; l'ajout d'une adresse passe par le API.
Les ajouts manuels reçoivent reason: manual et applies_to: all, ils bloquent donc toutes les catégories. L'appel est idempotent : une nouvelle suppression renvoie 201 Created, et une adresse déjà manuellement supprimée renvoie 200 OK avec l'enregistrement existant plutôt qu'un conflit. Dans les deux cas, le corps est l'objet de suppression :
Exemple de code
{
"applies_to": "all",
"created_at": "2026-07-23T14:52:03.192524705Z",
"email": "user@example.com",
"id": "sup_01ky7qckqrf06r38g49b9kxdbc",
"origin": "api_key",
"reason": "manual",
"scope": {
"id": "ws_01ky7m21hjffh9s8kq76gyb1xf",
"type": "workspace"
}
}Le champ origin enregistre comment l'enregistrement a été créé. Les ajouts manuels reçoivent api_key ou user, selon que l'appelant s'est authentifié avec une clé API ou une session du tableau de bord. Les ajouts automatiques reçoivent bounce_event ou complaint_event, selon le signal qui les a créés.
Lister et consulter
type Suppressions = { data: Array<{ id: string; email: string; reason: string }> };
const suppressions = await bird.request<Suppressions>({
method: "GET",
path: "/v1/email/suppressions?limit=25",
});
console.log(suppressions.data.length);suppressions = client.get("/v1/email/suppressions?limit=25")
print(len(suppressions["data"]))var out struct {
Data []struct {
Email string `json:"email"`
Reason string `json:"reason"`
} `json:"data"`
}
if err := client.Get(context.Background(), "/v1/email/suppressions?limit=25", &out); err != nil {
log.Fatal(err)
}
fmt.Println(len(out.Data))$suppressions = $bird->get('/v1/email/suppressions', query: ['limit' => 25]);bird email suppressions list --limit 25curl "https://us1.platform.bird.com/v1/email/suppressions?limit=25" \
-H "Authorization: Bearer $BIRD_API_KEY"La liste est paginée par curseur, du plus récent au plus ancien, et filtrable par reason. Pour vérifier une adresse, passez-la comme paramètre de requête email :
const suppressions = await bird.request({
method: "GET",
path: "/v1/email/suppressions?email=user@example.com",
});
console.log(suppressions.data.length);suppressions = client.get("/v1/email/suppressions?email=user@example.com")
print(len(suppressions["data"]))var out struct {
Data []struct {
Email string `json:"email"`
Reason string `json:"reason"`
} `json:"data"`
}
if err := client.Get(context.Background(), "/v1/email/suppressions?email=user@example.com", &out); err != nil {
log.Fatal(err)
}
fmt.Println(len(out.Data))$suppressions = $bird->get('/v1/email/suppressions', query: ['email' => 'user@example.com']);bird email suppressions list --email user@example.comcurl "https://us1.platform.bird.com/v1/email/suppressions?email=user@example.com" \
-H "Authorization: Bearer $BIRD_API_KEY"Un tableau data vide signifie que l'adresse n'est pas supprimée, et plusieurs enregistrements sont renvoyés lorsque plus d'un motif s'applique. Le filtre email effectue une correspondance insensible à la casse par préfixe, de sorte qu'une adresse complète renvoie les enregistrements de cette adresse et qu'un fragment tel que alice renvoie toutes les adresses supprimées commençant par celui-ci.
Supprimer une adresse
await bird.request({
method: "DELETE",
path: "/v1/email/suppressions/sup_01ky7qckqrf06r38g49b9kxdbc",
});client.delete("/v1/email/suppressions/sup_01ky7qckqrf06r38g49b9kxdbc")if err := client.Delete(context.Background(), "/v1/email/suppressions/sup_01ky7qckqrf06r38g49b9kxdbc", nil); err != nil {
log.Fatal(err)
}$bird->delete('/v1/email/suppressions/sup_01ky7qckqrf06r38g49b9kxdbc');bird email suppressions remove sup_01ky7qckqrf06r38g49b9kxdbc --yescurl -X DELETE https://us1.platform.bird.com/v1/email/suppressions/sup_01ky7qckqrf06r38g49b9kxdbc \
-H "Authorization: Bearer $BIRD_API_KEY"Renvoie 204 No Content. La suppression est définitive : nous ne conservons rien, et l'adresse redevient envoyable. Supprimer par adresse nécessite deux appels, une recherche ?email= pour obtenir l'ID puis la suppression, et une adresse supprimée pour plusieurs motifs nécessite la suppression de chaque enregistrement bloquant. Soyez prudent lorsque vous retirez un enregistrement hard_bounce, car une adresse qui n'existe toujours pas rebondira au prochain envoi et se supprimera de nouveau automatiquement.
Ce qui se passe lorsque vous envoyez à une adresse supprimée
Nous rejetons le destinataire de manière visible. Le destinataire reçoit un recipient_id et apparaît dans la liste des destinataires du message avec le statut rejected. Les événements API et vos webhooks enregistrent un événement email.rejected avec rejection_reason: "recipient_suppressed". Les autres destinataires sont livrés normalement.
Le message lui-même est toujours accepté avec un 202, même lorsque tous ses destinataires sont supprimés. Nous résolvons la suppression après avoir accepté l'envoi, pendant le traitement du message, de sorte qu'une adresse que vous ajoutez maintenant s'applique en quelques minutes et n'arrête jamais un envoi déjà en cours.
Tester avec le sandbox
Le sandbox de test exerce la gestion des suppressions de manière déterministe. Envoyer à suppressed@messagebird.dev se comporte comme si l'adresse figurait sur votre liste : le destinataire est rejeté avec rejection_reason: "recipient_suppressed" et n'atteint jamais la livraison. Les adresses de rebond et de plainte du sandbox (bounce@messagebird.dev, complaint@messagebird.dev) exécutent leurs résultats via le pipeline d'événements réel sans rien écrire dans votre liste de suppression, de sorte que les mêmes adresses de test restent réutilisables d'un test à l'autre.
Étapes suivantes
- Catégories : transactional versus marketing, et comment la catégorie interagit avec la politique de suppression
- Liens de désabonnement : comment les désinscriptions enregistrent une préférence déclarée au lieu d'une suppression
- Événements et webhooks : le contenu email.rejected et les événements du cycle de vie qui déclenchent la suppression automatique
- Sandbox de test : adresses magiques pour simuler chaque résultat de livraison
- Référence API : Suppressions : schémas complets de requête et de réponse
- Ce qui se passe quand quelqu'un se désinscrit : une vidéo qui suit un destinataire de la page de désabonnement jusqu'à un envoi rejeté
Ressources associées
Poursuivez avec la documentation, les guides et les exemples sur ce sujet. Les ressources sont en anglais.
Comprendre le conceptWhat is one-click unsubscribe, and how do I implement List-Unsubscribe?Explorer la fonctionnalitéEmail opt-outsSuivre le parcours d'apprentissageOperate messaging reliably
Obtenir un guide d'implémentation