Prompt
email delivery api bounce webhook suppression list
Latest observation
Oct 4, 2026
OpenAI APIWeb search: off
If you’re building an email delivery API and want to handle bounce webhooks plus a suppression list, the usual pattern is:
1) Set up a bounce webhook
Your email provider should POST events to your endpoint when an email bounces.
Typical event data includes:
- recipient email
- message ID / event ID
- bounce type:
hardorsoft - reason / diagnostic code
- timestamp
- provider metadata
Example webhook payload:
{
"event": "bounce",
"email": "user@example.com",
"message_id": "abc123",
"bounce_type": "hard",
"reason": "mailbox does not exist",
"timestamp": "2026-10-04T12:00:00Z"
}
2) Maintain a suppression list
A suppression list is a database of addresses you should not send to. Common entries:
- hard bounces
- complaints/spam reports
- unsubscribes
- repeated soft bounces, after threshold
Suggested fields:
emailreasonsource(bounce,complaint,unsubscribe)created_atprovider_message_idstatus(active,expiredif you support expiration)
3) Webhook handler logic
When you receive a bounce webhook:
- Verify signature/authentication
- Parse event type
- If hard bounce or complaint:
- add email to suppression list immediately
- If soft bounce:
- increment bounce counter
- suppress after threshold, e.g. 3–5 bounces in a time window
Pseudo-logic:
def handle_bounce(event):
email = event["email"]
bounce_type = event.get("bounce_type")
if bounce_type == "hard":
suppress(email, reason="hard bounce")
elif bounce_type == "soft":
count = increment_soft_bounce_count(email)
if count >= 3:
suppress(email, reason="repeated soft bounces")
4) Check suppression before sending
Before sending any email:
- query suppression list
- skip suppressed recipients
- optionally log the skip
if is_suppressed(email):
return {"status": "skipped", "reason": "suppressed"}
5) Best practices
- Idempotency: webhook events may be delivered more than once
- Signature verification: prevent spoofed webhook calls
- Audit trail: keep records of why an address was suppressed
- Unsubscribe support: treat unsubscribes separately from bounces
- Batch cleanup: optionally remove expired soft-bounce suppressions if appropriate
- Global vs campaign suppression: decide whether suppression is account-wide or per-brand/per-list
6) Common API endpoints
You might expose:
POST /webhooks/email— receive bounce/complaint eventsGET /suppressions— list suppressed addressesPOST /suppressions— manually suppress an addressDELETE /suppressions/{email}— remove suppression (admin only)POST /send— send email, checking suppression first
If you want, I can also provide:
- a database schema for suppression lists,
- a Node.js / Python webhook example,
- or a full email sending flow with bounce handling.