Home/Transactional Email/Templates/Email notification template

Email notification template: structure, fields, and the checks an agent-generated notification needs

An email notification template is a reusable message structure that a system fills with event data and sends automatically when a user action or a system event occurs. It is the message type most likely to be generated rather than authored, and today an AI agent or a model often generates it, so the template has to publish its shape and its field contract.

VerifiedBy George Hartley, Co-founder·Updated

What a notification template is for

A notification template exists so that a machine can send a message a person can act on without anyone writing that message each time. The template is authored once and rendered many times, with merge fields resolved per recipient at send time.

This is what separates a notification template from a marketing email. The trigger is an event rather than a schedule or a campaign, the audience is one recipient rather than a segment, and the content is determined by data the recipient already generated. That split is what the two sending streams exist to protect, and it is covered in transactional versus marketing email.

The library holds real account notification emails, which is the closest thing to a control group for this.

The design consequence is that the template must read correctly for every value the merge fields can take. Copy that only makes sense for the common case breaks visibly on the edge cases, and the edge cases are the ones a recipient is most likely to be worried about.

The anatomy of the template

The anatomy is standard and short: six parts, in a fixed order.

The six parts of a notification, in order
PartWhat it carries
Subject lineThe account, order or service the message concerns
GreetingThe recipient, by name
Core messageThe event, in one sentence
Details blockThe item or action, the date and time, and a reference identifier
Call to actionThe single next step
Sign-offWho sent it

That is also the whole section budget. Six parts, in that order, and a notification that needs a seventh is usually two notifications.

The subject line states the event, not the category. A subject naming what happened lets a recipient triage the message from the list view without opening it, which is the only job a notification subject line has.

The core message is one sentence and comes before any detail. A recipient scanning on a phone reads the first line and decides whether the rest matters, so the event belongs there rather than after a preamble.

The details block carries the identifiers that make the message actionable later. A reference number, an order identifier or a timestamp is what a recipient quotes when they contact support, and a notification without one forces them to go looking.

One call to action, not several. A notification concerns one event, so it has one next step.

The shape is literal here. A Nitrosend template is stored as structured JSON and rendered to MJML for email client compatibility, so no HTML has to be written by hand. What you author is an ordered list of typed sections. Nitrosend's documented examples use four types: a header, a text block holding the copy, a button carrying its text and href, and a footer.

For a notification that is the entire vocabulary, and the constraint is a feature. One text block, one button, one footer. The moment a notification grows a second button it has stopped being a notification, because it no longer describes one event with one next step.

A saved shape with the Brand Kit attached is also what keeps agent output on brand, rather than converging on a generic layout.

A notification is also read by machines more often than most email. Google's email markup documentation states that markup "relies on structured data in emails" and that Gmail supports both JSON-LD and Microdata, added "anywhere inside the <body> element of the email HTML". If the notification is about an order, a reservation or a parcel, the same fields the details block shows should be in a structured block generated from the same values.

One field never belongs in the template at all. The physical address that has to appear in a marketing footer by law lives on the Brand Kit, and Nitrosend applies it when the email is composed. A model asked to write a notification has no reason to ask for a postal address, so putting it in the template is asking the model to remember something it was never told.

What changes when an AI agent generates the notification

Nobody sits down to write "your report is ready". Something finishes, and a message has to exist. So the useful thing to publish is not a gallery of notification designs, it is the shape the generated message has to satisfy.

An agent changes two things about that shape. It fills the event fields at send time from whatever data the trigger carried, so a field it cannot resolve becomes a gap in a message a real recipient reads. And it can edit the live template itself, so a change asked for in a chat lands on every notification the template renders afterwards.

Over MCP, the template side of the Nitrosend email API is nitro_manage_template, which creates, edits or clones a reusable email template. Exact edits pass template_id, section_updates and if_version, so an agent changes the sections it was asked to change on a known version of the template rather than rewriting the whole thing.

Template work is a large share of what agents do. In Nitrosend's own tool usage, agents work in the order read, template, compose, test, deliver, and template management is the second most-called tool, at 1,710 calls. One recorded agent session called the template tool 11 times and the test send 3 times, so a notification template is usually revised several times before it is used.

Given a shape and a set of fields, a model can produce the message. Given a picture of a nice notification email, it produces a guess.

Personalization fields and their defaults

Every merge field needs a defined fallback, because the field will eventually be empty. A greeting that renders as an empty name, or a details block missing its reference, is the failure state a recipient actually sees.

The syntax provides this directly. A value that may be absent takes a default, as in {{ event.plan | default: "standard" }}, so the rendered output degrades to a sentence rather than a blank.

Notification anatomy · every variable carries a default
Subject: Order update · {{order_id}}
Hi {{first_name}},
Your order shipped today and should arrive within 3 business days.
Ref: {{order_id}}
Track your order
The Acme team
The forgotten fallback
a missing order_id ships the subject line "Order update · " to a customer
default: "Order update"
Body fallbacks
first_name defaults to "there"
tracking_url defaults to "your account page"
one call to action, a details block, a sign-off: nothing else
Every variable field needs a default. The subject line is the one everyone forgets.

The harder version of this problem is that a model does not only leave fields empty, it fills them with the wrong shape. A button prop named text will accept a paragraph, and the renderer prints what it is given, so a sign-off pasted into a call to action becomes a button containing an essay. A typed field is only a constraint if the save step rejects the wrong shape. Validate on save rather than instructing the model more carefully.

Two field namespaces exist and they fail differently. {{ contact.first_name }} reads the contact record, which existed before the event. {{ event.order.id }} reads the envelope that arrived with the trigger, which did not. A missing contact field degrades to a missing name. A missing event field degrades to an empty block where the reason for the email was.

Fallbacks belong on the subject line as much as the body, and that is the place people forget. A subject line is the one part of a notification that every recipient sees whether or not they open it, so a subject that renders as "Order update for " is the failure the whole audience witnesses.

So verify the template against a real triggering event, not just a real contact. Nitrosend's docs put it as one step: create and test the event contract before activating the flow. It is the step that gets skipped because rendering against a complete record proves nothing about the record that is not.

Some events make the requirement explicit rather than leaving it to a default.

Required and optional fields on two built-in events
FieldEventRequired
data.reset_urlpassword_resetYes
data.tracking_urlorder_shippedYes
data.carrierorder_shippedNo
data.tracking_numberorder_shippedNo

The rule those encode is the one to copy into any notification template you write: name the fields the message cannot be sent without, and give a default to every field that is left.

And keep the path stable once something depends on it. The documented rule is to keep each event contract stable once a flow uses it, with the same meaning and the same value type. Renaming a field in the producer does not raise an error anywhere. It renders nothing, in production, to a real recipient.

The default copy question is worth settling early too. Nitrosend ships default copy in every flow that reads well enough to send unedited, deliberately written as considered starting copy rather than filler text, on the assumption that a sender without time still ends up with something coherent going out. That is a reasonable standard for any template library: the unedited state should be publishable, because a proportion of it will be published.

Dynamic notifications require a reliable data source, and the end goal has always been basic: use the data you already hold to populate the content of the email automatically.

Worked example: an agent builds a shipping notification

The prompt, in the sender's words: "Make a shipping notification template with the tracking link and show me a test before it is used."

Before: an agent left to itself writes the email straight into a send, with no saved template, no defaults on the tracking fields and no test, so the first rendered copy anyone sees is the one a customer received.

  1. nitro_get_status reads the account context, sender identity and readiness.
  2. nitro_manage_template creates a reusable template with order number, carrier and tracking link fields, each with a default.
  3. nitro_review_delivery reviews the saved template with validation, spam analysis, preflight and previews. It never sends.
  4. For a real inbox check, nitro_send_test_message sends the template one time to the test recipients defined in nitro_configure_account. It never sends to an audience.
  5. A person opens the test and checks the subject line, the tracking link and the empty-field defaults.
  6. The app sends each notification through the transactional email API with an idempotency_key per event.
  7. nitro_get_insights reports email analytics with trends, benchmarks and recommendations once notifications are going out.

After: the same prompt produces a saved template, a review, a test a person has checked, and sends that each carry their own key.

The send itself is one call per event to the transactional email API, carrying an idempotency_key. Reuse the key only for an exact retry, because a job that retries on a timeout should not send the alert twice.

The retry case deserves the same care it gets on a receipt, and for a reason that sits in the protocol rather than in any one product. RFC 9110 defines an idempotent method as one whose repeated identical requests have the same intended effect as one, and names PUT, DELETE and the safe methods. POST is not on that list. A job that fires a notification and times out has no way to know whether the alert went, so the key is the only thing standing between a retry and a duplicate.

Delivery events such as delivered, bounced and complained come back to the app through email webhooks. The trigger for the notification itself is always the app's own event.

Where it goes wrong when an agent sends notifications

Most failures come from an agent filling or changing the template with no check between it and the recipient.

  • Fields that do not resolve. A missing event value ships as a raw {{ variable }} or an empty default, often in the subject line where every recipient sees it.
  • Double sends on retry. A job that retries after a timeout, or an event the producer replays, sends the notification twice unless each message carries an idempotency key.
  • Event loops. A producer that fires the same event over and over sends a burst of notifications and runs into plan limits. A new Free account starts at 100 and the allowance rises with sender standing, up to 5,000 recipients per rolling 24 hours. The limits for each plan are on the pricing page.
  • Promotional content in a notification. An agent asked to mention a sale turns a transactional message into a commercial one, which changes the legal obligations of every message the template renders.
  • Unreviewed edits to the live template. An exact edit through nitro_manage_template changes every notification sent from that template afterwards, so an edit needs the same review and test as a new template.

Common variations

An account alert covers a password change, a new sign-in or a permission change. It leads with the security action already taken, because a recipient reading it is deciding whether the action was theirs, and that decision cannot wait until the second paragraph.

A status update covers shipping progress, task completion or a milestone, which is the same family as an order confirmation and shares its field contract. It leads with the tracking number or the identifier, since a recipient opening it usually already knows the general event and wants the specific reference.

An operational alert points inward rather than at a customer, covering a finished job, a failed run or a threshold crossed. It leads with the outcome and the identifier, because the reader is deciding whether to act right now, and it is the variation most likely to be written by the system that triggered it.

A confirmation covers a completed transaction or an accepted request, and an invoice is the same message with money attached. It restates what was agreed in terms the recipient can check against their own expectation, which is why it carries amounts, dates and quantities rather than a summary.

Deliverability constraints on notification templates

Send through the email API rather than a dashboard, and authenticate the domain the same way as any other mail. The sending domain needs SPF, DKIM and a DMARC policy regardless of how the message was triggered, and a notification sent from an unauthenticated domain is filtered like anything else.

Notification mail is not exempt from email law. The CAN-SPAM Act exempts transactional or relationship messages from the opt-out mechanism and the physical address requirement, but the header accuracy and non-deceptive subject line requirements still apply, and the exemption is lost where the primary purpose of the message becomes commercial.

That constraint lands directly on the template. Adding a promotional block to a notification template is the mechanism by which a transactional message becomes a commercial one, and it changes the legal obligations of every message the template renders.

None of the above is a reason for a person to be in a template editor. The Brand Kit holds the company name and description, the brand, background and text colors, the heading and body fonts, the light and dark logo, the physical address and a brand voice that tells your agent how to write for you. You can set it from your own site by asking your assistant to configure it from a URL, and it is applied automatically when that assistant composes an email. So a notification drafted inside Claude, ChatGPT or Cursor already looks and sounds like you, with no layout to build.

What is left for a person is the part that was always the real work: which fields the message cannot go out without, which path the producer promises to keep stable, and what the email says when the value is not there. That is a specification, and it is worth writing down.

Go deeper

Make emails like these for your brand

Paste this into Claude, ChatGPT, Cursor or any AI assistant. It will connect Nitrosend and build the emails for you.

Using Nitrosend, design and build notification emails for my brand, as a flow or campaign, based on the email notification template on https://nitrosend.com/transactional-email/templates/email-notification-template

My brand's website is [your website]. Read it for my logo, colours, fonts, products and tone of voice.

If Nitrosend is not connected yet, read https://nitrosend.com/SKILL.md and follow it to connect the Nitrosend MCP server (https://api.nitrosend.com/mcp), then ask me to sign in or create a free account at app.nitrosend.com. On Claude.ai use claude.ai/directory/nitrosend; in ChatGPT, install the Nitrosend app. Then write and design every email in Nitrosend and send me a test of each one.

Or open Nitrosend and start freeWhich assistants work?

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 →