# Email Template

An **Email Template** represents the message structure and copywriting of transactional emails sent to your loyalty program members. These templates contain a subject line, an HTML body, and link to an optional [Email Header](/email-header) and [Email Footer](/email-footer) to form complete branded emails.

:::tip
Both `subject` and `htmlContent` fields are **localisable**. Pass a `languageCode` query parameter when updating or fetching the email template to manage translated copy for your international users.
:::

---

## How it works

1. **Create an email template** — define a name, description, status, subject line, and the HTML body content.
2. **Assign layout wrappers** — link an `EmailHeader` (`emailHeaderId`) and `EmailFooter` (`emailFooterId`) to structure the overall email frame.
3. **Choose the sample event code** — select a `sampleEventCode` (e.g. `streak_progress_broken`, `challenge_progress_completed`) to get the sample event data to design your email template. This field is used to select the sample event data to design your email template and not trigger the email itself. To send an email on the basis of event, you will need to configure [Email Notification](/email-notification).
4. **Define dynamic variables** — write your template using curly braces `{{ }}` to merge dynamic details (like member details, streak or challenge details, and streak status) during delivery.
5. **Attach to email notifications** — link the template to an active [Email Notification](/email-notification) rule to automate delivery.

---

## Fields

### Basic information

| Field | Type | Required | Max length | Description |
|---|---|---|---|---|
| `name` | string | ✅ | 256 | The name of the email template |
| `description` | string | ❌ | 1 024 | A brief description of the email template |
| `status` | enum | ✅ | — | `draft` · `live` · `paused` |

### Configuration settings

| Field | Type | Required | Description |
|---|---|---|---|
| `emailHeaderId` | UUID | ❌ | Optional reference to an [Email Header](/email-header) |
| `emailFooterId` | UUID | ❌ | Optional reference to an [Email Footer](/email-footer) |
| `sampleEventCode` | enum | ✅ | The sample event code to pick the sample event data for template designing. See [Event Codes](#event-codes) below. |

### Copy and content

| Field | Type | Required | Max length | Description |
|---|---|---|---|---|
| `subject` | string | ✅ | 256 | The email subject line. Supports variables and localisation. |
| `htmlContent` | string | ✅ | — | The HTML body of the email. Supports variables and localisation. |

---

## Event codes

The `sampleEventCode` maps the email template to a specific type of loyalty event. The template will receive event-specific variables at runtime:

- `streak_progress_broken`
- `streak_progress_to_be_broken`
- `streak_progress_completed`
- `streak_progress_milestone_completed`
- `streak_progress_non_milestone_completed`
- `streak_progress_in_progress`
- `challenge_progress_failed`
- `challenge_progress_to_be_failed`
- `challenge_progress_completed`
- `challenge_progress_milestone_completed`
- `challenge_progress_in_progress`

---

## Template variables

The template rendering engine replaces double curly braces `{{ }}` with event data. 

### Common variable namespaces supported

Available in all templates:

| Variable | Description | Example value |
|---|---|---|
| `{{$organization.*}}` | Organization variables | `{{$organization.name}}`. Refer to [Organization](/organization) for more details on available variables names.
| `{{$account.*}}` | Account variables | `{{$account.name}}`. Refer to [Account](/account) for more details on available variables names.
| `{{$account_user.*}}` | Account User (Member) variables | `{{$account_user.firstName}}`, `{{$account_user.lastName}}`, `{{$account_user.email}}`. Refer to [Member](/member) for more details on available variables names.
| `{{$event_log.payload.*}}` | Event log variables | `{{$event_log.payload.streakLog}}`, `{{$event_log.payload.challengeLog}}`, `{{$event_log.payload.streakProgress}}`, `{{$event_log.payload.challengeProgress}}`. Refer more on this below.
| `{{$helpers.*}}` | Helper variables | `{{$helpers.periodText}}`, `{{$helpers.currentProgressValue}}`, `{{$helpers.nextMilestoneRemainingValue}}`. Refer more on this below.


### Event Log variables
| Variable | Description | Example value |
|---|---|---|
|`{{$event_log.payload.streakLog}}`| Streak log object (When `sampleEventCode` is one of `streak_progress_completed`, `streak_progress_milestone_completed`, `streak_progress_non_milestone_completed`, `streak_progress_in_progress`  ) | Refer this [Streak Log](/streak-log) for object details|
|`{{$event_log.payload.challengeLog}}`| Challenge log object (When `sampleEventCode` is one of `challenge_progress_completed`, `challenge_progress_milestone_completed`, `challenge_progress_in_progress`) | Refer this [Challenge Log](/challenge-log) for object details|
|`{{$event_log.payload.streakProgress}}`| Streak progress object (When `sampleEventCode` is one of `streak_progress_broken`, `streak_progress_to_be_broken`) | Refer below for the object structure |
|`{{$event_log.payload.challengeProgress}}`| Challenge progress object (When `sampleEventCode` is one of `challenge_progress_failed`, `challenge_progress_to_be_failed`) | Refer below for the object structure |

**$event_log.payload.streakProgress**
```json
{
  ...<Streak Progress>,
  "streak": <Streak>,
  "nextMilestone": <Milestone> | null
}
```
Refer this [Streak Progress](/streak-progress) for object details

Refer this [Streak](/streak) for object details

Refer this [Milestone](/milestone) for object details

**$event_log.payload.challengeProgress**
```json
{
  ...<Challenge Progress Object>,
  "challenge": <Streak Object>,
  "nextMilestone": <Milestone Object> | null
}
```
Refer this [Challenge Progress](/challenge-progress) for object details

Refer this [Challenge](/challenge) for object details

Refer this [Milestone](/milestone) for object details

### Streak event helper variables

Available when `sampleEventCode` begins with `streak_`:

| Variable | Description | Example value |
|---|---|---|
| `{{$helpers.unsubscribeUrl}}` | The unsubscribe URL of the user. This URL is unique for each user. |
| `{{$helpers.periodText}}` | Aggregation period unit | `day` · `week` · `month` |
| `{{$helpers.remainingValue}}` | Steps/spend remaining to keep the streak. It is same as either `{{$helpers.nextMilestoneRemainingValue}}` or `{{$helpers.nextNonMilestoneRemaining  Value}}` depending on the current streak progress. | `10.00` |
| `{{$helpers.nextMilestoneRemainingValue}}` | Steps/spend remaining to reach the next milestone | `150.00` |
| `{{$helpers.nextNonMilestoneRemainingValue}}` | Steps/spend remaining to reach the next non-milestone | `50.00` |
| `{{$helpers.currentProgressValue}}` | Current active streak length | `5` |
| `{{$helpers.nextMilestoneTargetValue}}` | Target value for the next milestone | `3` |
| `{{$helpers.nextNonMilestoneTargetValue}}` | Target value for the next non-milestone | `2` |
| `{{$helpers.completionTargetValue}}` | Target value for the current period | `3` |
| `{{$helpers.formattedStreakToBeBrokenAt}}` | Expiration time for active period | `2026-07-20 23:59:59` |

### Challenge event helper variables

Available when `sampleEventCode` begins with `challenge_`:

| Variable | Description | Example value |
|---|---|---|
| `{{$helpers.unsubscribeUrl}}` | The unsubscribe URL of the user. This URL is unique for each user. |
| `{{$helpers.periodText}}` | Duration of the challenge window | `day` · `week` · `month` |
| `{{$helpers.remainingValue}}` | Steps/spend remaining to complete the challenge | `100.00` |
| `{{$helpers.currentProgressValue}}` | Total accumulated value | `25.00` |
| `{{$helpers.nextMilestoneRemainingValue}}` | Value needed for next milestone | `25.00` |
| `{{$helpers.completionTargetValue}}` | Target value for the current period | `150.00` |
| `{{$helpers.formattedChallengeToBeFailedAt}}` | Expiration time for active period | `2026-07-20 23:59:59` |
---

## Real-world examples

**🛍️ E-commerce — Streak Milestone Reached Template**

An email template sent when a user earns a coupon for maintaining their daily purchase streak:

```json
{
  "name": "Streak 7-Day Completed Email",
  "description": "Sent automatically when a member hits a 7-day streak.",
  "status": "live",
  "emailHeaderId": "01997da4-18e0-4863-9701-62b4c3000001",
  "emailFooterId": "01997da4-18e0-4863-9701-62b4c3000002",
  "sampleEventCode": "streak_progress_milestone_completed",
  "subject": "🎉 You hit a 7-{{$helpers.periodText}} streak!",
  "htmlContent": "<html>
<head>
<title>Congratulations!! You have completed {{$event_log.payload.streakLog.achievedMilestone.eudTitle}} of {{$event_log.payload.streakLog.streak.eudTitle}}</title>
<style>
        body {
            font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
            background-color: #f4f7f9;
            margin: 0;
            padding: 0;
            -webkit-font-smoothing: antialiased;
        }
        .container {
            max-width: 600px;
            margin: 40px auto;
            background-color: #ffffff;
            border-radius: 8px;
            overflow: hidden;
        }
        .content {
            padding: 40px;
            color: #333333;
            line-height: 1.6;
        }
        .field-table {
            width: 100%;
            border-collapse: collapse;
            margin: 24px 0;
        }
        .field-table tr {
            border-bottom: 1px solid #f0f0f0;
        }
        .field-table tr:last-child {
            border-bottom: none;
        }
        .field-label {
            width: 36%;
            padding: 10px 12px 10px 0;
            font-size: 13px;
            font-weight: 600;
            color: #888888;
            text-transform: uppercase;
            letter-spacing: 0.04em;
            vertical-align: top;
            white-space: nowrap;
        }
        .field-value {
            padding: 10px 0;
            font-size: 15px;
            color: #333333;
            vertical-align: top;
            word-break: break-word;
        }
        .message-box {
            background-color: #f8f9fb;
            border-left: 3px solid rgb(124, 58, 237);
            border-radius: 4px;
            padding: 16px 20px;
            margin: 4px 0;
            font-size: 15px;
            color: #333333;
            white-space: pre-wrap;
            word-break: break-word;
        }
        .optional-section {
            margin-top: 28px;
            padding-top: 20px;
            border-top: 1px solid #eeeeee;
        }
        .optional-title {
            font-size: 12px;
            font-weight: 600;
            color: #aaaaaa;
            text-transform: uppercase;
            letter-spacing: 0.06em;
            margin-bottom: 12px;
        }
    </style>
</head>
<body>
<div class="container">
{{>header}}
<div class="content">
<p>Hi {{$account_user.firstName}},</p>
<p>{{$event_log.payload.streakLog.streak.eudMilestoneAchievedMessage}}</p>
</body>
</div>
{{>footer}}
</div>
</html>"
}
```

---

## Access & permissions

| Caller | Allowed operations | Notes |
|---|---|---|
| Admin | CREATE · GET · LIST · UPDATE · DELETE | Full control over email templates |
| End user | *(none)* | No access |
| Guest user | *(none)* | No access |

---

## Related resources

| Resource | Description |
|---|---|
| [Email Header](/email-header) | Custom HTML header banner linked to the template |
| [Email Footer](/email-footer) | Custom HTML footer wrapper linked to the template |
| [Email Notification](/email-notification) | The active triggers that map event codes to specific templates |

---

## API reference

See the [API Reference](/api/email_template) for full request/response schemas and interactive examples for:

- `GET /schema/email_template/record` — list email templates
- `POST /schema/email_template/record` — create an email template
- `GET /schema/email_template/record/{id}` — get an email template by ID
- `PATCH /schema/email_template/record/{id}` — update an email template
- `DELETE /schema/email_template/record/{id}` — delete an email template
