Send one message to a list of people
Keep contacts in an audience, send a broadcast to all of them, and handle the unsubscribe that follows.
A transactional message goes to an address you already have in hand. Marketing mail works the other way round: you keep a list of people and send one message to all of them. That list is an audience, the people on it are contacts, and the message is a broadcast.
Everything here belongs to one product. For the transactional side — one message to one address, triggered by something that happened — see How system email works.
Put people in an audience
An audience is a named bucket: a name of 1 to 200 characters, and nothing else. You create them, rename them, list them and delete them.
MCP. mail_audience_create, mail_audience_list, mail_audience_update, mail_audience_delete.
A contact is a person you may send marketing mail to:
| Field | What it holds |
|---|---|
email | The address, stored trimmed and lower-cased |
properties | Your own key/value pairs — first_name, plan, anything you like |
unsubscribed | Whether this person has opted out |
audienceId | The audience the contact belongs to |
properties is free-form: keys are yours to choose and values are ordinary JSON. Two of them mean something — first_name and last_name are offered to templates — and the rest are simply carried along.
MCP. mail_contact_create, mail_contact_list, mail_contact_get, mail_contact_update, mail_contact_delete.
Two rules worth knowing before you design your lists:
- Updating a contact replaces the whole
propertiesobject rather than merging into it, so send back the fields you want to keep. The same call sets or clearsunsubscribed. - A contact belongs to exactly one audience. An address may appear in several audiences, but only once in each, so the same person can be on both “product updates” and “beta testers” as two separate contacts, each with its own properties and its own opt-out state. There is no way to move a contact between audiences: create it in the other audience and delete the original.
Deleting an audience deletes the contacts in it.
Contacts are listed one audience at a time, between 1 and 100 at a time (50 by default) with a cursor for the next page, and can be narrowed to only the unsubscribed or only the subscribed.
Send a broadcast
A broadcast is one message to one audience. It is created as a draft and sends nothing until you queue it.
- Create the draft. It needs a name, the audience to send to, and a
fromaddress at one of your verified domains — the same rule as any other send, see Verify a sending domain. It may also carry reply-to addresses and custom headers. - Give it content. Choose one of two forms and do not mix them: inline — a subject, plus HTML or plain text (or both); or a template — the id of a published template with the variables to render it with, see Write a template.
- Queue it. This is the point of no return.
MCP. mail_broadcast_create, mail_broadcast_update, mail_broadcast_queue, mail_broadcast_get, mail_broadcast_list.
While it is a draft, a broadcast can be edited freely and deleted. Once it leaves that state neither is possible: editing or deleting a queued, sent, failed or cancelled broadcast is refused.
What queuing does
The broadcast moves to queued and is then fanned out: the audience is walked and one ordinary email is created per eligible contact. Two kinds of contact are skipped:
- Anyone whose
unsubscribedflag is set is not even considered. - Anyone whose address is on the product’s suppression list is recorded as skipped and no message is created — see Keep your mail deliverable.
Each message that is created goes through the normal send path from there, with its own status and its own events, and each carries a per-recipient unsubscribe header. Because a broadcast is many messages they do not all leave at once: the audience is worked through in pages, and the broadcast becomes sent when the last of them has been handed on.
When the content comes from a template, each contact’s message is rendered with the broadcast’s own variables plus four filled in for you:
| Variable | Value |
|---|---|
FIRST_NAME | The contact’s first_name property, or empty |
LAST_NAME | The contact’s last_name property, or empty |
EMAIL | The contact’s address |
UNSUBSCRIBE_URL | That contact’s unsubscribe link |
UNSUBSCRIBE_URL is what lets you put a visible “unsubscribe” link in the body of the message itself, next to the one the mail client offers.
Cancelling it
A broadcast can be cancelled while it is a draft or while it is queued. Cancelling a draft simply stops it ever going out. Cancelling one that is already being fanned out stops it between pages: messages already created are on their way and are not recalled, but no further contact is reached. Anything already sent, failed or cancelled cannot be cancelled.
If the fan-out itself cannot complete, the broadcast ends as failed and keeps the reason it failed with.
MCP. mail_broadcast_cancel, mail_broadcast_delete.
Read what happened
Each broadcast reports on itself. MCP: mail_broadcast_stats.
| Field | Meaning |
|---|---|
recipients | Contacts a message was created for |
suppressed | Contacts skipped because the address was suppressed |
failed | Contacts whose message could not be created |
delivered | Messages the receiving servers accepted |
bounced | Messages that were rejected |
opened, clicked | Opens and link clicks, when tracking is on for the sending domain |
The first three add up to the contacts the fan-out considered. The rest arrive afterwards, as the outcomes come back, so they keep rising for a while after the broadcast is sent. For an event per message rather than a total, see Receive mail webhooks.
Handle unsubscribes
Every message created by a broadcast carries the two headers that let a mail client offer a one-click unsubscribe of its own: List-Unsubscribe, holding a link unique to that contact, and List-Unsubscribe-Post, which tells the client the link can be triggered directly. The link is signed, so it cannot be forged or edited to point at someone else, and it does not expire.
Opening the link in a browser shows a short confirmation page with a button and changes nothing by itself — mailbox scanners follow links in mail, and a link that unsubscribed people merely for being visited would opt out people who never asked to leave. The opt-out happens only when the button is pressed, or when a mail client triggers the link directly. Using the same link twice does nothing the second time.
When it does happen, two things follow at once:
- The contact is marked
unsubscribed, so no later broadcast to that audience includes them. - Their address is added to the product’s suppression list with the reason
unsubscribe, so no later message of any kind reaches it.
That second step reaches your transactional mail too. An opt-out from a marketing message stops your receipts and password resets to the same address. If a recipient asks to come back, remove the address from the suppression list and clear the contact’s
unsubscribedflag — both sides have to be undone.
MCP. mail_suppression_list, mail_suppression_remove.
Next steps
- See where your audience came from: the people Lessly Tracking identified are the addresses worth putting in an audience.
- Read the attribution reports:
utm_medium=emailis its own channel, so a broadcast’s revenue is attributable. - Send one email: the transactional side, one message to one address.
- Verify a sending domain: the
fromaddress a broadcast needs. - Keep your mail deliverable: the suppression list an unsubscribe writes into.