Store an email template in Bird and reference it by id. Conditionals, loops, and defaults render per recipient when the message is sent, so the personalization logic stays in the template instead of scattered through your code. Author it as HTML with declared variables, or render your React Email components.
import { BirdClient } from "@messagebird/sdk";
import { render } from "@react-email/render";
import { WelcomeEmail } from "./emails/welcome";
const bird = new BirdClient({ apiKey: process.env.BIRD_API_KEY! });
const { data, error } = await bird.email.send({
from: "Bird <hello@bird.com>",
to: ["ada@example.com"],
subject: "Your invite is ready",
html: await render(<WelcomeEmail name="Ada" />),
}).safe();
if (error) throw error;
console.log(data.id);
// → "em_2bX91Yk8h..."You can sign in any time at bird.com/login.
Your test API key is on your dashboard, ready to send.
Store a template. Personalize at send.
Send only the values that change per recipient.
Templates are part of the Bird Email API. Store the layout and its logic once; on each send you reference the template and pass a flat set of per-recipient values. Bird renders the final message on its side, so the same template drives one email or a million.
import { BirdClient } from "@messagebird/sdk";
const bird = new BirdClient({ apiKey: process.env.BIRD_API_KEY! });
// Store a template once. Conditionals and loops render per recipient at send.
const tpl = await bird.templates.create({
name: "order-confirmation",
subject: "Order {{ order_number }} confirmed",
html: "<h1>Thanks, {{ first_name or 'there' }}.</h1>" +
"{{ if is_member }}<p>You earned {{ points }} points.</p>{{ end }}",
variables: [
{ key: "first_name", type: "string", fallback: "there" },
{ key: "order_number", type: "string" },
{ key: "is_member", type: "boolean" },
{ key: "points", type: "number" },
],
});
// Send it. Bird fills in the blanks for each recipient.
await bird.email.send({
from: "orders@acme.com",
to: ["ada@example.com"],
template: tpl.id,
variables: { first_name: "Ada", order_number: "A-1043", is_member: true, points: 120 },
});More than find-and-replace.
Real templating logic, resolved on Bird's side, per recipient, at send.
- 01
Conditionals.
Show a block only when a value applies, like a members-only note or a free-shipping banner, without sending two different templates.
- 02
Loops.
Repeat a row for each item in an array, so one order-confirmation template lists every line item a customer actually bought.
- 03
Defaults.
Fall back to a safe value when a field is missing, so a blank first name never ships as an empty greeting.
- 04
Nested data.
Reach into structured objects with dotted paths, not just flat top-level keys, so your existing data shapes map straight in.
- 05
Rich variable types.
Declared variables can be strings, numbers, booleans, arrays, and objects, which is what makes the loops and conditionals above possible.
Author it the way you already work.
Send plain HTML with a list of declared variables through the API, and you have a working template, no new editor to learn. Prefer components? Render your React Email templates to HTML and store the result. The one thing to know: leave Bird's tokens as literal text in the JSX so they survive the render and get filled at send, instead of baking in a value when React renders.
import { render } from "@react-email/render";
import { Receipt } from "./emails/receipt";
// Author in React. Leave Bird's tokens as literal text so they
// survive the render and get personalized per recipient at send.
const html = await render(<Receipt firstName="{{ first_name }}" />);
await bird.templates.create({
name: "receipt",
subject: "Your receipt",
html,
variables: [{ key: "first_name", type: "string", fallback: "there" }],
});Versioned, like the rest of your code.
Editing happens on a draft and never touches what's live. Publishing freezes an immutable, numbered version and pushes it; if a change goes wrong, roll back to an earlier version and re-publish. Concurrent edits are caught rather than silently overwritten, so two people working on the same template don't clobber each other. Every version carries a stable identity, which is what lets per-template reporting attribute opens and clicks correctly.
Keep every brand consistent.
A brand kit holds your colors, type, spacing, logo, and voice, and applies them to a template so the output looks and reads like you without restyling each one by hand. Kits live at the workspace level and a workspace can keep several, because a parent brand, a sub-brand, and your plain transactional mail rarely want the same look. Using a kit is optional: a template with none falls back to clean defaults.
Preview exactly what will ship.
Fill a template with sample values and see the rendered message before anyone receives it. The preview runs through the same rendering path as the real send, so what you approve is what goes out, not a close-enough approximation that drifts once tokens and logic resolve for real recipients.
Where templates are headed.
The stored-template model is the foundation for what comes next: describe a template in a prompt and generate a draft to refine, build one visually without writing HTML, and let coding agents compose on-brand templates over MCP, plus a library of starter templates to begin from. These build on the same versioned, brand-aware model, not a separate track, so the API you integrate today is the one they extend.
Go deeper in the docs.
See how templates fit the sending guide, including rendering React Email, and wire up email events and webhooks so opens and clicks flow back per template.
Templates FAQ
Do I have to use a visual builder?+
How is a stored template different from passing HTML on every send?+
What can the personalization do beyond find-and-replace?+
Does React Email work?+
Can I roll back a template I broke?+
Is there AI generation or a drag-and-drop builder?+
How do I actually send a stored template?+
The rest of the Email platform
One API, one set of keys. Explore the other capabilities.
Templates are part of a platform, not a point tool.
Store, version, and personalize templates on the same Email API that handles sending, deliverability, suppression, and analytics. One set of keys.