# Feed Postmark bounces into Spaw's suppression list

Point a Postmark webhook at your Spaw feedback URL and every hard bounce, delivery and spam complaint updates your suppression list and measured accuracy.

Updated: 2026-09-03

A verification verdict is a prediction; what your mail server sees afterwards is the truth. Spaw accepts Postmark's bounce, delivery and spam-complaint webhooks directly, so every hard bounce lands on your suppression list without a line of code, every delivery counts as a confirmed mailbox, and the History tab shows how often the verdicts you paid for were right.

## Set up the webhook

1. Open the API keys page in the Spaw dashboard and generate a feedback key. The page shows the ready-made URL for each supported provider; the Postmark one looks like this:

```text
https://spaw.co/api/v1/email/feedback/postmark/fb_…
```

2. In Postmark, open the server and message stream you send from, go to its Webhooks section, and add a webhook with that URL.
3. Tick the Bounce, Delivery and SpamComplaint events. Other events are accepted and ignored.
4. Send Postmark's test payload from the webhook's settings. Spaw answers `200` with how many outcomes it recorded, and the entry appears on your suppression list a moment later.

Postmark cannot send a bearer token, which is why the feedback key rides in the URL. Treat the URL as a secret: anyone who has it can add outcomes to your account. Rotating the key on the API keys page invalidates every old URL at once, and a rotated URL answers `401 INVALID_FEEDBACK_KEY`.

## What Spaw reads from the payload

Postmark posts one JSON object per event. Spaw reads `RecordType` and the recipient in `Email` or `Recipient`, and nothing else in the payload:

| Postmark event | Recorded as |
| --- | --- |
| `Bounce` with `Type` HardBounce, BadEmailAddress, ManuallyDeactivated, Blocked or DnsError | bounced |
| `Bounce` with any other type, for example a transient or soft bounce | ignored |
| `Delivery` | delivered |
| `SpamComplaint` | complained |

The `Description` or `Details` field is stored as the reason, and `BouncedAt`, `DeliveredAt` or `ReceivedAt` as the time it happened. A payload like this records one bounce:

```json
{
  "RecordType": "Bounce",
  "Type": "HardBounce",
  "Email": "mia@acme.com",
  "Description": "The server was unable to deliver your message (ex. unknown user, mailbox not found).",
  "BouncedAt": "2026-09-03T10:12:44Z"
}
```

## What Spaw does with the events

A bounce or complaint adds the address to your suppression list with source `feedback`. From then on, batch, bulk and monitor runs answer it from the stored verdict at no cost, with reason `suppressed` and a risk score of 100; a single lookup still re-verifies, which is the only way off the list.

A delivery removes an entry Spaw had added automatically, and for the next 90 days the address counts as a confirmed mailbox for your own lookups: the answer carries `smtp_reason: "delivered_recently"` and no mailbox probe runs. Only your account's deliveries are used for your lookups.

Every outcome is matched against the verdict you were given for that address in the previous 90 days. The feedback summary endpoint and the History tab report the delivery rate among addresses answered `deliverable` and the bounce rate among addresses answered `undeliverable`, which are the two numbers that say how right Spaw was for you. Outcomes are kept for 180 days.

## Cost

Feedback is free and is never logged as a lookup. The webhook endpoint is throttled at 120 requests per minute per IP, which is far above what a single Postmark server sends.

Reference: https://spaw.co/integrations/postmark
