# Connect an email provider

> Connect Resend, Postmark or SendGrid to Whisperr, verify the sender, and get bounces and complaints back through a webhook.

Whisperr sends email through your own email provider account. This page shows how to connect the account, set and verify the sender, and get delivery reports back. You need it before Whisperr can send email to your users. For push, see [Connect a push provider](/integrations/push-providers/).

## Pick a provider

Connect the provider you already send with: Resend, Postmark or SendGrid.

Only owners and admins of the app can connect a provider. Whisperr stores the credentials encrypted and never shows a secret again.

## Enter the key

In the dashboard, open **Integrations**, go to **Email**, and click **Connect** next to the provider. Enter the credentials and click **Check key**.

### Resend

| Field                             | Where to get it                                                                                                                                                   |
| --------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| API key                           | Resend → **API Keys**. Use a key with full access (`re_…`). A sending-access key cannot list domains, so Whisperr cannot check it or your sender.                 |
| Webhook signing secret (optional) | Leave it empty. Whisperr adds the webhook and its secret for you. Paste a secret (`whsec_…`) only if you created the webhook to Whisperr’s receiver URL yourself. |

### Postmark

| Field            | Where to get it                                                                                          |
| ---------------- | -------------------------------------------------------------------------------------------------------- |
| Server API token | Postmark → your server → **API Tokens**. Use the token of the Live server that should send for this app. |

Whisperr sends on a Broadcasts message stream named `whisperr-retention` and creates the stream if it is missing. Whisperr refuses a Sandbox server, because it never delivers email. It also refuses a server that cannot get that stream: one that already has 10 streams, or one where `whisperr-retention` exists as a different stream type.

### SendGrid

| Field                                     | Where to get it                                                                                                                                                                                                                      |
| ----------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| API key                                   | SendGrid → **Settings → API Keys**. The key (`SG.…`) must have the Mail Send scope (`mail.send`). Whisperr refuses a key without it.                                                                                                 |
| Event webhook verification key (optional) | Leave it empty. Whisperr adds the signed Event Webhook and its key for you. Paste a key only if you created the webhook to Whisperr’s receiver URL yourself (**Settings → Mail Settings → Event Webhook → Signature Verification**). |

Also give the key these scopes, so Whisperr can sync suppressions, set up the webhook and check your sender: `suppression.read`, `suppression.create`, `user.webhooks.event.settings.read`, `user.webhooks.event.settings.update` and `whitelabel.read`. Whisperr connects a key without them, but cannot do those steps.

## Check the key

Whisperr asks the provider whether it accepts the key. The check sends no email. If the provider refuses the key, the dashboard shows the provider’s reason. Go back, fix the key and check again.

## Set the sender

Enter **From name** and **From address**: the name and address your users see. Click **Save sender**. The provider must have the address’s domain verified.

## Verify the sender

Whisperr sends no email until the sender is verified.

- **Resend:** click **Check the domain**. Whisperr asks Resend whether the domain of the from address is verified there. The match is exact: a subdomain is a separate domain. Add and verify the domain in Resend first.
- **Postmark:** click **Send a test email**. Whisperr sends one email from your sender, through your Postmark server, to your own address. It proves that Postmark sends for the domain.
- **SendGrid:** click **Check the domain**. Whisperr asks SendGrid whether the domain of the from address is an authenticated domain there, with valid DNS. The check sends no email. A subdomain does not inherit the authentication of its parent domain, and Single Sender Verification alone does not pass. Authenticate the domain in SendGrid → **Settings → Sender Authentication** first.

The dashboard shows “Verified. We can send as” and your address when the check passes. A change to the from address or the credentials clears the verification, so verify again after either change.

## Add the delivery reports webhook

Bounces and complaints come back to Whisperr through a webhook. Whisperr adds the webhook in your provider account for you. The dashboard then shows “We added the webhook in” and the provider name.

If Whisperr could not add it, for example because the key cannot manage webhooks, the dashboard shows the reason, the webhook URL and the events. Add the webhook in the provider by hand:

| Provider | Events                                                                                                                                                              |
| -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Resend   | `email.sent`, `email.delivered`, `email.delivery_delayed`, `email.bounced`, `email.complained`, `email.opened`, `email.clicked`, `email.failed`, `email.suppressed` |
| Postmark | `Delivery`, `Bounce`, `SpamComplaint`, `Open`, `Click`, `SubscriptionChange`                                                                                        |
| SendGrid | `processed`, `delivered`, `deferred`, `bounce`, `dropped`, `open`, `click`, `spamreport`, `unsubscribe`, `group_unsubscribe`, `group_resubscribe`                   |

With Resend, if you add the webhook by hand, paste its signing secret in **Webhook signing secret** when you connect.

With SendGrid, Whisperr creates or updates an Event Webhook named “Whisperr” and turns on its signature verification. If you add the webhook by hand, turn on **Signature Verification** for it and paste the verification key in **Event webhook verification key** when you connect.

Until the first report arrives, the Email row shows “Waiting for the first delivery report”.

## Turn on sending

The provider sends Whisperr messages once sending is on for your app. Open **Messages** and use the **Sending** control: **Drafts only** sends nothing, **You approve each** holds each message for your approval, and **Sends on its own** sends without asking. Only owners and admins can change it.

## How does an email link back to your app?

Each email that Whisperr writes and sends through your email provider ends with one button that opens your app or your website. Whisperr picks the link when it writes the draft, so the email you review links to the same place as the email that is sent.

Whisperr uses the first link that exists:

1. The destination that Whisperr picked for this message, if its link is an `https://` link: a universal link, an app link or a web page.
2. Your app’s default destination. An app has at most one default, and it must be an `https://` link without `{item_id}`.
3. The website you entered in setup, if it is an `https://` link or a bare domain such as `example.com`. An `http://` website is skipped.
4. The App Store or Google Play link you entered in setup.

If none of them exists, Whisperr sends the email without a button.

Email uses the same destinations as push. You add them in **Brand & rules → Links in messages**, also when your app has no push (see [What are tap targets?](/integrations/push-providers/#what-are-tap-targets)). Links such as `myapp://paywall` and app routes such as `/paywall` work only in push, because mail apps do not open them reliably. Email skips them and uses the next link in the list.

So that every email Whisperr writes gets a button, add a website or store link in setup, or pick a destination in **Email button default** under **Brand & rules → Links in messages**. Only `https://` destinations can be picked.

### Button text

Whisperr writes the button text together with the subject and body, in your voice. If the text is empty, longer than 30 characters, more than one line, or holds a link, a placeholder or one of your forbidden phrases, the button says **Open the app**.

The plain-text part of the email carries the same link after the body, as the button text followed by the URL.

### Click tracking

Whisperr does not route the button link through a redirect of its own. Your provider’s click tracking records the click, and the click comes back to Whisperr through the delivery reports webhook. Whisperr matches it to the message by the message metadata it sends with the email.

When Whisperr sends the email, it also adds a `wmid` query parameter to the button link, so the page or app that the link opens receives `?wmid=<message id>`. You can ignore it.

- **Postmark:** Whisperr turns on link tracking for the HTML part of the email, so a click on the button is recorded.
- **Resend:** clicks are recorded only when click tracking is on for your sending domain in Resend.

The unsubscribe link never gets `wmid`. Postmark does not track it. Resend has no way to skip one link: with click tracking on for the domain, Resend also rewrites the unsubscribe link in the HTML part. The `List-Unsubscribe` header is never rewritten.

## Which users get email?

Whisperr sends email only to an address that is opted in and not opted out.

- Your backend can opt an address in with the server key (`wrk_…`). Whisperr does not email an address that your server declared `verified: false`.
- An address that your app sets with the publishable key (`wpk_…`) is opted in only under your answer to **Does your signup get permission to email users?** With **No**, it is stored as pending until your backend confirms it.
- With **Require a server key** on, in **Settings → API keys**, only your server can opt an address in. Addresses your app sets get no messages until your server confirms them.

See [Contact consent](/concepts/consent/) for the answers and the limits on addresses from your app.

## How does unsubscribe work?

Each email that Whisperr sends to a known user carries:

- the `List-Unsubscribe` header with a Whisperr unsubscribe link, and `List-Unsubscribe-Post: List-Unsubscribe=One-Click`, so mail apps can show a one-click unsubscribe;
- an unsubscribe line with the same link at the end of the plain-text body.

A user who unsubscribes is opted out of email.

With SendGrid, Whisperr turns off SendGrid’s own subscription tracking for its messages, so each email carries only the Whisperr unsubscribe link.

## What is the suppression list sync?

Whisperr reads your provider’s suppression list every 6 hours. It stores only keyed fingerprints of the addresses, never the addresses. A message to an address on the list is not sent.

Whisperr also tells the provider about its own decisions. It always adds an address with a hard bounce. To also add users who unsubscribe through a Whisperr link, turn on **Tell Resend when someone unsubscribes** (or **Tell Postmark…**, **Tell SendGrid…**) in the provider’s **Suppression list** section.

SendGrid does not let Whisperr add a bounce, so Whisperr adds these addresses to your SendGrid global unsubscribe list. A global unsubscribe stops every send from your SendGrid account to that address.

## How do I replace or remove the credentials?

Open the provider in **Integrations → Email**. Click **Replace credentials** to enter a new key: the old credentials keep working until the new ones pass the check. To remove the account, hold **Hold to disconnect**. Disconnecting SendGrid also deletes the Event Webhook that Whisperr created.

If the provider refuses the key while Whisperr sends, for example after you revoked it, Whisperr stops sending through that account until you replace the credentials.

## Common questions

### Which email providers can Whisperr send through?

Resend, Postmark and SendGrid. Whisperr sends email through your own account with one of them.

### Which email addresses does Whisperr send to?

Only addresses that are opted in and not opted out. Your backend can opt an address in with the server key. Your app can opt an address in only under your answer to Does your signup get permission to email users? See Contact consent.

### Does Whisperr add an unsubscribe link?

Yes. Each email to a known user gets List-Unsubscribe and one-click List-Unsubscribe-Post headers, and an unsubscribe line at the end of the plain-text body.

### Does a Whisperr email link back to my app?

Yes, when Whisperr has an https link for it. Each email that Whisperr writes and sends through your email provider ends with one button. The link is the destination Whisperr picked for the message, then your default destination, then the website or store link from setup. With none of them, the email has no button.

### Does connecting a provider send email right away?

No. The provider is used once sending is on for your app. You set that in the Sending control on the Messages page.

Source: https://docs.whisperr.net/integrations/email-providers/
