Home/Transactional Email/Services/Transactional messages

Transactional messages

A transactional message is an automated communication sent in direct response to one user's action, carrying the information that action requires. What defines the class is the trigger, not the content, and the boundary is written into the send endpoint itself. It goes to a single recipient, is expected because the recipient caused it, and its failures are silent.

VerifiedBy George Hartley, Co-founder·Updated

What makes a message transactional

The trigger, not the content. A transactional message goes out because one person did one thing, and it carries what that action requires. Change the trigger from an event to a schedule and you have a campaign, whatever the copy says.

That is the whole boundary, and every rule further down this page follows from it. The longer version of the split, including where the two overlap in practice, is on transactional versus marketing email. One recipient, because one person acted. Expected, because they caused it. Urgent or not depending on what the action was.

I think this is the most underrated category in email. Stripe's 472px receipt. Webflow turning verification into onboarding. The emails with the highest open rates are the ones most companies phone in. A receipt is a brand moment that a person actually opens, and it usually gets treated as a template nobody owns.

What makes this class hard is not writing it. It is that its failure mode is silence. Nobody files a ticket about a receipt that never arrived, they just quietly stop trusting you, and the sending system usually reports the send as fine. I have watched a welcome email never arrive while the flow was live, the contact was on the list and every status we had said it had gone. Nothing errored anywhere.

So the rule I would hold any transactional system to is that it tells the user it failed and why, with something to do about it, because silent failure is the bad outcome and not the failure itself.

That is the reason the rest of this page is mostly about delivery and status rather than about copy. And it is the reason the useful part, if something other than a person is going to send these, is that the boundary and the outcome are both written down in a place a machine can read. More on that below.

Common types

Confirmations acknowledge that something completed. Order receipts, payment confirmations, booking acknowledgments and event RSVPs all fall here, and their job is to be findable months later.

Notifications report a change in state the recipient is waiting on. Shipping updates, delivery alerts, status changes and security warnings.

Account messages handle access and administration. Password resets, email verification, two-factor codes and subscription renewal notices.

The three differ in urgency rather than in kind. A verification code is useless after a few minutes, while a receipt retains value indefinitely, and that difference drives how each should be sent.

Our own list is not a marketing taxonomy. The send endpoint enumerates it. POST /v1/my/messages documents itself as sending a transactional email or SMS to a single recipient immediately, with no campaign, no audience and no approval required, and names the use it is for: receipts, password resets, OTPs, order confirmations and system notifications.

The class is in the tool surface

Most pages about this topic hand you a taxonomy and trust you to apply it. That works when a person is doing the applying. It stops working the moment the sender is an assistant deciding, at request time, which call to make.

So the thing worth knowing about our version is where the boundary lives. It is not in a policy page that an agent has to read and remember. It is in the shape of the tools.

nitro_send_message sends an immediate single-recipient transactional email or SMS. nitro_compose_campaign creates or edits a broadcast draft and never delivers it, with delivery a separate call through nitro_control_delivery. The transactional path has no audience argument and no approval step. The campaign path cannot send by itself.

An assistant does not need a mapping table from your use case to a product feature, because the use cases are in the summary line of the call. Describe a password reset and the correct tool is the one whose description contains password resets. Describe a Tuesday announcement to a list and that tool is not available to you, because it does not deliver.

That is a small design decision with a large consequence. A rule that lives in prose is a rule an agent can talk itself out of. A rule that lives in which function exists is a rule it cannot reach around. We built it that way on purpose, because we assumed from the start that the caller would be a model rather than a person who had read the guide, and because a tool's name and summary are the primary signal an agent uses to decide which tool to call.

The separation is also the reason a flow is the wrong shape for this. Flows are far too heavyweight for sending a simple transactional message, so the transactional path is a dedicated send that writes one thin record rather than a campaign with an audience and a schedule around it.

The rule that comes with it, and it is not optional: never build bulk on the transactional path. A mail merge or an outreach blast routed through the endpoint designed for one triggered message is a deliverability and compliance trap, and it is a trap in the direction that damages the mail you most need delivered.

It is also why this page can be short about classification and long about delivery. The classification question is answered by the API surface itself.

Key rules

No marketing content. A transactional message carries only information related to the action that triggered it, and adding promotional material changes what the message legally is. Kam, our co-founder and CTO, built that rule into the design layer itself. The transactional_plain design mode requires transaction details and a support path, and it rejects marketing copy outright.

That boundary is enforced by primary purpose rather than by intent. Under the CAN-SPAM Act, transactional and relationship messages are exempt from the opt-out and physical-address requirements, but a message whose primary purpose becomes commercial loses that exemption and needs both. The boundary cuts the other way too. We support marking legally required authentication and recovery steps in a flow as transactional, so a password reset still reaches a contact who unsubscribed from marketing, personalization like the confirm URL intact.

Accurate headers and a non-deceptive subject line are required regardless of category. The exemption is partial, never total.

The SMS distinction

Consent works differently by channel, and this is the rule most often got wrong.

Transactional email generally does not require prior opt-in, because the recipient triggered it by taking an action with the sender.

SMS does. Under the Telephone Consumer Protection Act, codified at 47 USC 227, and the FCC's implementing rules at 47 CFR 64.1200, sending automated text messages requires prior express consent from the recipient, and the transactional nature of the message does not remove that requirement.

Treating an email address and a phone number as interchangeable contact fields is therefore a compliance error rather than a design shortcut. A system sending both needs separate consent state per channel. That applies with more force when the sender is an agent, because channel is a field on the same call and picking the other value is one token of difference.

Delivery requirements

Latency is a functional requirement for part of this class. A one-time passcode arriving in ninety seconds has failed even though it was delivered, so time to inbox belongs in the specification.

Separate sent from delivered, because the protocol does. RFC 5321 says the receiver accepts responsibility for delivering or relaying a message when it answers DATA with a 250 OK, which means an accepted send is a transfer of responsibility and not an arrival. A system that reports only the first of those two states is reporting the easier one.

Send from a sending identity separate from marketing. A sending identity is not a label on an account, it is a domain, and reputation attaches to the domain rather than to you. Marketing generates complaints at rates transactional mail does not, so a shared sending domain means a campaign can degrade the reputation carrying password resets. Our own documentation gives the fix in one line: verify a second subdomain and route product mail through it, so a large promotional send cannot drag down receipts and resets.

Decide the failure behavior deliberately. A message that fails and silently retries a day later is frequently worse than one that fails visibly, because a password reset arriving 26 hours later is a support ticket rather than a delivery.

Make the outcome readable rather than reported. An agent that sent a reset needs to answer what happened to it, which means per-message status it can query and a suppression list it can inspect. GET /v1/my/suppressions covers hard bounces, soft-bounce suppressions, complaints and manual suppressions, with the bounded provider diagnostic text kept from the source feedback event. Without that read, an autonomous sender is confident and uninformed, which is the worst combination available.

Include a support path. For anything concerning money or account access, somewhere to reply is the difference between a question and a dispute. The rest of the operating rules for this class are on transactional email best practices.

And never let commercial state gate this mail. An unpaid invoice should stop a campaign. It should not stop a password reset, because the person locked out of the account did nothing wrong and has no idea a billing problem exists.

One recipient, no campaign machinery

A transactional message is a single-recipient send triggered by something a person just did, and the interface should reflect that. Ours queues one message through a single POST to /v1/my/messages, with delivery handled by the normal background sending path, and the agent-facing equivalent sends to one recipient immediately with no campaign, no audience and no approval step.

Campaign
Audience
a list, segmented
Approval gate
a human signs off
Scheduled
Tuesday, 9:00
Send
Transactional
Event fires
password.reset.requested
Send
Immediate · one recipient · no gate
No gate makes idempotency the safety mechanism: a duplicate reset send issues a second live credential.
Campaigns queue behind machinery. Transactional mail has one recipient, an event for a trigger, and nothing in the way.

That last part is the design decision worth noticing. Our position on agent autonomy is four words: humans approve, agents operate. Campaign sending has an approval gate because a mistake reaches thousands of people and the send is the irreversible step. A transactional send does not have one, because the trigger already happened and the recipient is waiting, and putting a human in that loop would break the thing.

Content ownership sits with the application rather than the platform, which is the right default for this class of mail. Customers use the transactional path for signup and password reset messages where their own system decides what the message says, and the platform's job is delivery and status rather than composition.

The distinction from campaigns is not cosmetic. Retry semantics differ, status expectations differ, and failure means something different: a failed campaign send is a marketing problem, while a failed password reset is a person locked out of an account.

Getting a transactional message right by hand, the rules above, the idempotency, the one-recipient discipline, is exactly the kind of careful, repetitive work an AI agent should be doing instead of a person. I do not think of that as a future feature. The dashboard era assumed a human operator with a browser open, time to check the rules, and a reason to go looking when nothing appeared to be wrong. For a class of mail whose failures are silent, that assumption was always weak, and now it is just wrong. Describe the receipt, the reset link or the reminder inside an agent like Claude or ChatGPT, and it sends the message correctly every time, without anyone re-checking the rules by hand.

Idempotency matters more here than anywhere else for the same reason. A retried campaign send is embarrassing, but a duplicated password reset issues a second live credential, which is why the same key on a retry has to produce the same result rather than a second send. The header and the two documented outcomes are covered on the API for email page, along with the wider email API. Our documentation makes the Idempotency-Key header mandatory on this endpoint from September 1, 2026.

The problem is old enough to be in the protocol. RFC 5321's advice for avoiding duplicate messages caused by timeouts is that the receiver must minimize the time it takes to answer the end of data indicator. Answer faster is the whole mitigation, because SMTP has no key to reconcile against. A retry key is the part that was missing, and it matters more now that the caller retrying is a model rather than a person deciding whether to press the button again.

Which brings the page back to where it started. When that key became required, integrations that had never sent one started failing, and they failed the way this class of mail always fails: quietly, on somebody else's server, with nobody watching. A daily canary caught it. A changelog entry would not have. If you are choosing how to send transactional messages, assume your integration will fail closed and silently one day, and pick the thing that will tell you.

Go deeper

First send in thirty seconds.

Simple pricing. Unlimited contacts.

Every plan includes full stack emailing: Flows, Newsletter Campaigns and Transactional Email, plus our NitroWheel LLM and all agent integrations (Claude, ChatGPT, Codex, Cursor and others). Pay for what you send, not who you store.

Choose your billing interval

Every paid plan includes 3 agent inboxes and no Nitrosend footer.

Starter

For your first email program.

$16USD / month

$192 billed yearly.

20,000 emails / month

Choose Starter
  • 5 brands · 3 seats
  • 5 custom sending domains
  • 500 email verifications/month
  • $1.50 / 1,000 extra emails

Pro

For a growing audience.

$40USD / month

$480 billed yearly.

60,000 emails / month

Choose Pro
  • 10 brands · 5 seats
  • 10 custom sending domains
  • 1,000 email verifications/month
  • $1.20 / 1,000 extra emails

Growth

For teams and agencies.

$120USD / month

$1,440 billed yearly.

200,000 emails / month

Choose Growth
  • Unlimited brands · 10 seats
  • 25 custom sending domains
  • 2,500 email verifications/month
  • $0.90 / 1,000 extra emails

Scale

For high-volume sending.

$240USD / month

$2,880 billed yearly.

500,000 emails / month

Choose Scale
  • Unlimited brands · 20 seats
  • 100 custom sending domains
  • 5,000 email verifications/month
  • $0.70 / 1,000 extra emails
Enterprise

Hey, big sender.

Sending 500,000+ emails a month? Get a custom plan designed for you, with volume email pricing and capacity that fits your business.

Start free. No card needed.

5,000 emails to start, then 500 emails every month. No expiry on your starter emails.

Start free

Daily allowances depend on your plan and sender standing. Strong list, domain and delivery evidence can raise standing, including on day one. Trusted receives the full plan allowance; available email credits, safety checks and delivery pacing still apply.

Free forever. No credit card required. See full comparison →