University
Sign in

Lesson 3 8 min read

Transactional email

Send password resets, login codes and receipts through the Broadcast API, with templates, safe retries and the right unsubscribe rules.

Transactional email is the mail your app sends to one person because of something they did: a password reset, a login code, a receipt. In this lesson you send one through the API, keep the content in a template, make retries safe, and learn how it differs from marketing email.

How it differs from marketing

Broadcasts and sequences respect unsubscribe status. Transactional email does not. A password reset has to arrive whether or not the person wants your newsletter. Broadcast delivers transactional email even to someone who unsubscribed.

That power comes with a duty. Send only real service messages this way. Using the transactional route for promotions is how sending reputations get damaged.

A few addresses are still blocked. Broadcast does not send to a redacted subscriber or to an address on the global suppression list. By default, a hard bounce on the channel’s own suppression list blocks marketing only. To block transactional mail too, turn on Hard bounces also block transactional email in the channel settings.

A transactional email carries no unsubscribe link and no List-Unsubscribe header, unless you send it with include_unsubscribe_link: true.

Broadcasts and sequences

  • Respect unsubscribe status
  • Carry an unsubscribe link
  • Sent to a list

Transactional email

  • Reaches people who unsubscribed
  • No unsubscribe link by default
  • Sent to one person, through the API
Transactional email has more reach, so keep it for real service messages.

Step 1: Get a token

Every channel starts with an access token that has transactional permissions. Find it under Access Tokens. Or create one with only Transactional Emails read and write, so a leak cannot touch your campaigns.

Before you write code, open Transactional in the sidebar. The Try it now card sends a test to your own address and shows a ready-to-copy cURL command.

The Transactional page with a Try it now card and an API Reference card holding a cURL command
The Try it now card, above a cURL command you can copy.

Step 2: Send one

curl -X POST https://broadcast.example.com/api/v1/transactionals.json \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "to": "ada@example.com",
    "subject": "Your sign-in code",
    "body": "Your code is 123456. It expires in 10 minutes.",
    "reply_to": "support@example.com"
  }'

to is required. subject and body are required unless you use a template. The body can be plain text or HTML, and Broadcast wraps it in the HTML document for you.

The response includes an id and a status_url. GET /api/v1/transactionals/:id.json returns the current state. If the recipient’s address matches a subscriber, the email is linked to that subscriber’s record.

Step 3: Move the content into a template

Email copy in application code is hard to change. Put it in a Broadcast template instead, and send it by id:

{ "to": "ada@example.com", "template_id": 123 }

The template’s subject, body and preheader are the defaults, and any subject or body you send overrides them. The template must belong to the token’s channel. Now a marketer can fix a typo in the receipt without a deploy.

To send from a different From address, pass sender_identity_id. The email marketing course explains sender identities.

Step 4: Make retries safe

Networks fail. If your client times out and retries, the person may get two receipts. Prevent that with an Idempotency-Key header, unique per logical send:

Idempotency-Key: order-12345-receipt

The rules:

  1. The first request with a key is processed and its response is stored.
  2. A retry with the same key and the same body does not send again. Broadcast replays the stored response with Idempotency-Replayed: true.
  3. The same key with a different body fails with 422.
  4. A retry while the first is still processing gets 409. Wait and retry.

Keys are scoped to the token and expire after 24 hours.

Same key, same body

  • Nothing is sent again
  • Stored response comes back
  • Idempotency-Replayed: true

Same key, different body

  • Fails with 422

First request still processing

  • Gets 409
  • Wait and retry
What happens when a request arrives with a key Broadcast has already seen.

Statuses, and when mail waits

A transactional email moves through Pending, Queued and Sent, or ends as Failed. The Transactional page lists every send, with filters by recipient and status, and lets you resend one.

  1. Pending
  2. Queued
  3. Sent
An email that cannot be sent ends as Failed.
A transactional email panel with its status, recipient, details and a timeline, beside an email preview and a Resend Email button
Click a send to see its timeline, a preview and the Resend Email button.

Transactional email has the highest priority in Broadcast, and one worker thread is kept for it alone. But it still respects the email server’s hourly limit. If the server is full, the email stays Queued and Broadcast retries every minute. After 30 minutes, every page of the channel shows a notice. After 24 hours it is marked Failed: “Email server at hourly limit: no room for 24 hours, giving up”.

The fix is in your setup, not your code. Send transactional email through its own email server, one that does not send broadcasts. Then a large newsletter can never delay a login code. See How sending works.

Double opt-in from your own email

If you want your own confirmation email design, send a transactional with double_opt_in: true and put {{ confirmation_url }} in the body. Broadcast creates the confirmation and fills in the link. The Transactional Email API lists the other Liquid variables, such as {{ first_name }}.

What you learned

  • Transactional email bypasses unsubscribe status. Use it only for real service messages.
  • POST /api/v1/transactionals.json with to, and subject and body or a template_id.
  • An Idempotency-Key makes retries safe for 24 hours.
  • Give transactional email its own email server, so broadcasts never delay it.

Check what you learned

Answer all 3 questions correctly to complete this lesson.

1. Does a transactional email reach someone who unsubscribed from your marketing?
2. Your client times out and retries a receipt. How do you stop a second copy going out?
3. A transactional email waits because the server is at its hourly limit. When does Broadcast give up?