# Transactional Email Templates: 10 Examples to Copy

> 10 transactional email templates to copy: verification, password reset, receipts, failed payments, security alerts and more, plus an HTML base template.

Canonical: https://www.cresca.xyz/blog/transactional-email-templates
Author: Lalit Kumar Jangid
Published: 2026-11-05
Last updated: 2026-11-05

Good **transactional email templates** do one job: tell a person what just happened and what to do next, in a format that renders in every inbox. This guide gives you 10 transactional email templates you can copy, from email verification and password resets to receipts, failed payments and security alerts, each with a subject line, preview text, body copy and the variables your app fills in. You'll also get a tested HTML base template and the code to send any of them from your app.

If you're new to the difference between app email and newsletters, start with [transactional vs marketing email](https://www.cresca.xyz/blog/transactional-vs-marketing-email). This post is the copy-and-paste part.

## What makes a good transactional email template

Every template below follows the same five rules. If you write your own, check it against them:

1. **One purpose per email.** A password reset resets a password. It doesn't announce a feature or ask for a review.
2. **The action above the fold.** The button or code should be visible without scrolling on a phone.
3. **A plain-text fallback for every link.** Some people read with images and styles off, and some email clients strip buttons. Always include the raw link or code in text.
4. **Say what happens if they ignore it.** "If you didn't request this, you can ignore this email" prevents panicked support tickets.
5. **No marketing.** Transactional email generally doesn't need marketing consent because it's about a transaction the person started. Add promotions and it stops being purely transactional, and it starts looking like a promotion to spam filters too.

The variables in the templates use triple braces, like `{{{NAME}}}`, which is the placeholder format Cresca's templates use. Swap in your own tool's syntax if it's different.

## 1\. Email verification template

**When:** right after signup, to confirm the address belongs to the person.

**Subject:** `Verify your email for {{{PRODUCT}}}` **Preview text:** `Confirm your address to finish setting up your account.`

```text
Hi {{{NAME}}},

Confirm your email address to finish creating your {{{PRODUCT}}} account.

[Verify email]  →  {{{VERIFY_LINK}}}

Or enter this code: {{{CODE}}}

The link and code expire in {{{EXPIRES_IN}}}.
If you didn't create an account, you can ignore this email.
```

**Variables:** `NAME`, `PRODUCT`, `VERIFY_LINK`, `CODE`, `EXPIRES_IN`

**Tip:** include the code as well as the link. People often sign up on a laptop and open the email on their phone.

## 2\. Password reset template

**When:** the user asks to reset their password.

**Subject:** `Reset your {{{PRODUCT}}} password` **Preview text:** `This link expires in 1 hour.`

```text
Hi {{{NAME}}},

We received a request to reset the password for your {{{PRODUCT}}} account.

[Reset password]  →  {{{RESET_LINK}}}

This link expires in 1 hour and can only be used once.

If you didn't ask for this, you can ignore this email. Your password won't change.
```

**Variables:** `NAME`, `PRODUCT`, `RESET_LINK`

**Tip:** every reset request should produce a new email with a new link. If your server retries a send after a timeout, use an idempotency key based on the reset request's id, so the retry can't send a duplicate.

## 3\. Magic link or login code template

**When:** passwordless sign-in.

**Subject:** `Your {{{PRODUCT}}} sign-in code: {{{CODE}}}` **Preview text:** `Use it within 10 minutes.`

```text
Your sign-in code is:

{{{CODE}}}

Or sign in with one click: {{{LOGIN_LINK}}}

The code expires in 10 minutes. If you didn't try to sign in, someone may
have typed your email by mistake. You can ignore this email.
```

**Variables:** `PRODUCT`, `CODE`, `LOGIN_LINK`

**Tip:** putting the code in the subject line lets people copy it from the notification without opening the email.

## 4\. Order confirmation template

**When:** immediately after a successful order.

**Subject:** `Order {{{ORDER_ID}}} confirmed` **Preview text:** `Thanks for your order, {{{NAME}}}. Here's what happens next.`

```text
Thanks for your order, {{{NAME}}}!

Order {{{ORDER_ID}}} · {{{ORDER_DATE}}}

{{{ITEMS_SUMMARY}}}

Total: {{{TOTAL}}}
Shipping to: {{{SHIPPING_ADDRESS}}}

We'll email you again when it ships.

[View your order]  →  {{{ORDER_LINK}}}

Questions? Just reply to this email.
```

**Variables:** `NAME`, `ORDER_ID`, `ORDER_DATE`, `ITEMS_SUMMARY`, `TOTAL`, `SHIPPING_ADDRESS`, `ORDER_LINK`

**Tip:** let people reply. "Questions? Just reply" with a monitored reply-to address beats a `noreply@` that sends customers hunting for a contact form.

## 5\. Payment receipt template

**When:** every successful charge, including renewals.

**Subject:** `Your {{{PRODUCT}}} receipt for {{{PERIOD}}}` **Preview text:** `{{{AMOUNT}}} paid on {{{DATE}}}.`

```text
Hi {{{NAME}}},

Thanks for your payment. Here's your receipt.

Amount paid:  {{{AMOUNT}}}
Date:         {{{DATE}}}
Plan:         {{{PLAN}}}
Card:         ending in {{{CARD_LAST4}}}
Receipt no.:  {{{RECEIPT_ID}}}

[Download invoice (PDF)]  →  {{{INVOICE_LINK}}}

{{{COMPANY_LEGAL_NAME}}} · {{{COMPANY_ADDRESS}}}
```

**Variables:** `NAME`, `PRODUCT`, `PERIOD`, `AMOUNT`, `DATE`, `PLAN`, `CARD_LAST4`, `RECEIPT_ID`, `INVOICE_LINK`, `COMPANY_LEGAL_NAME`, `COMPANY_ADDRESS`

**Tip:** many countries require your legal name and address on invoices. If your payment provider also sends receipts, turn one of them off, because two receipts for one payment generate support tickets.

## 6\. Failed payment template

**When:** a charge fails, usually on a renewal.

**Subject:** `Action needed: your {{{PRODUCT}}} payment didn't go through` **Preview text:** `Update your card to keep your account active.`

```text
Hi {{{NAME}}},

We couldn't charge your card ending in {{{CARD_LAST4}}} for your {{{PLAN}}} plan
({{{AMOUNT}}}).

[Update payment method]  →  {{{BILLING_LINK}}}

We'll try again on {{{RETRY_DATE}}}. If the payment still fails, your account
will move to {{{FALLBACK}}} on {{{CUTOFF_DATE}}}.

Already updated your card? You can ignore this email.
```

**Variables:** `NAME`, `PRODUCT`, `CARD_LAST4`, `PLAN`, `AMOUNT`, `BILLING_LINK`, `RETRY_DATE`, `FALLBACK`, `CUTOFF_DATE`

**Tip:** say exactly what happens and when. "Your account may be affected" makes people anxious; "your account will move to the Free plan on December 3" makes them act.

## 7\. Shipping update template

**When:** an order ships, and again when it's out for delivery.

**Subject:** `Your order {{{ORDER_ID}}} is on its way` **Preview text:** `Estimated delivery: {{{DELIVERY_ESTIMATE}}}.`

```text
Good news, {{{NAME}}}: your order has shipped.

Carrier:        {{{CARRIER}}}
Tracking:       {{{TRACKING_NUMBER}}}
Estimated:      {{{DELIVERY_ESTIMATE}}}

[Track your package]  →  {{{TRACKING_LINK}}}
```

**Variables:** `NAME`, `ORDER_ID`, `CARRIER`, `TRACKING_NUMBER`, `DELIVERY_ESTIMATE`, `TRACKING_LINK`

## 8\. Account update template (email or password changed)

**When:** a user changes their email address, password or two-factor settings.

**Subject:** `Your {{{PRODUCT}}} {{{CHANGE}}} was changed` **Preview text:** `If this was you, no action is needed.`

```text
Hi {{{NAME}}},

The {{{CHANGE}}} on your {{{PRODUCT}}} account was changed on {{{DATE}}}.

If this was you, you don't need to do anything.

If it wasn't you, secure your account now:
[Secure my account]  →  {{{SECURE_LINK}}}
```

**Variables:** `NAME`, `PRODUCT`, `CHANGE` (for example "password" or "email address"), `DATE`, `SECURE_LINK`

**Tip:** when the email address changes, send this to the **old** address. That's the person who needs to know if the change wasn't them.

## 9\. Security alert template (new sign-in)

**When:** a sign-in from a new device or location.

**Subject:** `New sign-in to your {{{PRODUCT}}} account` **Preview text:** `{{{DEVICE}}} · {{{LOCATION}}}`

```text
Hi {{{NAME}}},

Your account was just signed in to from a new device.

Device:    {{{DEVICE}}}
Location:  {{{LOCATION}}} (approximate)
Time:      {{{TIME}}}

If this was you, you can ignore this email.
If not, change your password and sign out other sessions:
[Review activity]  →  {{{ACTIVITY_LINK}}}
```

**Variables:** `NAME`, `PRODUCT`, `DEVICE`, `LOCATION`, `TIME`, `ACTIVITY_LINK`

## 10\. Team invitation template

**When:** someone invites a colleague to their workspace.

**Subject:** `{{{INVITER}}} invited you to {{{WORKSPACE}}} on {{{PRODUCT}}}` **Preview text:** `Accept the invite to join the team.`

```text
{{{INVITER}}} has invited you to join {{{WORKSPACE}}} on {{{PRODUCT}}}.

[Accept invitation]  →  {{{INVITE_LINK}}}

This invite expires on {{{EXPIRES_ON}}}. If you weren't expecting it, you can
ignore this email.
```

**Variables:** `INVITER`, `WORKSPACE`, `PRODUCT`, `INVITE_LINK`, `EXPIRES_ON`

**Tip:** put the inviter's name in the subject and the From name ("Maya via Acme"). People open email from someone they know.

## The HTML base template for all 10

Each template above is the content. This is the wrapper that makes it render properly: a single column, table-based layout (still the most reliable approach across email clients), hidden preview text, a button that works in Outlook, and a plain-text fallback link under it.

```html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <meta name="color-scheme" content="light dark">
  <meta name="supported-color-schemes" content="light dark">
  <title>{{{SUBJECT}}}</title>
</head>
<body style="margin:0;padding:0;background:#f4f4f5;">
  <!-- Preview text: shown in the inbox list, hidden in the email -->
  <div style="display:none;max-height:0;overflow:hidden;">{{{PREVIEW_TEXT}}}</div>

  <table role="presentation" width="100%" cellpadding="0" cellspacing="0" style="background:#f4f4f5;">
    <tr>
      <td align="center" style="padding:24px 12px;">
        <table role="presentation" width="100%" cellpadding="0" cellspacing="0"
               style="max-width:560px;background:#ffffff;border-radius:8px;">
          <tr>
            <td style="padding:32px;font-family:-apple-system,Segoe UI,Roboto,Helvetica,Arial,sans-serif;
                       font-size:16px;line-height:24px;color:#18181b;">
              <p style="margin:0 0 16px;">Hi {{{NAME}}},</p>
              <p style="margin:0 0 24px;">We received a request to reset your password.</p>

              <!-- Button: a padded link inside a table cell works in Outlook too -->
              <table role="presentation" cellpadding="0" cellspacing="0">
                <tr>
                  <td style="border-radius:6px;background:#18181b;">
                    <a href="{{{ACTION_LINK}}}"
                       style="display:inline-block;padding:12px 20px;color:#ffffff;
                              text-decoration:none;font-weight:600;">Reset password</a>
                  </td>
                </tr>
              </table>

              <p style="margin:24px 0 0;font-size:14px;line-height:20px;color:#52525b;">
                Or copy this link: {{{ACTION_LINK}}}<br>
                If you didn't ask for this, you can ignore this email.
              </p>
            </td>
          </tr>
        </table>
        <p style="margin:16px 0 0;font-family:Arial,sans-serif;font-size:12px;color:#71717a;">
          {{{COMPANY_LEGAL_NAME}}} · {{{COMPANY_ADDRESS}}}
        </p>
      </td>
    </tr>
  </table>
</body>
</html>
```

Why it's built this way:

- **Tables, not `<div>` layouts.** Some desktop email clients, Outlook for Windows in particular, still render with a limited HTML engine. Nested tables survive it.
- **Inline styles.** Many clients strip `<style>` blocks or ignore classes, so every style that matters is inline.
- **`max-width:560px`.** One column that's readable on a phone and doesn't stretch on a desktop.
- **Color-scheme meta tags.** They tell clients that support dark mode the email can be adapted, instead of inverting it badly. For the full picture, see [dark mode email design](https://www.cresca.xyz/blog/dark-mode-email-design).
- **The raw link under the button.** If the button doesn't render, the reader can still act.

Test the result in Gmail, Outlook and Apple Mail, on a phone and a desktop, before you ship it. Our [mobile email design guide](https://www.cresca.xyz/blog/mobile-email-optimization) covers what to check.

## How to send these templates from your app

Writing HTML into your application code works, but it means a deploy every time someone wants to change a word. A better pattern is to store the templates in your email platform and have your code send only the template's id and the values.

Here's how that works with Cresca's Templates API. First, create the template once, with its variables and fallbacks:

```bash
curl -X POST https://api.cresca.xyz/api/v1/templates \
  -H "Authorization: Bearer $CRESCA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Password reset",
    "alias": "password-reset",
    "subject": "Reset your Acme password",
    "from": "Acme <hello@mail.acme.com>",
    "preview_text": "This link expires in 1 hour.",
    "html": "<p>Hi {{{NAME}}},</p><p><a href=\"{{{RESET_LINK}}}\">Reset your password</a>. The link expires in 1 hour.</p>",
    "variables": [
      { "key": "NAME", "type": "string", "fallback_value": "there" },
      { "key": "RESET_LINK", "type": "string" }
    ]
  }'
```

Publish it (sends always use the published version, so you can edit a draft without affecting live email):

```bash
curl -X POST https://api.cresca.xyz/api/v1/templates/password-reset/publish \
  -H "Authorization: Bearer $CRESCA_API_KEY"
```

Then your app sends the alias and the values. In Node.js:

```javascript
const res = await fetch("https://api.cresca.xyz/api/v1/emails", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.CRESCA_API_KEY}`,
    "Content-Type": "application/json",
    // One key per reset request, so a retried request can't send a duplicate
    "Idempotency-Key": `password-reset/${resetRequest.id}`,
  },
  body: JSON.stringify({
    to: user.email,
    template: {
      id: "password-reset",
      variables: { NAME: user.firstName, RESET_LINK: resetRequest.url },
    },
  }),
});
const { id } = await res.json();
```

A few things this gets you for free:

- **Escaping.** Values are HTML-escaped in the HTML body, so a name like `<b>Ana</b>` shows as text and can never change your email's markup.
- **Fallbacks.** `NAME` falls back to "there" if your app doesn't send it. A variable with no value and no fallback stops the send with a clear `422` error, instead of sending "Hi ," to a customer.
- **Version history.** Every publish is kept, so you can see who changed a template and restore an earlier version.
- **No redeploys for copy changes.** Edit the template, send a test, publish.

The [email templates API guide](https://www.cresca.xyz/blog/email-templates-api) has the full walkthrough with Python and cURL, and the [templates docs](https://www.cresca.xyz/docs/templates) cover every field.

## Transactional email template checklist

Before any template goes live:

- One purpose, one primary action, visible without scrolling on a phone.
- A plain-text link or code under every button.
- "If you didn't request this…" on anything security-related.
- No promotions, banners or newsletter signups.
- A real reply-to address, not `noreply@`, unless replies genuinely can't be handled.
- Sent from your own verified domain, ideally a subdomain used only for app email (for example `mail.yourapp.com`).
- A fallback for every optional variable.
- Tested in Gmail, Outlook and Apple Mail, light and dark mode, phone and desktop.

## Frequently asked questions

### What is a transactional email template?

A transactional email template is a reusable layout for an email your app sends after a user's action, such as a password reset, receipt or verification email. It contains placeholders, like `{{{NAME}}}` or `{{{RESET_LINK}}}`, that your app fills in for each person at send time.

### What should a transactional email include?

What happened, what the person needs to do (one clear action), what happens if they ignore it, and how to get help. For receipts and invoices, also your company's legal details. Keep out anything promotional.

### Do transactional emails need an unsubscribe link?

No. Transactional emails are about a specific transaction the person started, so they don't need an unsubscribe link, and an unsubscribe from your newsletter shouldn't stop them. Marketing emails always need one.

### Should transactional emails be HTML or plain text?

Send both. Use simple HTML for structure and a button, and include a plain-text version for clients that prefer it. Most email APIs, Cresca included, can generate the text version from your HTML if you don't provide one.

### Where can I find free transactional email templates?

The 10 templates in this guide are free to copy and adapt, along with the HTML base template above. Replace the variables with your own and test them in the main email clients before you go live.

## Send your first template today

Cresca includes a transactional email API on every plan: templates with variables and version history, idempotent sends, and delivery status for every email, from your own domain, in the same account as your marketing campaigns. **[Try Cresca free for 30 days](https://app.cresca.xyz/signup)**, no credit card required, and follow the [quickstart](https://www.cresca.xyz/docs/quickstart) to send your first template.
