Skip to main content
Transactional emails send one real-time message, such as a password reset or an order confirmation. They reach unsubscribed contacts because they carry essential account information, and they skip the unsubscribe footer. A suppressed address, such as one that hard-bounced, is still skipped.

The Domain Decides

In Brew, a transactional email is an automation. There is no separate transactional email object to create. What makes an automation transactional is the sending domain. A domain with sendingPurpose: 'transactional' removes the unsubscribe requirement and delivers to unsubscribed contacts. The same automation on a marketing-purpose domain is a marketing send that respects unsubscribes. You pick the class by picking the domain. Automations on marketing-purpose domains still cover the marketing side of event-driven email: welcome flows, onboarding, abandoned cart, win-back. Those respect unsubscribes, which is what you want for marketing, and not what you want for a password reset. That is why a reset flow’s send step belongs on a transactional-purpose domain.

Set It Up

1

Add a transactional domain

Add a sending domain with the Transactional purpose in the Brew app, or from code with POST /v1/domains and sendingPurpose: "transactional". The MCP create_domain tool adds marketing domains only. Verify Your Sending Domain covers the DNS records and both purposes. Run marketing and transactional mail on separate subdomains.
2

Create the trigger

Build a custom trigger, or use one an integration provisions. Declare the payload fields the email needs. Build an Automation covers triggers and payload contracts.
3

Build and publish the automation

Wire the trigger to an automation. Point its Send Email step at the transactional domain, then publish.
4

Fire it from your product

Send the event from your backend, as shown below.

Fire It from Your Product

Fire the trigger with a JSON payload (nested objects and arrays supported). Reference payload fields in the email as {{ trigger.* }} variables:
The email design references {{ trigger.resetUrl }}. The payload’s email field is the contact the automation runs for. Merge Tags covers the variable syntax.

What to Know Before You Ship One

  • Suppressed addresses are skipped. A fire to a hard-bounced address answers 202 with counts.skipped: 1 and starts no run. The events feed records why.
  • A fire for a new address creates a contact. It’s subscribed, like a contact added with only an email. Send that person marketing only if they opted in.
  • Keep one-time codes off the contact. Nest them in the payload, such as { "verification": { "code": "482913" } }, and write {{ trigger.verification.code }}. A nested value renders but isn’t saved on the contact.
  • The subject line is stored. The events feed keeps each email’s subject, so put a code in the body, not the subject.
  • Tracking still applies. Click and open tracking follow the domain’s settings, so links go through the tracking domain and an open pixel is added.
  • Retries don’t send twice. Send an Idempotency-Key header with a stable value per event, such as the reset request’s ID. A retry with the same key answers with the original runs instead of sending again.
  • Redact secrets in logs. In the trigger’s payload schema, set pii: "high" on fields such as codes and reset links. Brew then hides their values in execution logs and the inbound log.
  • Encode values inside links. A token with + or & breaks in a raw link. Write {{ trigger.reset.token | url_encode }}, or pass the whole link already encoded. See Merge Tags.
  • MCP won’t fire to a contact who opted out of marketing. The email itself has no unsubscribe link, but an agent still can’t send it to that contact. fire_trigger_event answers RECIPIENT_UNSUBSCRIBED even for a transactional automation. Fire receipts and resets from your backend over the API.

Change a Domain’s Purpose

PATCH /v1/domains/{domainId} with sendingPurpose changes a domain’s purpose. Published automations on that domain follow the new purpose on their next send. After a switch to transactional, they send with no unsubscribe link and reach unsubscribed contacts. Emails can’t send from a transactional domain. If one still points at the domain, it’s blocked at send time.

Next Steps

Need Help?

Our team is ready to support you at every step of your journey with Brew. Choose the option that works best for you:

Search Documentation

Type in the “Ask any question” search bar at the top left to instantly find relevant documentation pages.

ChatGPT/Claude Integration

Click “Open in ChatGPT” at the top right of any page to explore it further with ChatGPT or Claude.