Suppressies
Je werkruimte heeft een suppressielijst: een verzameling e-mailadressen waar we niet aan bezorgen. Hard bounces en spamklachten komen er automatisch op terecht, en je kunt zelf adressen toevoegen. Herhaaldelijk mailen naar adressen die bouncen of spam melden kan ertoe leiden dat mailboxproviders je domein blokkeren, dus we stoppen die verzendingen voordat ze het platform verlaten.
Een nieuwe uitschrijving voegt geen suppressierecord toe. Het legt de eigen voorkeur van de ontvanger vast in plaats van een afleveringsfeit, en staat daarom op het tabblad Preferences. Zie Uitschrijflinks voor hoe dat werkt.
Beheer de lijst in Email > Suppressions, via de suppressions-API of met bird email suppressions.

De drie redenen en wat ze blokkeren
Elk record heeft een reason die aangeeft waarom het adres op de lijst staat, en een applies_to-beleid dat bepaalt welke categorieën het blokkeert:
| Reden | applies_to | Marketingcategorie | Transactionele categorie |
|---|---|---|---|
| hard_bounce | all | Geblokkeerd | Geblokkeerd |
| complaint | non_transactional | Geblokkeerd | Toegestaan |
| manual | all | Geblokkeerd | Geblokkeerd |
De verdeling volgt uit wat elke reden betekent:
- hard_bounce: het adres bestaat niet. Verzenden is zinloos in elke categorie, dus het blokkeert alles.
- complaint: een verklaring over ongewenste mail. Iemand die je nieuwsbrief als spam heeft gemeld, kan nog steeds een wachtwoordreset of een orderbevestiging nodig hebben, dus het blokkeert alleen niet-transactionele verzendingen.
- manual: een bewuste beslissing van jou of je team. We trekken die niet in twijfel, dus een handmatige suppressie blokkeert elke categorie, inclusief transactioneel.
Een adres heeft één record per reden, dus een hard bounce en een eerdere klacht staan naast elkaar als afzonderlijke records, en bezorging blijft geblokkeerd zolang er een blokkerend record bestaat. We kiezen bij onbekende waarden altijd voor blokkeren: als een record terugkomt met een applies_to die je integratie nog nooit heeft gezien, behandel het dan als blokkerend voor elke categorie, want zo behandelen wij het zelf ook.
Note: reason: unsubscribe is deprecated on the suppressions API. New unsubscribes record a preference instead of a suppression. The deprecated ?reason=unsubscribe filter still returns legacy suppression records with origin: unsubscribe_link or origin: unsubscribe_event until those records are removed.
Hoe adressen automatisch worden toegevoegd
We voegen suppressies toe op basis van signalen van ontvangers, dus een bounce of klacht vereist geen actie van jou:
| Trigger | Resulterende suppressie |
|---|---|
| Hard bounce (email.bounced) | reason: hard_bounce, origin: bounce_event, applies_to: all |
| Out-of-band hard bounce (email.out_of_band_bounce) | reason: hard_bounce, origin: bounce_event, applies_to: all |
| Spamklacht (email.complained) | reason: complaint, origin: complaint_event, applies_to: non_transactional |
Een uitschrijving, via de link in de berichttekst of de one-click-knop, verschijnt hier niet: die registreert een voorkeur op het tabblad Preferences in plaats van een rij aan deze lijst toe te voegen.
Alleen een bounce van de klasse hard leidt tot suppressie, en de classificatietabel toont welke bounce_class-waarden als hard tellen. Twee uitkomsten die op fouten lijken laten het adres verzendbaar:
- Soft bounces en deferrals (email.deferred, of email.bounced met bounce_type: "soft"): tijdelijke fouten zoals een volle mailbox. We proberen het opnieuw.
- Afwijzingen aan de verzendzijde: generatiefouten en beleidsafwijzingen zijn problemen met de verzending, niet met het adres. Ze produceren email.rejected-events en geen suppressie.
Herhaalde signalen voor een adres dat al is onderdrukt met dezelfde reden laten het oorspronkelijke record intact, inclusief de created_at. Het record behoudt source_email_id en source_recipient_id, die een automatische suppressie koppelen aan het exacte bericht en de ontvanger die het veroorzaakten. Die twee velden beantwoorden de supportvraag "why did this person stop getting our email", en ze zijn null bij handmatige toevoegingen.
Elke toevoeging, automatisch of handmatig, stuurt een email_suppression.created-event naar je webhook-endpoint met de suppression_id, het onderdrukte email, de reason en de workspace_id, zodat je eigen systeem de lijst kan spiegelen zonder te pollen:
Codevoorbeeld
{
"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"
}
}Suppressies beheren via de API
De API voegt toe, geeft weer, zoekt op en verwijdert afzonderlijke records. Adressen worden voor opslag en opzoeken naar kleine letters omgezet, en ze verschijnen nooit in een URL-pad, omdat een pad in toegangslogs belandt en een e-mailadres persoonsgegevens is. Om het record voor een adres te vinden filter je de lijst met ?email=.
Elke SDK biedt deze bewerkingen aan als getypte methoden op de suppressions-resource.
Een adres toevoegen
const suppression = await bird.suppressions.add({ email: "user@example.com" });
console.log(suppression.id);suppression = client.suppressions.add(email="user@example.com")
print(suppression.id)suppression, err := client.Suppressions.Add(context.Background(), bird.SuppressionsAddParams{
Email: "user@example.com",
})
if err != nil {
log.Fatal(err)
}
fmt.Println(suppression.Id)$suppression = $bird->suppressions->add(
(new SuppressionCreate())->setEmail('user@example.com'),
);
echo $suppression->getId();bird email suppressions add --email user@example.comcurl -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" }'Handmatige toevoegingen krijgen reason: manual en applies_to: all, dus ze blokkeren elke categorie. De aanroep is idempotent: een nieuwe suppressie retourneert 201 Created, en een adres dat al handmatig is onderdrukt retourneert 200 OK met het bestaande record in plaats van een conflict. In beide gevallen is de body het suppressie-object:
Codevoorbeeld
{
"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"
}
}Het veld origin registreert hoe het record tot stand is gekomen. Handmatige toevoegingen krijgen api_key of user, afhankelijk van of de aanroeper zich heeft geauthenticeerd met een API-sleutel of een dashboardsessie. Automatische toevoegingen krijgen bounce_event of complaint_event, afhankelijk van welk signaal ze heeft aangemaakt.
Opvragen en opzoeken
Deze aanroepen geven de eerste pagina terug. In Go start het lege derde argument de paginering; geef de NextCursor van de vorige pagina mee om de volgende pagina op te halen.
const page = await bird.suppressions.list({ limit: 25 });
console.log(page.data.length);page = client.suppressions.list(limit=25)
print(len(page.data))page, err := client.Suppressions.ListPage(context.Background(), bird.SuppressionsListParams{Limit: 25}, "")
if err != nil {
log.Fatal(err)
}
fmt.Println(len(page.Data))$page = $bird->suppressions->list(['limit' => 25])->fetch();
echo count($page->data);bird email suppressions list --limit 25curl "https://us1.platform.bird.com/v1/email/suppressions?limit=25" \
-H "Authorization: Bearer $BIRD_API_KEY"De lijst is cursor-gepagineerd, nieuwste eerst, en filterbaar op reason. Om één adres te controleren geef je het mee als queryparameter email:
const page = await bird.suppressions.list({ email: "user@example.com" });
console.log(page.data.length);page = client.suppressions.list(email="user@example.com")
print(len(page.data))page, err := client.Suppressions.ListPage(context.Background(), bird.SuppressionsListParams{
Email: "user@example.com",
}, "")
if err != nil {
log.Fatal(err)
}
fmt.Println(len(page.Data))$page = $bird->suppressions->list(['email' => 'user@example.com'])->fetch();
echo count($page->data);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"Het email-filter matcht hoofdletterongevoelig op prefix: user@example.com matcht ook user@example.com.au. Vergelijk elk teruggegeven adres met het volledige adres dat je hebt opgevraagd, en volg next_cursor door elke pagina voordat je beslist of er een overeenkomend record bestaat. Meerdere records kunnen op één adres van toepassing zijn. MCP-aanroepers kunnen email_suppressions_check gebruiken voor deze exacte-adreszoekopdracht.
Zodra je een suppressie-ID hebt, geeft GET /v1/email/suppressions/{suppression_id} dat ene record terug: suppressions.get in de SDK's, of bird email suppressions get <id> op de CLI.
Een adres verwijderen
await bird.suppressions.remove("sup_01ky7qckqrf06r38g49b9kxdbc");client.suppressions.remove("sup_01ky7qckqrf06r38g49b9kxdbc")if err := client.Suppressions.Remove(context.Background(), "sup_01ky7qckqrf06r38g49b9kxdbc"); err != nil {
log.Fatal(err)
}$bird->suppressions->remove('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"Eén reden kan niet op deze manier worden verwijderd. Een complaint-record wordt alleen verwijderd door een ingelogde dashboardgebruiker; een API-sleutel krijgt 422 SuppressionNotRemovableByAPIKey. hard_bounce- en manual-records zijn op beide manieren verwijderbaar.
Retourneert 204 No Content en verwijdert dat record permanent. Andere records voor hetzelfde adres blijven bestaan, en aflevering blijft geblokkeerd zolang een resterend record de berichtcategorie blokkeert. Om records per adres te verwijderen pagineer je de ?email=-zoekopdracht, selecteer je alleen exacte adresovereenkomsten en verwijder je elk beoogd record op ID. Wees voorzichtig met het verwijderen van een hard_bounce-record, want een adres dat nog steeds niet bestaat bouncet bij de volgende verzending en onderdrukt zichzelf opnieuw.
Wat er gebeurt als je naar een onderdrukt adres verzendt
We weigeren de ontvanger op een plek waar je het kunt zien. De ontvanger krijgt een recipient_id en verschijnt in de ontvangerslijst van het bericht met status rejected. De events API en je webhooks registreren een email.rejected-event met rejection_reason: "recipient_suppressed". De overige ontvangers worden normaal afgeleverd.
Het bericht zelf wordt nog steeds geaccepteerd met een 202, zelfs als al zijn ontvangers onderdrukt zijn. We verwerken suppressie na het accepteren van de verzending, terwijl we het bericht verwerken, dus een adres dat je nu toevoegt is binnen een paar minuten actief en stopt nooit een verzending die al onderweg is.
Testen met de sandbox
De testsandbox test suppressieverwerking deterministisch. Verzenden naar suppressed@messagebird.dev gedraagt zich alsof het adres op je lijst staat: de ontvanger wordt geweigerd met rejection_reason: "recipient_suppressed" en bereikt nooit de aflevering. De sandbox-bounce- en klachtadressen (bounce@messagebird.dev, complaint@messagebird.dev) doorlopen de echte eventpipeline zonder iets naar je suppressielijst te schrijven, zodat dezelfde testadressen herbruikbaar blijven tussen runs.
Volgende stappen
- Categorieën: transactional versus marketing, en hoe de categorie samenwerkt met het suppressiebeleid
- Uitschrijflinks: hoe opt-outs een voorkeur vastleggen in plaats van een suppressie
- Events en webhooks: de email.rejected-payload en de lifecycle-events die automatische suppressie aansturen
- Testsandbox: magische adressen om elk afleveringsresultaat te simuleren
- API-referentie: Suppressions: volledige request- en responseschema's
- Wat er gebeurt wanneer iemand zich afmeldt: een video die één ontvanger volgt van de uitschrijfpagina tot een geweigerde verzending
Gerelateerde bronnen
Ga verder met de documentatie, gidsen en voorbeelden voor dit onderwerp. De bronnen zijn in het Engels.
Begrijp het conceptWhat is one-click unsubscribe, and how do I implement List-Unsubscribe?Ontdek de mogelijkheidEmail opt-outsVolg het leerpadOperate messaging reliably
Ontvang een implementatieoverzicht