How to Automate Transactional Emails with Braze

Hands holding a phone showing an abstract email card with a green tick, beside a coffee cup, a plant and a notebook, illustrating a transactional email arriving.

You have three routes for sending transactional email from your own systems into Braze. These are the dedicated Transactional Email endpoint, an API-triggered campaign, and the messages endpoint. The right one depends on who owns the copy and who owns eligibility. Decide that first, because each route changes what you can schedule, test, suppress and track.

‍

Key Takeaways

  • Pick the route by two questions: who edits the copy after launch, and where eligibility is decided.
  • The Transactional Email endpoint names one user per request and treats the whole user base as eligible, including unsubscribed users.
  • It has no scheduling, re-eligibility, frequency capping or conversion tracking, so your own service is the only eligibility gate.
  • Build the external_send_id from the order and the message type, because Braze stores it as a deduplication key for 24 hours.
  • Status postbacks tell you whether a message arrived, and Braze describes using them to reach the user on another channel if it didn't.
  • Write four decisions down before the first template: route, eligibility owner, key format and waiting window.

‍

What counts as a transactional email in Braze?

Braze describes a transactional email as an automated, non-promotional email message that facilitates an agreed-upon transaction. Its own examples are order confirmations, password resets, billing alerts and shipping alerts.

The name is easy to confuse with something else. Braze states that transactional emails differ from transactional campaigns, which can be used to target your users without additional costs. Use the exact term in briefs, so nobody scopes the wrong feature.

Availability comes first. Transactional Email is only available as part of select Braze packages, and Braze points you to your customer success manager. Settle that before you design anything around it.

‍

Which Braze transactional email route should you choose?

We group the ways to send transactional-style email from your own systems into three routes. They differ on where the content lives, who can be targeted and which campaign controls still apply.

RouteWhere the copy livesWho can be targetedCampaign controls
Transactional Email endpointA Braze dashboard campaignOne user per request, with the whole user base eligible, including unsubscribed usersNo scheduling, re-eligibility, frequency capping or conversion tracking
API-triggered campaignA Braze dashboard campaignUp to 50 named recipients per request, or an audience segment defined in the requestCopy, multivariate testing and re-eligibility rules managed in the dashboard
Messages endpointYour backend, inside the request bodyUsers who already exist in BrazeMessage delays and A/B testing can be added as extensions

‍

Two questions decide the route. One is who edits the copy after launch. The other is where eligibility gets decided. When your service decides eligibility and engineers own the template, we recommend the dedicated endpoint. When marketers need to test copy or limit repeat sends, we recommend an API-triggered campaign. When your backend produces the content itself, the messages endpoint fits.

‍

How do you set up the Transactional Email route?

The setup is short, and each step produces something the next step needs.

  1. Create a campaign and select Transactional Email as the messaging channel.
  2. Compose the email or choose a template, then note the campaign ID that Braze generates.
  3. Generate an API key with the transactional.send permission.
  4. Send requests to the transactional send path for that campaign ID, naming exactly one recipient.
  5. Set the Transactional Event Status Postback URL under Settings, then Email Preferences.

‍

{
  "external_send_id": "YOUR_BUSINESS_KEY",
  "trigger_properties": { "YOUR_PROPERTY": "YOUR_VALUE" },
  "recipient": { "external_user_id": "YOUR_USER_ID" }
}

‍

The field names above come from the endpoint page, and every value is an example for you to replace. The request goes to /transactional/v1/campaigns/{campaign_id}/send, and it must name a single user by external user ID or user alias.

If you pass an external user ID that doesn't exist yet, passing any fields in the attributes object creates the profile. Send several requests for the same user with different data, and Braze updates first name, last name and email synchronously. It templates them into the message. Custom attributes don't have that protection, so take care when you pass different custom values in quick succession.

‍

What does the dedicated route leave out?

Braze removed several campaign controls so that all users are reachable for these critical transactional alerts. Scheduling options are gone, as are re-eligibility controls and frequency capping. The Conversions step is removed too, because transactional emails don't support conversion event tracking.

There's no audience step either. Braze treats the entire user base as eligible, including unsubscribed users. Any recipient logic has to run before you decide whether to make the API request.

That makes your own service the only eligibility gate. We recommend naming the owner of that logic and writing the rule down. The campaign settings that would normally filter the send aren't there.

Two content rules follow. Braze doesn't support the Connected Content or Promotion Code tags in any field of a transactional email. The first needs an outbound API request during sending, and the second needs additional processing. Fetch any external data in your own service and pass it in through trigger properties instead.

Message Archiving is supported on this route, and Braze saves a rendered copy of each transactional email send. Anything you template into the message is in that copy.

Braze scopes this route to non-promotional messages. It says it doesn't add one-click unsubscribe to this campaign type, and you can add it by editing the setting under Sending Info. Whether a message counts as transactional under the law that applies to you is a question for your legal and security reviewers. This post doesn't settle it. Keep promotional copy out of these templates.

‍

How do you make Braze transactional email sends safe to retry?

Braze gives you a deduplication key for this. The optional external_send_id is a string that Braze stores for 24 hours as a deduplication key. Passing the same identifier in another request doesn't result in a new instance, so a retry inside that window won't send a second email. If you intend a new message, use a new identifier.

That behaviour decides how to build the key. We recommend using the business event rather than the order alone, by combining the order number with the message type. A confirmation and a shipping alert for the same order are different messages. A shared key would suppress the second one for 24 hours.

‍

How do you know a transactional email arrived?

Braze sends status postbacks to a URL you set under Settings, then Email Preferences. Each one carries a dispatch_id that Braze generates, plus your external_send_id if you passed one, so you can match events to your own records. Braze describes using them to evaluate message status in real time. You can reach the user on another channel if the message goes undelivered, or fall back to an internal system if Braze is experiencing latency.

StatusWhat Braze says it means
sentThe message was dispatched to a Braze email sending partner
processedThe sending partner received the message and prepared it for the user's inbox provider
abortedBraze couldn't dispatch the message because the user has no emailable address, or Liquid abort logic was called in the message body
deliveredThe user's inbox provider accepted the message
bouncedThe user's inbox provider rejected the message

‍

Aborted and bounced events include a reason field. Braze describes it as the reason Braze or the inbox provider was unable to process the message. That makes it the first place to look when a customer says nothing arrived. We recommend setting your own waiting window for a missing delivered event, based on how time-sensitive each message is. A password reset needs a short window, and a copy of an invoice can wait longer.

Plan for volume as well. The endpoint is a paid-for endpoint in units per hour, for example 50,000 per hour depending on your package. Braze says you can send beyond your allotted volume, but only the allotted volume is covered by the service level. Within it, 99.9% of emails send in less than one minute.

Requests to this endpoint also count toward your overall external API rate limit. If you exceed that limit, Braze returns 429 and throttles requests, and its example is 250,000 requests per hour across all endpoints.

‍

What changes with the other two routes?

An API-triggered campaign keeps copy, multivariate testing and re-eligibility rules in the Braze dashboard while your servers trigger the send. By default, send_to_existing_only is true, so Braze sends the message only to existing users.

If the profile has no email address at trigger time, Braze retries for up to approximately 2 hours while waiting for profile data. Including the email address in the attributes object of the same call avoids that delay. For anything time-critical, we suggest designing around that retry window, because a password reset that waits on a profile write defeats its own purpose.

For a transactional use case, Braze advises setting the delay to zero minutes. The user then receives the campaign every time they do the transaction. It also says to use exactly two curly braces per Liquid tag, because an extra brace is a common cause of API-triggered personalisation failures.

The messages endpoint suits content that your backend produces. Each recipient must already exist in Braze, because API-only sends don't create profiles. Call the user tracking endpoint first, or choose an API-triggered campaign. The key needs the messages.send permission, and the body accepts HTML with Liquid personalisation.

‍

What should you test before go-live?

We suggest testing in this order, so each check builds on the last. Run every step in a test setup that you control, with recipients you own, and never with live customers.

  1. Send the same external_send_id twice and confirm the second request doesn't produce a second email.
  2. Trigger an aborted case, such as a user with no emailable address, and confirm your postback handler records the reason.
  3. Confirm your service stops promotional or ineligible sends before the API call, because the route won't filter them for you.
  4. Time the gap between the API call and the delivered event, then set the waiting window from that evidence.
  5. Check what your service does on a 429 response, and make sure it retries with the same key rather than a new one.

‍

One failure mode to plan for is a key built from the order number alone. The shipping alert then shares an identifier with the confirmation, so it isn't treated as a new message for 24 hours. A key built from the order and the message type avoids that.

‍

What should you write down before the first template?

As a Braze implementation partner, CustomerIK recommends capturing four decisions on one page before the first template is built.

  1. Which route each message type uses, and who owns its copy.
  2. Who owns the eligibility logic that runs before the API call.
  3. The format of the external_send_id key.
  4. The waiting window that turns a missing delivered event into an incident.

‍

Agreed once, those four lines stop each engineer making the choices differently.

‍

How does this connect to the rest of the programme?

For the sending side, see email deliverability setup. Braze says sends through the messages endpoint show opens, clicks and bounces alongside your other campaigns and Canvases. That's where email campaign reporting applies. The same care over naming applies to user event tracking.

Where marketers own the copy, personalisation and dynamic content are what keep an API-triggered template useful after launch.

‍

Frequently Asked Questions
‍

1. What is the difference between a transactional email and a transactional campaign in Braze?

They're different things. A transactional email is its own campaign type, available in select Braze packages. A transactional campaign can be used to target your users without additional costs.

2. Can Braze transactional emails reach unsubscribed users?

Yes. Braze treats the entire user base as eligible, including unsubscribed users. Keep the content non-promotional. Whether a message counts as transactional under the law that applies to you is a question for your legal and security reviewers.

3. How long does Braze remember an external_send_id?

Braze stores it as a deduplication key for 24 hours, so passing the same identifier inside that window doesn't result in a new instance.

4. Which API key permission does each route need?

The Transactional Email endpoint needs transactional.send. The messages endpoint needs messages.send. The trigger endpoint for API-triggered campaigns needs campaigns.trigger.send.

5. Can I use Connected Content in a transactional email?

No. Braze says it doesn't support the Connected Content or Promotion Code tags in any field of a transactional email campaign, because both add processing during sending.

‍

Sources

‍

CustomerIK is a Braze implementation partner working across onboarding, technical integration, marketing operations and customer data management.

If your order confirmations and password resets depend on one engineer remembering how they work, let's talk.

‍

Preferences

Privacy is important to us, so you have the option of disabling certain types of storage that may not be necessary for the basic functioning of the website. Blocking categories may impact your experience on the website.

Accept all cookies
Accept all cookies

These items are required to enable basic website functionality.

Always active

These items are used to deliver advertising that is more relevant to you and your interests.

These items allow the website to remember choices you make (such as your user name, language, or the region you are in) and provide enhanced, more personal features.

These items help the website operator understand how its website performs, how visitors interact with the site, and whether there may be technical issues.

Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.