# RevCent MCP Operation: `CreateEmailTemplate`

This document describes the `CreateEmailTemplate` MCP operation, every input field from the operation schema, and how email template Handlebars data is sourced from the selected `template_trigger`.

Sources used:
- RevCent MCP operation schema for `CreateEmailTemplate`
- RevCent Knowledge Base: Email Template — `https://kb.revcent.com/en/integrations/smtp/email-template`

> Scope: This document intentionally covers only the `CreateEmailTemplate` operation.

---

## Operation Summary

`CreateEmailTemplate` creates a new RevCent Email Template and returns a unique 20-character `email_template_id`.

Email Templates define:
- Who the email is sent from.
- Who the email is sent to.
- The subject and HTML body.
- The trigger that causes the email to send.
- Optional timing rules.
- Optional filters.
- Optional custom data injected into the Handlebars render context.
- Optional API/AI custom arguments for `api_direct` templates.

---

## Required Fields

The `CreateEmailTemplate` schema requires the following fields:

| Field | Type | Required | Notes |
|---|---:|---:|---|
| `name` | string | Yes | Must be unique across Email Template names. |
| `smtp_profile` | string | Yes | 20-character SMTP Profile ID. |
| `template_subject` | string | Yes | Supports Handlebars. |
| `template_from` | string | Yes | Sender email address. Supports Handlebars. |
| `template_to` | string[] | Yes | Recipient email addresses or Handlebars email shortcodes. |
| `template_html` | string | Yes | HTML email body. Supports Handlebars. |
| `template_trigger` | string enum | Yes | Determines how the template is triggered and what input data Handlebars receives. |

All other fields are optional.

---

## Complete Input Schema Field Reference

### `name`

**Type:** `string`  
**Required:** Yes

The unique display name of the Email Template.

Use a clear name that identifies both the purpose and the trigger, for example:

```json
"name": "Sale Success - Customer Receipt"
```

Important behavior:

- The name must be unique.
- The name is not used as the trigger identifier.
- A good naming convention makes it easier for API/AI tools to find the correct template later.

---

### `description`

**Type:** `string`  
**Required:** No

A human-readable description of what the template is for.

Example:

```json
"description": "Sent to the customer after a successful sale. Includes purchased products and receipt details."
```

Recommended content:

- Trigger purpose.
- Recipient audience.
- Any important filters.
- Any required custom data or custom arguments.

---

### `enabled`

**Type:** `boolean`  
**Required:** No

Controls whether the Email Template is active and able to send SMTP messages.

```json
"enabled": true
```

Behavior:

- `true`: the template may be used to send SMTP messages when triggered.
- `false`: the template should not be used to send SMTP messages.
- For drafts, use `false` or use `template_trigger: "no_trigger"`.

---

### `smtp_profile`

**Type:** `string`  
**Required:** Yes  
**Length:** exactly 20 characters

The SMTP Profile ID used to send the email.

```json
"smtp_profile": "XXXXXXXXXXXXXXXXXXXX"
```

Important behavior:

- RevCent requires at least one active SMTP Profile to send emails.
- The `template_from` address should match the sender address configured in the SMTP Profile to reduce delivery issues.
- This field is the ID, not the SMTP Profile name.

---

### `template_subject`

**Type:** `string`  
**Required:** Yes  
**Supports Handlebars:** Yes

The subject line used when the email is sent.

Example:

```json
"template_subject": "Thanks for your order, {{customer.first_name}}"
```

How Handlebars works here:

- The subject is rendered using the same input data as the HTML body.
- Available fields depend on `template_trigger`.
- For a sale-related trigger, `{{customer.first_name}}` may be available because the Sale input data includes a nested `customer` object.
- For a customer-created trigger, the customer fields are top-level, so use `{{first_name}}`, not necessarily `{{customer.first_name}}`.

---

### `template_from`

**Type:** `string`  
**Required:** Yes  
**Supports Handlebars:** Yes

The sender email address.

Example:

```json
"template_from": "support@example.com"
```

Dynamic example:

```json
"template_from": "{{custom_data.from_email}}"
```

Best practices:

- Prefer a fixed sender address that matches the SMTP Profile.
- Only use Handlebars if the rendered result will always be a valid email address.
- Avoid rendering an empty value.

---

### `template_from_name`

**Type:** `string`  
**Required:** No  
**Supports Handlebars:** Yes

The sender display name.

Example:

```json
"template_from_name": "Customer Support"
```

Dynamic example:

```json
"template_from_name": "{{custom_data.brand_name}} Support"
```

---

### `template_to`

**Type:** `array<string>`  
**Required:** Yes  
**Supports Handlebars:** Yes

The primary recipients of the email. Each array item may be either a literal email address or a Handlebars expression that renders to an email address.

Example using a customer email:

```json
"template_to": ["{{customer.email}}"]
```

Example using a fixed internal recipient:

```json
"template_to": ["warehouse@example.com"]
```

Important behavior:

- The schema expects an array.
- Each item should render to a valid email address.
- Whether `{{customer.email}}` is valid depends on the trigger input data.
- For `customer_create_success`, the customer object is the input data itself, so the correct path may be `{{email}}` rather than `{{customer.email}}`.
- For sale, shipping, subscription renewal, trial, pending refund, and many other event item types, customer data is commonly nested under `customer`.

---

### `template_to_cc`

**Type:** `array<string>`  
**Required:** No  
**Supports Handlebars:** Yes

CC recipients.

Example:

```json
"template_to_cc": ["orders@example.com"]
```

Dynamic example:

```json
"template_to_cc": ["{{custom_data.account_manager_email}}"]
```

Use this when the recipient should be visible to primary recipients.

---

### `template_to_bcc`

**Type:** `array<string>`  
**Required:** No  
**Supports Handlebars:** Yes

BCC recipients.

Example:

```json
"template_to_bcc": ["audit@example.com"]
```

Use this for internal logging, compliance, or operational recipients who should not be visible to other recipients.

---

### `template_html`

**Type:** `string`  
**Required:** Yes  
**Supports Handlebars:** Yes

The HTML body of the email.

Example:

```json
"template_html": "PASTE_USER_STARTER_HTML_OR_FETCHED_STYLED_SAMPLE_HTML_HERE"
```

Do not use bare paragraph-only examples as final `template_html`.

The HTML body can include:

- Standard HTML.
- Handlebars substitutions.
- Handlebars conditionals.
- Handlebars loops.
- RevCent custom helpers.
- `custom_data` values, if configured.
- `custom_arguments` values, for API/AI direct templates.

Example with conditionals:

```handlebars
{{#if customer.first_name}}
  <p>Hello {{customer.first_name}},</p>
{{else}}
  <p>Hello,</p>
{{/if}}
```

Example with an array loop:

```handlebars
<ul>
{{#each products_detailed}}
  <li>{{name}} — {{formatCurrency total_amount}}</li>
{{/each}}
</ul>
```

---

### `template_trigger`

**Type:** `string` enum  
**Required:** Yes

Determines how the template is triggered and what source input data the Handlebars compiler receives.

Schema-supported enum values:

```text
no_trigger
api_direct
sale_create_success
sale_create_decline
pending_sale_no_payment
sentinel_alert_create_success
ai_memo_create_success
fraud_alert_create_success
fraud_detection_create_success
invoice_create_success
customer_create_success
pending_refund_create_success
shipping_item_created
shipping_item_shipped
shipping_item_delivered
shipping_item_voided
subscription_renew_success
subscription_renew_decline
subscription_renewal_upcoming
trial_expire_success
trial_expire_decline
trial_expire_upcoming
```

Important:

- The Knowledge Base page lists additional UI trigger names and examples, including sale fail, sale fraud alert, invoice, Sentinel, fraud detection, shipping created, and shipping voided.
- The MCP/OpenAPI schema for `CreateEmailTemplate` only allows the enum values above.
- When creating templates via MCP, use only schema-supported enum values.

---

### `trigger_sources_allowed`

**Type:** `array<string>`  
**Required:** No  
**Applies only to:** `shipping_item_shipped`, `shipping_item_delivered`

Restricts shipping-triggered emails based on what caused the shipment.

Allowed values:

```text
sale_create
subscription_renew
trial_expire
```

Example:

```json
"trigger_sources_allowed": ["sale_create"]
```

Behavior:

- Only applies to shipping update triggers.
- Leave empty or omit to allow all shipping trigger sources.
- Use this when shipment emails should only be sent for shipments originating from a sale, renewal, or trial expiration.

Example use cases:

```json
{
  "template_trigger": "shipping_item_shipped",
  "trigger_sources_allowed": ["sale_create"]
}
```

This means the template should send when an item ships, but only if the shipment originated from a sale.

---

## `timing`

**Type:** `object`  
**Required:** No

Controls when the email sends relative to the trigger event.

If timing is not enabled, the template sends immediately when the trigger occurs.

Schema:

```json
"timing": {
  "enabled": true,
  "time_unit": "hours",
  "time_value": 3,
  "time_relative": "after"
}
```

### `timing.enabled`

**Type:** `boolean`

Whether timing settings are active.

- `false`: send immediately when the trigger occurs.
- `true`: use `time_unit`, `time_value`, and `time_relative`.

### `timing.time_unit`

**Type:** `string` enum

Allowed values:

```text
hours
days
weeks
months
years
```

The schema description references seconds and minutes conceptually, but the actual schema enum only allows the values above.

### `timing.time_value`

**Type:** `integer`

The numeric amount of `time_unit`.

Example:

```json
"time_value": 3
```

With `time_unit: "hours"` and `time_relative: "after"`, this means 3 hours after the event.

### `timing.time_relative`

**Type:** `string` enum

Allowed values:

```text
after
before
```

Behavior:

- `after`: send after the event occurs.
- `before`: only applies to predictable upcoming triggers:
  - `subscription_renewal_upcoming`
  - `trial_expire_upcoming`

Do not use timing with `api_direct`; API-direct templates are intended to send immediately when explicitly triggered.

Examples:

Send 3 hours after a successful sale:

```json
"template_trigger": "sale_create_success",
"timing": {
  "enabled": true,
  "time_unit": "hours",
  "time_value": 3,
  "time_relative": "after"
}
```

Send 1 day before an upcoming subscription renewal:

```json
"template_trigger": "subscription_renewal_upcoming",
"timing": {
  "enabled": true,
  "time_unit": "days",
  "time_value": 1,
  "time_relative": "before"
}
```

---

## `filters`

**Type:** `object`  
**Required:** No

Filters determine whether the template should send when the trigger occurs. The trigger can occur, but the email will only send if the related item matches the configured filters.

Schema:

```json
"filters": {
  "campaign": ["XXXXXXXXXXXXXXXXXXXX"],
  "product": ["XXXXXXXXXXXXXXXXXXXX"],
  "product_group": ["XXXXXXXXXXXXXXXXXXXX"],
  "third_party_shop": ["XXXXXXXXXXXXXXXXXXXX"]
}
```

### `filters.campaign`

**Type:** `array<string>`

A list of 20-character Campaign IDs.

The event must be related to one of the listed campaigns.

### `filters.product`

**Type:** `array<string>`

A list of 20-character Product IDs.

The event must be related to one of the listed products.

### `filters.product_group`

**Type:** `array<string>`

A list of 20-character Product Group IDs.

The event must be related to one of the listed product groups.

### `filters.third_party_shop`

**Type:** `array<string>`

A list of 20-character third-party shop IDs.

The event must be related to one of the listed shops.

Filter notes:

- Omit `filters` entirely if no filter is needed.
- Omit a specific filter array if that filter should not be applied.
- Filters are most useful for sale, shipping, subscription, and trial-related templates.
- The related event must contain enough data for the filter to be evaluated.

---

## `custom_data`

**Type:** `object`  
**Required:** No

Adds extra data to the Handlebars input data under the `custom_data` property.

Schema:

```json
"custom_data": {
  "enabled": true,
  "source_type": "json",
  "source_value": "{\"brand_name\":\"Example Brand\"}"
}
```

### `custom_data.enabled`

**Type:** `boolean`

Enables or disables custom data.

When enabled, `custom_data` becomes available in the Handlebars render context:

```handlebars
{{custom_data.brand_name}}
```

### `custom_data.source_type`

**Type:** `string` enum

Allowed values:

```text
json
custom_function
```

### `custom_data.source_value`

**Type:** `string`

The meaning depends on `source_type`.

#### When `source_type` is `json`

`source_value` must be a stringified JSON object.

Example:

```json
"custom_data": {
  "enabled": true,
  "source_type": "json",
  "source_value": "{\"support_email\":\"support@example.com\",\"brand_name\":\"Example Brand\"}"
}
```

Template usage:

```handlebars
<p>Need help? Email {{custom_data.support_email}}.</p>
```

#### When `source_type` is `custom_function`

`source_value` must be a 20-character Function ID.

Example:

```json
"custom_data": {
  "enabled": true,
  "source_type": "custom_function",
  "source_value": "XXXXXXXXXXXXXXXXXXXX"
}
```

Function requirements:

- The function must have an event source of `email_template`.
- The function receives the same item details as the template input data.
- In the function, the item details are available at:

```javascript
event.data.item_details
```

- The function must return a plain JavaScript object.
- The returned object is inserted into the Handlebars input data as `custom_data`.

Example function concept:

```javascript
let customerEmail = event.data.item_details.customer.email;

callback(null, {
  email_capitalized: customerEmail.toUpperCase(),
  email_local_part: customerEmail.split('@')[0]
});
```

Template usage:

```handlebars
<p>Email local part: {{custom_data.email_local_part}}</p>
```

Important concept:

The base Handlebars input data comes from the selected trigger. `custom_data` does not replace it. It is added alongside it.

For example, for a sale trigger, the render context may conceptually look like:

```json
{
  "amount_captured": 12,
  "customer": {
    "email": "george@example.com",
    "first_name": "George"
  },
  "custom_data": {
    "email_local_part": "george"
  }
}
```

---

## `custom_arguments`

**Type:** `array<object>`  
**Required:** No  
**Applies primarily to:** `api_direct`

Defines argument names and descriptions that should be supplied when sending an API/AI-triggered SMTP message using this template.

Schema:

```json
"custom_arguments": [
  {
    "name": "thank_you_paragraph",
    "description": "Generate a customized thank-you paragraph based on the customer's name and purchase."
  }
]
```

Each object has:

### `custom_arguments[].name`

**Type:** `string`

The argument name. This becomes available in Handlebars as:

```handlebars
{{custom_arguments.thank_you_paragraph}}
```

### `custom_arguments[].description`

**Type:** `string`

Instructional text describing what value should be provided when the email is sent.

Best practices:

- Use descriptive names.
- Write descriptions as instructions.
- Be specific about tone, length, and source data.
- Only use this for `api_direct` templates.

Example:

```json
"custom_arguments": [
  {
    "name": "personalized_intro",
    "description": "Write a warm one-sentence intro using the customer's first name and the product they purchased."
  }
]
```

Template usage:

```handlebars
<p>{{custom_arguments.personalized_intro}}</p>
```

Important:

- `custom_arguments` defines what arguments the sender should provide later.
- It does not itself provide the runtime value.
- Runtime values are supplied when the SMTP message is sent via API/AI.

---

# Handlebars Data Model

## Core Rule

The Handlebars compiler receives input data based on the selected `template_trigger`.

The Knowledge Base states that the input data corresponds to the trigger item type. For example, if the trigger is a sale trigger, the compiler receives Sale JSON. If the trigger is a shipping trigger, it receives Shipping JSON.

That means this:

```handlebars
{{customer.first_name}}
```

only works when the input data contains:

```json
{
  "customer": {
    "first_name": "George"
  }
}
```

For a Customer trigger, the input data is the Customer object itself, so the first name is top-level:

```handlebars
{{first_name}}
```

not:

```handlebars
{{customer.first_name}}
```

unless the input data actually contains a nested `customer`.

---

## Where Handlebars Can Be Used

The schema explicitly supports Handlebars in:

- `template_subject`
- `template_from`
- `template_from_name`
- `template_to`
- `template_to_cc`
- `template_to_bcc`
- `template_html`

Most templates use Handlebars primarily in `template_subject` and `template_html`, but recipient fields can also be dynamic.

---

## Basic Substitution

Input data:

```json
{
  "customer": {
    "first_name": "George"
  }
}
```

Template:

```handlebars
Hello {{customer.first_name}}
```

Output:

```text
Hello George
```

---

## Conditionals

```handlebars
{{#if customer.first_name}}
  <p>Hello {{customer.first_name}},</p>
{{else}}
  <p>Hello,</p>
{{/if}}
```

Use conditionals when:

- A field may be empty.
- You want different content for success vs decline.
- You want to show shipping details only if a tracking number exists.

---

## Iteration

If the input data contains an array, use `each`.

Example:

```handlebars
<ul>
{{#each products_detailed}}
  <li>{{name}} — {{formatCurrency total_amount}}</li>
{{/each}}
</ul>
```

Inside `each`, paths are relative to the current item.

To access parent scope, use normal Handlebars parent path syntax where supported, for example:

```handlebars
{{../customer.first_name}}
```

---

## Additional Shortcodes

The KB lists these additional shortcodes for all triggers:

| Shortcode | Applies To | Description |
|---|---|---|
| `{{item_date}}` | All triggers | Date of the item relative to the trigger, such as sale date or renewal date. |
| `{{date_now}}` | All triggers | Current date when the email is sent. |

Example:

```handlebars
<p>Email sent on {{date_now}}.</p>
<p>Item date: {{item_date}}.</p>
```

---

## Custom Helpers

RevCent supports standard Handlebars plus custom helpers.

### `formatDate`

Formats a valid ISO date or Unix timestamp.

```handlebars
{{formatDate created_date_unix 'MM/DD/YYYY' '-0500'}}
```

Notes:

- Default format is `MM/DD/YYYY`.
- Timezone offset is optional.
- You can use `now` to format the send-time timestamp.

```handlebars
{{formatDate now 'MM/DD/YYYY' '-0500'}}
```

### `formatCurrency`

Formats a number using the `iso_currency` value from the input data.

```handlebars
{{formatCurrency amount_total}}
```

Example use:

```handlebars
<p>Total: {{formatCurrency amount_total}}</p>
```

### `findWhereEquals`

Finds a value inside an array of objects.

Format:

```handlebars
{{findWhereEquals 'metadata' 'name' 'affiliate_id' 'value'}}
```

Meaning:

- Search the `metadata` array.
- Find the object where `name` equals `affiliate_id`.
- Return that object's `value`.

Useful for metadata:

```handlebars
Affiliate ID: {{findWhereEquals 'metadata' 'name' 'affiliate_id' 'value'}}
```

### `math`

Performs a calculation.

Format:

```handlebars
{{math 'add' shipping_amount tax_amount 'currency'}}
```

Supported operations:

- `add`
- `subtract`
- `multiply`
- `divide`

Supported output formats:

- `integer`
- `float`
- `currency`

### Type and Case Helpers

```handlebars
{{parseInt amount}}
{{parseFloat amount}}
{{toString amount}}
{{startCase customer.first_name}}
{{upperCase customer.first_name}}
{{lowerCase customer.first_name}}
```

---

# Trigger-Specific Source `input_data`

The `template_trigger` determines the source data available to Handlebars. The trigger enum description includes direct JSON example links for each supported trigger that has event data.

Use the JSON link for the selected trigger as the source of truth for Handlebars paths. For example, a Sale trigger uses the Sale JSON object, while `subscription_renewal_upcoming` uses the Subscription JSON object, not the Subscription Renewal JSON object.

| `template_trigger` | Source `input_data` | Input data JSON | Notes |
|---|---|---|---|
| `no_trigger` | None | N/A | Draft or external-process template; no event input data. |
| `api_direct` | None by default | N/A | Triggered directly by API/MCP or AI; use custom arguments/custom data unless item context is supplied when sending. |
| `sale_create_success` | sale object | [sale object](https://revcent.com/documentation/files/email_template/input_data/sale.json) | Sale created and payment succeeded. |
| `sale_create_decline` | sale object | [sale object](https://revcent.com/documentation/files/email_template/input_data/sale.json) | Sale created but all payment attempts failed due to error or decline. |
| `pending_sale_no_payment` | sale object | [sale object](https://revcent.com/documentation/files/email_template/input_data/sale.json) | Pending sale created but no payment attempt was made; abandoned-cart style trigger. |
| `sentinel_alert_create_success` | sentinel object | [sentinel object](https://revcent.com/documentation/files/email_template/input_data/sentinel.json) | Sentinel fraud detection occurred. |
| `ai_memo_create_success` | AI memo object | [AI memo object](https://revcent.com/documentation/files/email_template/input_data/ai_memo.json) | AI Assistant created an AI Memo. |
| `fraud_alert_create_success` | sentinel object | [sentinel object](https://revcent.com/documentation/files/email_template/input_data/sentinel.json) | Sale was marked with a fraud alert for manual review; payment was not prevented. |
| `fraud_detection_create_success` | fraud detection object | [fraud detection object](https://revcent.com/documentation/files/email_template/input_data/fraud_detection.json) | Fraud Detection was created and payment was prevented. |
| `invoice_create_success` | invoice object | [invoice object](https://revcent.com/documentation/files/email_template/input_data/invoice.json) | Invoice was created with a unique URL. |
| `customer_create_success` | customer object | [customer object](https://revcent.com/documentation/files/email_template/input_data/customer.json) | Customer created by customer create method, not because of a new sale. |
| `pending_refund_create_success` | pending refund object | [pending refund object](https://revcent.com/documentation/files/email_template/input_data/pending_refund.json) | Pending refund was created. |
| `shipping_item_created` | shipping object | [shipping object](https://revcent.com/documentation/files/email_template/input_data/shipping.json) | Shipment was created; useful for warehouse notifications. |
| `shipping_item_shipped` | shipping object | [shipping object](https://revcent.com/documentation/files/email_template/input_data/shipping.json) | Shipment was shipped. |
| `shipping_item_delivered` | shipping object | [shipping object](https://revcent.com/documentation/files/email_template/input_data/shipping.json) | Shipment was delivered. |
| `shipping_item_voided` | shipping object | [shipping object](https://revcent.com/documentation/files/email_template/input_data/shipping.json) | Shipment was voided. |
| `subscription_renew_success` | subscription renewal object | [subscription renewal object](https://revcent.com/documentation/files/email_template/input_data/subscription_renewal.json) | Subscription renewal succeeded. |
| `subscription_renew_decline` | subscription renewal object | [subscription renewal object](https://revcent.com/documentation/files/email_template/input_data/subscription_renewal.json) | Subscription renewal declined. |
| `subscription_renewal_upcoming` | subscription object | [subscription object](https://revcent.com/documentation/files/email_template/input_data/subscription.json) | Upcoming subscription renewal; uses subscription object, not subscription_renewal. |
| `trial_expire_success` | trial object | [trial object](https://revcent.com/documentation/files/email_template/input_data/trial.json) | Trial expired successfully. |
| `trial_expire_decline` | trial object | [trial object](https://revcent.com/documentation/files/email_template/input_data/trial.json) | Trial expiration failed due to error or decline. |
| `trial_expire_upcoming` | trial object | [trial object](https://revcent.com/documentation/files/email_template/input_data/trial.json) | Upcoming trial expiration. |

## Input Data Link Reference

These are the unique linked input-data JSON files used by the trigger enum description:

| Source object | URL |
|---|---|
| Sale | https://revcent.com/documentation/files/email_template/input_data/sale.json |
| Sentinel | https://revcent.com/documentation/files/email_template/input_data/sentinel.json |
| AI Memo | https://revcent.com/documentation/files/email_template/input_data/ai_memo.json |
| Fraud Detection | https://revcent.com/documentation/files/email_template/input_data/fraud_detection.json |
| Invoice | https://revcent.com/documentation/files/email_template/input_data/invoice.json |
| Customer | https://revcent.com/documentation/files/email_template/input_data/customer.json |
| Pending Refund | https://revcent.com/documentation/files/email_template/input_data/pending_refund.json |
| Shipping | https://revcent.com/documentation/files/email_template/input_data/shipping.json |
| Subscription Renewal | https://revcent.com/documentation/files/email_template/input_data/subscription_renewal.json |
| Subscription | https://revcent.com/documentation/files/email_template/input_data/subscription.json |
| Trial | https://revcent.com/documentation/files/email_template/input_data/trial.json |

## Trigger: `api_direct`

### Source input data

`api_direct` templates are triggered directly via API/AI. The template does not have a fixed event item type by default.

Use:

- `custom_arguments` for values provided at send time.
- `custom_data` for static JSON or function-generated values.
- Optional item context when the SMTP message is sent with an item type and item ID.

### Recommended Handlebars

```handlebars
<p>{{custom_arguments.personalized_message}}</p>
<p>Support: {{custom_data.support_email}}</p>
```

### Recommended CreateEmailTemplate pattern

```json
{
  "name": "API Direct - Personalized Follow Up",
  "smtp_profile": "XXXXXXXXXXXXXXXXXXXX",
  "template_subject": "{{custom_arguments.subject_line}}",
  "template_from": "support@example.com",
  "template_from_name": "Support Team",
  "template_to": ["{{custom_arguments.recipient_email}}"],
  "template_html": "PASTE_USER_STARTER_HTML_OR_CUSTOM_STYLED_EMAIL_LAYOUT_HERE",
  "template_trigger": "api_direct",
  "custom_arguments": [
    {
      "name": "recipient_email",
      "description": "The recipient email address."
    },
    {
      "name": "subject_line",
      "description": "A concise subject line for the email."
    },
    {
      "name": "message_body",
      "description": "The full message body to send to the recipient."
    }
  ]
}
```

---

## Trigger: `no_trigger`

### Source input data

No event input data.

Use this for drafts or templates used by an external process.

### Recommended Handlebars

Avoid relying on event fields. Use static content or `custom_data`.

```handlebars
<p>{{custom_data.preview_text}}</p>
```

---

## Trigger: `ai_memo_create_success`

**Input data JSON:** [AI memo object](https://revcent.com/documentation/files/email_template/input_data/ai_memo.json)

### Source input data

AI Memo JSON.

The KB example includes fields such as:

- `id`
- `created_date_unix`
- `updated_date_unix`
- `subject`
- `message`
- `status`
- `source_type`
- `item_type`
- `item_id`
- `ai_assistant.name`
- `ai_assistant.id`
- `ai_thread.id`

### Recommended Handlebars

```handlebars
<h1>{{subject}}</h1>
<p>{{message}}</p>
<p>Assistant: {{ai_assistant.name}}</p>
<p>Created: {{formatDate created_date_unix 'MM/DD/YYYY hh:mm:ssa'}}</p>
```

---

## Trigger: `customer_create_success`

**Input data JSON:** [customer object](https://revcent.com/documentation/files/email_template/input_data/customer.json)

### Source input data

Customer JSON.

Important path behavior:

- Customer fields are top-level.
- Use `{{first_name}}`, `{{last_name}}`, and `{{email}}`.
- Do not assume `{{customer.first_name}}` exists for this trigger.

Common fields from the KB example include:

- `id`
- `first_name`
- `last_name`
- `email`
- `company`
- `address_line_1`
- `address_line_2`
- `city`
- `country`
- `created_date_unix`
- `enabled`
- `blocked`
- `campaign_id`
- `campaign_name`
- `customer_card`
- `customer_group`
- `metadata`
- `lifetime_value`

### Recommended Handlebars

```handlebars
<p>Welcome {{first_name}} {{last_name}}.</p>
<p>Your account email is {{email}}.</p>
```

---

## Trigger: `pending_refund_create_success`

**Input data JSON:** [pending refund object](https://revcent.com/documentation/files/email_template/input_data/pending_refund.json)

### Source input data

Pending Refund JSON.

Common examples from the KB:

```handlebars
{{amount}}
{{formatCurrency amount}}
{{customer.first_name}}
```

Use this when notifying internal teams or customers that a pending refund was created.

### Recommended Handlebars

```handlebars
<p>A pending refund was created for {{customer.first_name}}.</p>
<p>Refund amount: {{formatCurrency amount}}</p>
```

---

## Trigger: `sale_create_success`

**Input data JSON:** [sale object](https://revcent.com/documentation/files/email_template/input_data/sale.json)

### Source input data

Sale JSON.

Common examples from the KB:

```handlebars
{{amount_gross}}
{{formatCurrency amount_gross}}
{{customer.first_name}}
```

Common fields in the KB Sale example include:

- `amount_captured`
- `amount_discounted`
- `amount_fees`
- `amount_gross`
- `amount_net`
- `amount_original_total`
- `amount_refunded`
- `amount_remaining`
- `amount_total`
- `campaign_id`
- `campaign_name`
- `customer`
- `metadata`
- `products_detailed`
- related transaction, shipping, subscription, trial, and tax data depending on the sale

### Recommended Handlebars

```handlebars
<p>Hi {{customer.first_name}},</p>
<p>Thanks for your order. Your total was {{formatCurrency amount_total}}.</p>

{{#if products_detailed}}
<ul>
{{#each products_detailed}}
  <li>{{name}} — {{formatCurrency total_amount}}</li>
{{/each}}
</ul>
{{/if}}
```

---

## Trigger: `shipping_item_shipped`

**Input data JSON:** [shipping object](https://revcent.com/documentation/files/email_template/input_data/shipping.json)

### Source input data

Shipping JSON.

Common examples from the KB:

```handlebars
{{amount_gross}}
{{formatCurrency amount_gross}}
```

Use this for shipment notifications after a shipment is marked as shipped.

### Recommended Handlebars

```handlebars
<p>Your order has shipped.</p>

{{#if tracking_number}}
  <p>Tracking number: {{tracking_number}}</p>
{{/if}}

{{#if tracking_url}}
  <p><a href="{{tracking_url}}">Track your shipment</a></p>
{{/if}}
```

### With `trigger_sources_allowed`

```json
{
  "template_trigger": "shipping_item_shipped",
  "trigger_sources_allowed": ["sale_create"]
}
```

This limits the shipped email to shipments created from sale events.

---

## Trigger: `shipping_item_delivered`

**Input data JSON:** [shipping object](https://revcent.com/documentation/files/email_template/input_data/shipping.json)

### Source input data

Shipping JSON.

Use this when a shipping provider marks the shipment as delivered.

### Recommended Handlebars

```handlebars
<p>Your shipment has been delivered.</p>
<p>Thank you for your order, {{customer.first_name}}.</p>
```

---

## Trigger: `subscription_renew_success`

**Input data JSON:** [subscription renewal object](https://revcent.com/documentation/files/email_template/input_data/subscription_renewal.json)

### Source input data

Subscription Renewal JSON.

Common examples from the KB:

```handlebars
{{amount}}
{{formatCurrency amount}}
{{customer.first_name}}
```

### Recommended Handlebars

```handlebars
<p>Hi {{customer.first_name}},</p>
<p>Your subscription renewal was successful.</p>
<p>Renewal amount: {{formatCurrency amount}}</p>
```

---

## Trigger: `subscription_renew_decline`

**Input data JSON:** [subscription renewal object](https://revcent.com/documentation/files/email_template/input_data/subscription_renewal.json)

### Source input data

Subscription Renewal JSON.

Use this when a subscription renewal payment fails due to error or decline.

### Recommended Handlebars

```handlebars
<p>Hi {{customer.first_name}},</p>
<p>We were unable to process your subscription renewal.</p>
<p>Amount attempted: {{formatCurrency amount}}</p>
```

---

## Trigger: `subscription_renewal_upcoming`

**Input data JSON:** [subscription object](https://revcent.com/documentation/files/email_template/input_data/subscription.json)

### Source input data

Subscription JSON.

Common examples from the KB:

```handlebars
{{amount}}
{{formatCurrency amount}}
{{customer.first_name}}
```

This trigger supports `timing.time_relative: "before"`.

### Recommended Handlebars

```handlebars
<p>Hi {{customer.first_name}},</p>
<p>Your subscription renewal is coming up.</p>
<p>Renewal amount: {{formatCurrency amount}}</p>
```

Recommended timing:

```json
"timing": {
  "enabled": true,
  "time_unit": "days",
  "time_value": 3,
  "time_relative": "before"
}
```

---

## Trigger: `trial_expire_success`

**Input data JSON:** [trial object](https://revcent.com/documentation/files/email_template/input_data/trial.json)

### Source input data

Trial JSON.

Common examples from the KB:

```handlebars
{{amount}}
{{formatCurrency amount}}
{{customer.first_name}}
```

Use this when a trial expiration successfully converts or processes as expected.

### Recommended Handlebars

```handlebars
<p>Hi {{customer.first_name}},</p>
<p>Your trial has ended successfully.</p>
<p>Amount: {{formatCurrency amount}}</p>
```

---

## Trigger: `trial_expire_decline`

**Input data JSON:** [trial object](https://revcent.com/documentation/files/email_template/input_data/trial.json)

### Source input data

Trial JSON.

Use this when trial expiration payment fails due to error or decline.

### Recommended Handlebars

```handlebars
<p>Hi {{customer.first_name}},</p>
<p>We were unable to process your trial expiration payment.</p>
<p>Amount attempted: {{formatCurrency amount}}</p>
```

---

## Trigger: `trial_expire_upcoming`

**Input data JSON:** [trial object](https://revcent.com/documentation/files/email_template/input_data/trial.json)

### Source input data

Trial JSON.

This trigger supports `timing.time_relative: "before"`.

### Recommended Handlebars

```handlebars
<p>Hi {{customer.first_name}},</p>
<p>Your trial is ending soon.</p>
<p>Upcoming amount: {{formatCurrency amount}}</p>
```

Recommended timing:

```json
"timing": {
  "enabled": true,
  "time_unit": "days",
  "time_value": 1,
  "time_relative": "before"
}
```

---

---

# Template Creation Workflow Guidance for MCP/AI Agents

When a user asks to create a new email template for a specific `template_trigger`, the MCP/AI agent must first ask whether the user already has starter HTML for the email.

The MCP should not begin by inventing a plain, simplistic, or minimally styled `template_html`. A production-ready `template_html` should come from one of these sources:

1. User-provided starter HTML.
2. A trigger-specific styled sample HTML body fetched from the RevCent sample-template links.
3. A fully custom styled HTML layout created only after the user explicitly asks for a custom layout or the trigger sample is unavailable.

## Starter HTML First

Before drafting or creating the template, ask the user:

```text
Do you already have starter HTML for this email template?
```

If the user provides starter HTML:

1. Use the provided HTML as the base `template_html`.
2. Preserve the user's layout, styling, images, spacing, and structure unless the user asks for changes.
3. Insert or adjust Handlebars fields only where needed for the selected `template_trigger`.
4. Cross-check every Handlebars path against the selected trigger's input-data JSON before calling `CreateEmailTemplate`.
5. Ask for any missing brand, copy, footer, compliance, or sender details needed to finalize the template.

If the user does not have starter HTML:

1. Identify the exact schema-supported `template_trigger`.
2. Select the matching styled sample HTML body link from the trigger sample-template URL pattern.
3. Fetch the matching sample HTML body.
4. Inspect the sample for any sample or placeholder logo image URL.
5. Before adapting or finalizing the sample, ask the user for a replacement logo image URL to customize the template for their brand. Do not silently keep the sample logo URL as the final logo.
6. Use the fetched styled sample as the base `template_html`.
7. Adapt the sample to the user's brand, audience, tone, products, offer, logo URL, and required Handlebars fields.
8. Do not substitute a simplistic fallback body such as a few `<p>` tags, an unstyled list, or a plain text-like HTML fragment as the final `template_html`.


## Sample Template Logo Replacement Requirement

When the MCP/AI uses one of the RevCent sample template HTML files as the base `template_html`, it must ask the user for a logo image URL before creating the template. This requirement exists because the sample logo URL is only a placeholder and should be replaced with a logo specific to the user or their brand.

Required behavior:

1. Detect whether the selected base HTML came from a RevCent sample template URL such as `https://revcent.com/documentation/files/email_template/samples/[trigger].txt`.
2. Inspect the fetched sample HTML for logo, brand, header, or placeholder image URLs.
3. Ask the user for their logo image URL and use it to replace the sample logo URL.
4. If the user does not have a logo image URL, ask whether they want to omit the logo, keep a clearly marked placeholder temporarily, or provide the logo later.
5. Do not create the final Email Template with an unchanged sample logo URL unless the user explicitly approves using that placeholder.
6. Include the replaced logo in the rendered preview so the user can verify that it loads and appears correctly.

## Trigger Sample HTML Body Files

For every supported trigger, a styled sample HTML body file may be available at:

```text
https://revcent.com/documentation/files/email_template/samples/[trigger].txt
```

Replace `[trigger]` with the selected `template_trigger`.

Example URLs:

```text
https://revcent.com/documentation/files/email_template/samples/sale_create_success.txt
https://revcent.com/documentation/files/email_template/samples/customer_create_success.txt
https://revcent.com/documentation/files/email_template/samples/shipping_item_shipped.txt
https://revcent.com/documentation/files/email_template/samples/subscription_renewal_upcoming.txt
```

## Trigger-to-Sample Template Selection

Use the selected `template_trigger` to choose the sample HTML body file.

| `template_trigger` | Sample HTML body URL |
|---|---|
| `sale_create_success` | `https://revcent.com/documentation/files/email_template/samples/sale_create_success.txt` |
| `sale_create_decline` | `https://revcent.com/documentation/files/email_template/samples/sale_create_decline.txt` |
| `pending_sale_no_payment` | `https://revcent.com/documentation/files/email_template/samples/pending_sale_no_payment.txt` |
| `sentinel_alert_create_success` | `https://revcent.com/documentation/files/email_template/samples/sentinel_alert_create_success.txt` |
| `ai_memo_create_success` | `https://revcent.com/documentation/files/email_template/samples/ai_memo_create_success.txt` |
| `fraud_alert_create_success` | `https://revcent.com/documentation/files/email_template/samples/fraud_alert_create_success.txt` |
| `fraud_detection_create_success` | `https://revcent.com/documentation/files/email_template/samples/fraud_detection_create_success.txt` |
| `invoice_create_success` | `https://revcent.com/documentation/files/email_template/samples/invoice_create_success.txt` |
| `customer_create_success` | `https://revcent.com/documentation/files/email_template/samples/customer_create_success.txt` |
| `pending_refund_create_success` | `https://revcent.com/documentation/files/email_template/samples/pending_refund_create_success.txt` |
| `shipping_item_created` | `https://revcent.com/documentation/files/email_template/samples/shipping_item_created.txt` |
| `shipping_item_shipped` | `https://revcent.com/documentation/files/email_template/samples/shipping_item_shipped.txt` |
| `shipping_item_delivered` | `https://revcent.com/documentation/files/email_template/samples/shipping_item_delivered.txt` |
| `shipping_item_voided` | `https://revcent.com/documentation/files/email_template/samples/shipping_item_voided.txt` |
| `subscription_renew_success` | `https://revcent.com/documentation/files/email_template/samples/subscription_renew_success.txt` |
| `subscription_renew_decline` | `https://revcent.com/documentation/files/email_template/samples/subscription_renew_decline.txt` |
| `subscription_renewal_upcoming` | `https://revcent.com/documentation/files/email_template/samples/subscription_renewal_upcoming.txt` |
| `trial_expire_success` | `https://revcent.com/documentation/files/email_template/samples/trial_expire_success.txt` |
| `trial_expire_decline` | `https://revcent.com/documentation/files/email_template/samples/trial_expire_decline.txt` |
| `trial_expire_upcoming` | `https://revcent.com/documentation/files/email_template/samples/trial_expire_upcoming.txt` |

For `api_direct` and `no_trigger`, there is no fixed event input data. Ask for starter HTML first. If none is provided, create or select a styled email layout based on the user's stated use case, required custom arguments, brand details, and audience. Do not use a bare paragraph-only HTML fragment as the final `template_html`.

Recommended MCP behavior:

1. First identify the exact schema-supported `template_trigger` the user wants.
2. Ask whether the user already has starter HTML for the email.
3. If starter HTML is provided, use it as the base `template_html`.
4. If starter HTML is not provided and the trigger is event-based, fetch the matching styled sample HTML body file from `https://revcent.com/documentation/files/email_template/samples/[trigger].txt`.
5. If the sample file is unavailable, empty, or not styled enough for production use, explain that no suitable styled sample was available and create a styled, table-based email layout using the trigger's input-data JSON.
6. Adapt the chosen base HTML to the user's brand, audience, tone, products, offer, and required Handlebars fields.
7. Cross-check all Handlebars paths against the selected trigger's input-data JSON file before calling `CreateEmailTemplate`.
8. Do not put simplistic example snippets into `template_html` in request examples or final tool calls.

Important: the sample HTML is a starting point, not final production copy. The MCP should improve it for the user's actual brand and use case.

## Template HTML Quality Requirements

The final `template_html` should be styled and suitable for an email client. Avoid using low-fidelity HTML as final `template_html`, including:

- A single paragraph or sequence of bare `<p>` tags.
- Unstyled `<ul>` or `<li>` product lists as the primary layout.
- Plain text wrapped in HTML tags.
- Placeholder-only layouts with no header, body hierarchy, call-to-action area, or footer.
- Simplistic examples copied from documentation sections that are intended only to explain Handlebars paths.

A suitable `template_html` should generally include:

- Table-based or otherwise email-client-safe layout.
- Inline styles or email-compatible styling.
- A clear header or brand area.
- Preview or intro copy where appropriate.
- Main content sections tailored to the selected trigger.
- A clear call-to-action when relevant.
- Footer, support, and compliance text where appropriate.
- Responsive-friendly width and spacing.

## Branding Asset and Copy Collection

Before finalizing `template_html`, the MCP should strongly encourage the user to provide replacement branding assets and text. This is especially important when the trigger sample contains placeholder logos, generic headings, generic support text, default product messaging, or placeholder visual elements.

The MCP should proactively request, when relevant:

- Replacement logo image URL or uploaded logo file.
- Brand name and sender display name.
- Brand colors, including primary button color and background/accent colors.
- Header text, preview text, and hero copy.
- Footer text, company address, support email, support phone, and unsubscribe/compliance language when applicable.
- Product-specific language, offer text, refund/shipping policy text, renewal terms, or invoice payment instructions.
- Any images that should replace sample product, hero, banner, social, or trust-badge images.

If the user does not provide branding assets, the MCP may create a reasonable styled draft, but should clearly mark generic assets/copy as placeholders and avoid pretending they are final brand-approved materials.

## Rendered Email Preview Image

After drafting or modifying `template_html`, the MCP/AI must generate a visual preview image of the email as if it were rendered in an email client before calling `CreateEmailTemplate`, when the MCP client is capable of rendering or returning a preview. The goal is to let the user review layout, spacing, branding, imagery, buttons, and copy before the template is created or finalized.

The MCP/AI must not create the Email Template until the rendered preview has been shown to the user and the user has approved it, unless preview generation is not supported by the current MCP client. If preview generation is not supported, the MCP/AI must clearly tell the user that a visual preview cannot be generated in the current client and should provide the rendered/reviewable HTML or a best-effort textual preview before proceeding.

Recommended preview behavior:

1. Render the HTML body using representative sample data for the selected `template_trigger`.
2. Use the trigger input-data JSON and/or the fetched trigger sample file to choose realistic placeholder values.
3. Replace Handlebars expressions with representative preview values where possible.
4. Generate an image preview of the rendered email body.
5. Show or return the preview image to the user and ask for visual/content changes before final creation when the user is still iterating.

The preview image is for review only. The actual `CreateEmailTemplate` request must still send the Handlebars-based `template_html`, not the rendered preview HTML with sample values substituted.

When making the preview, the MCP should pay special attention to:

- Whether logos and images load correctly.
- Mobile-friendly width and spacing.
- Button readability and contrast.
- Header, body, and footer hierarchy.
- Whether dynamic fields such as customer names, totals, product rows, tracking links, invoice links, and dates appear in the expected places.
- Whether the rendered email still makes sense if optional fields are missing.

---

# CreateEmailTemplate Request Examples

These examples intentionally do not include simplistic or non-styled HTML bodies as `template_html`.

For actual `CreateEmailTemplate` calls, `template_html` must be one of:

- User-provided starter HTML adapted for the selected trigger.
- The fetched styled sample HTML body from `https://revcent.com/documentation/files/email_template/samples/[trigger].txt`.
- A custom styled, email-client-safe layout created after the user confirms they do not have starter HTML and no suitable sample is available.

Do not use bare paragraph-only examples, unstyled lists, or documentation snippets as the final `template_html`.

## Example: Sale Success Receipt

```json
{
  "name": "Sale Success - Customer Receipt",
  "description": "Sends a styled receipt to the customer after a successful sale. Uses either user-provided starter HTML or the styled sample from https://revcent.com/documentation/files/email_template/samples/sale_create_success.txt.",
  "enabled": true,
  "smtp_profile": "XXXXXXXXXXXXXXXXXXXX",
  "template_subject": "Thanks for your order, {{customer.first_name}}",
  "template_from": "support@example.com",
  "template_from_name": "Example Store",
  "template_to": ["{{customer.email}}"],
  "template_html": "PASTE_USER_STARTER_HTML_OR_FETCHED_STYLED_SAMPLE_HTML_HERE",
  "template_trigger": "sale_create_success",
  "timing": {
    "enabled": false,
    "time_unit": "hours",
    "time_value": 1,
    "time_relative": "after"
  }
}
```

## Example: Upcoming Subscription Renewal

```json
{
  "name": "Subscription Renewal Upcoming - 3 Day Reminder",
  "description": "Reminds customers three days before their subscription renews. Uses either user-provided starter HTML or the styled sample from https://revcent.com/documentation/files/email_template/samples/subscription_renewal_upcoming.txt.",
  "enabled": true,
  "smtp_profile": "XXXXXXXXXXXXXXXXXXXX",
  "template_subject": "Your subscription renews soon",
  "template_from": "billing@example.com",
  "template_from_name": "Billing Team",
  "template_to": ["{{customer.email}}"],
  "template_html": "PASTE_USER_STARTER_HTML_OR_FETCHED_STYLED_SAMPLE_HTML_HERE",
  "template_trigger": "subscription_renewal_upcoming",
  "timing": {
    "enabled": true,
    "time_unit": "days",
    "time_value": 3,
    "time_relative": "before"
  }
}
```

## Example: API Direct Template with Custom Arguments

```json
{
  "name": "API Direct - AI Personalized Email",
  "description": "Triggered by API or AI with runtime custom arguments. Ask the user for starter HTML first; if none is provided, create a styled email-client-safe layout for the use case.",
  "enabled": true,
  "smtp_profile": "XXXXXXXXXXXXXXXXXXXX",
  "template_subject": "{{custom_arguments.subject_line}}",
  "template_from": "support@example.com",
  "template_from_name": "Support Team",
  "template_to": ["{{custom_arguments.recipient_email}}"],
  "template_html": "PASTE_USER_STARTER_HTML_OR_CUSTOM_STYLED_EMAIL_LAYOUT_HERE",
  "template_trigger": "api_direct",
  "custom_data": {
    "enabled": true,
    "source_type": "json",
    "source_value": "{\"signature\":\"Thanks, Support Team\"}"
  },
  "custom_arguments": [
    {
      "name": "recipient_email",
      "description": "The recipient email address."
    },
    {
      "name": "subject_line",
      "description": "A concise subject line for this email."
    },
    {
      "name": "opening_line",
      "description": "A warm opening line personalized to the recipient."
    },
    {
      "name": "body",
      "description": "The main body of the message."
    }
  ]
}
```

---

# Output Schema

A successful `CreateEmailTemplate` response returns:

```json
{
  "api_call_id": "XXXXXXXXXXXXXXXXXXXX",
  "api_call_unix": 1740000000,
  "code": 1,
  "email_template_id": "XXXXXXXXXXXXXXXXXXXX",
  "result": "..."
}
```

Fields:

| Field | Type | Description |
|---|---:|---|
| `api_call_id` | string | 20-character API call ID. |
| `api_call_unix` | integer | Unix timestamp when the API call was initiated. |
| `code` | integer | Response code. `1` indicates success. |
| `email_template_id` | string | 20-character ID of the created Email Template. |
| `result` | string | Human-readable result message. |

---


## SMTP Profile Validation Requirement

Before attempting to create an Email Template, the MCP must verify that the account already has at least one active SMTP Profile available.

The MCP should:

1. Call the `GetSMTPProfiles` operation before collecting or validating Email Template inputs.
2. Check whether the account has one or more valid SMTP Profiles.
3. If at least one SMTP Profile exists:
   - Present the available SMTP Profiles to the user for selection.
   - Use the selected SMTP Profile ID as the `smtp_profile` field.
4. If zero SMTP Profiles exist:
   - Stop the Email Template creation workflow.
   - Inform the user that an SMTP Profile must be created first.
   - Guide the user through creating an SMTP Profile before continuing.
   - Do not attempt to call `CreateEmailTemplate` until an SMTP Profile exists.

Important behavior:

- `smtp_profile` is a required field for `CreateEmailTemplate`.
- The `smtp_profile` value must be a valid 20-character SMTP Profile ID.
- Email Templates cannot send messages without an SMTP Profile.
- The MCP should never assume a default SMTP Profile exists.
- The MCP should validate that the selected SMTP Profile is active before using it.

Recommended MCP flow:

```text
1. Call GetSMTPProfiles
2. If no SMTP Profiles exist:
   - Ask the user to create one first
   - Do not proceed with CreateEmailTemplate
3. If SMTP Profiles exist:
   - Let the user choose one
   - Continue template creation workflow
4. If using a RevCent sample template HTML body:
   - Ask the user for a replacement logo image URL
   - Replace the sample logo URL before preview/final creation
5. Generate and show a rendered template preview before CreateEmailTemplate, if the MCP client supports preview generation
6. Only call CreateEmailTemplate after the user approves the preview, unless preview generation is unsupported and the user approves proceeding without it
```


# Implementation Checklist

Before calling `CreateEmailTemplate`:

1. Call `GetSMTPProfiles` before starting the template workflow and confirm at least one SMTP Profile exists.
2. Confirm the selected SMTP Profile ID is active and exactly 20 characters.
3. Select a schema-supported `template_trigger`.
4. Confirm the trigger's source input data shape.
5. Write `template_subject` and `template_html` using Handlebars paths that exist for that trigger.
5. Use `{{email}}` for Customer trigger recipient emails, but `{{customer.email}}` for triggers where customer is nested.
6. Add `timing` only when appropriate.
7. Use `before` timing only for upcoming subscription renewal or trial expiration triggers.
8. Use `trigger_sources_allowed` only for shipped or delivered shipping triggers.
9. Add filters only when the trigger event contains the relevant campaign, product, product group, or shop context.
10. Ask whether the user already has starter HTML for the email.
11. If starter HTML is provided, use it as the base `template_html` and preserve its styling unless the user asks for changes.
12. If starter HTML is not provided for an event-based trigger, fetch and review the styled sample HTML body at `https://revcent.com/documentation/files/email_template/samples/[trigger].txt`.
13. Use the fetched styled trigger sample as the starting draft unless the user asks for a fully custom layout.
14. Do not use simplistic snippets, bare paragraph-only HTML, or unstyled examples as the final `template_html`.
15. Ask the user for replacement logos, brand images, brand colors, footer/support text, and any trigger-specific copy needed to replace generic sample content.
16. Use `custom_data` for static or function-generated reusable template data.
17. Use `custom_arguments` for API/AI direct templates that need runtime values.
18. If using one of the RevCent sample template HTML files, ask the user for a logo image URL and replace the sample logo URL before previewing or creating the template.
19. Generate a rendered image preview of the email using representative sample data before calling `CreateEmailTemplate`, if possible with the MCP client.
20. Show the preview to the user and receive approval before creating the template. If preview generation is not supported, clearly state that limitation and get user approval before proceeding.
21. Verify all recipient fields render to valid email addresses.

---


# Expanded Trigger Enum Update

The current `CreateEmailTemplate` schema supports the following `template_trigger` enum values:

```text
no_trigger
api_direct
sale_create_success
sale_create_decline
pending_sale_no_payment
sentinel_alert_create_success
ai_memo_create_success
fraud_alert_create_success
fraud_detection_create_success
invoice_create_success
customer_create_success
pending_refund_create_success
shipping_item_created
shipping_item_shipped
shipping_item_delivered
shipping_item_voided
subscription_renew_success
subscription_renew_decline
subscription_renewal_upcoming
trial_expire_success
trial_expire_decline
trial_expire_upcoming
```

The expanded values add sale decline, abandoned/pending sale, Sentinel/fraud, invoice, and additional shipping lifecycle triggers.

## Expanded Trigger-to-Input-Data Map

| `template_trigger` | Source `input_data` | Notes |
|---|---|---|
| `no_trigger` | None | Draft or external-process template. |
| `api_direct` | None by default | Use `custom_arguments`, `custom_data`, and optional item context supplied when sending. |
| `sale_create_success` | Sale object | Sale created and payment succeeded. |
| `sale_create_decline` | Sale object | Sale created, but all payment attempts failed by error or decline. |
| `pending_sale_no_payment` | Sale object | Pending sale was created but no payment attempt was made; abandoned-cart style trigger. |
| `sentinel_alert_create_success` | Sentinel object | Sentinel fraud detection occurred. |
| `fraud_alert_create_success` | Sentinel object | Sale received a fraud alert for manual review; payment was not prevented and no Fraud Detection was created. |
| `fraud_detection_create_success` | Fraud Detection object | Fraud Detection was created and payment was prevented. |
| `invoice_create_success` | Invoice object | Invoice was created with a unique URL. |
| `ai_memo_create_success` | AI Memo object | AI Assistant created an AI Memo. |
| `customer_create_success` | Customer object | Customer created via customer create method, not due to a new sale. |
| `pending_refund_create_success` | Pending Refund object | Pending refund was created. |
| `shipping_item_created` | Shipping object | Shipment was created; useful for warehouse notifications. |
| `shipping_item_shipped` | Shipping object | Shipment was shipped. |
| `shipping_item_delivered` | Shipping object | Shipment was delivered. |
| `shipping_item_voided` | Shipping object | Shipment was voided. |
| `subscription_renew_success` | Subscription Renewal object | Subscription renewal succeeded. |
| `subscription_renew_decline` | Subscription Renewal object | Subscription renewal failed by error or decline. |
| `subscription_renewal_upcoming` | Subscription object | Upcoming subscription renewal; supports `before` timing. |
| `trial_expire_success` | Trial object | Trial expired successfully. |
| `trial_expire_decline` | Trial object | Trial expiration failed by error or decline. |
| `trial_expire_upcoming` | Trial object | Upcoming trial expiration; supports `before` timing. |

## Additional Trigger Sections

### `sale_create_decline`

Uses the Sale object. Use the same general paths as `sale_create_success`, such as `{customer.first_name}`, `{customer.email}`, `{amount_total}`, and `{formatCurrency amount_total}`, but write the content for a failed payment.

```handlebars
<p>Hi {customer.first_name},</p>
<p>We were unable to complete your order.</p>
<p>Attempted total: {formatCurrency amount_total}</p>
```

### `pending_sale_no_payment`

Uses the Sale object. This is appropriate for abandoned-cart or incomplete checkout messaging.

```handlebars
<p>Hi {customer.first_name},</p>
<p>You left items in your cart.</p>
<p>Cart total: {formatCurrency amount_total}</p>

{#if products_detailed}
<ul>
{#each products_detailed}
  <li>{name} — {formatCurrency total_amount}</li>
{/each}
</ul>
{/if}
```

A typical timing configuration is after the pending sale was created:

```json
"timing": {
  "enabled": true,
  "time_unit": "hours",
  "time_value": 1,
  "time_relative": "after"
}
```

### `sentinel_alert_create_success`

Uses the Sentinel object. This is for a Sentinel fraud detection event.

```handlebars
<p>A Sentinel alert was created.</p>
<p>Review the Sentinel details in RevCent.</p>
```

Use exact Sentinel paths from the Sentinel input-data JSON when referencing detailed fields.

### `fraud_alert_create_success`

Uses the Sentinel object. This is different from `fraud_detection_create_success`: payment was not prevented, and the sale was marked with a fraud alert for manual review.

```handlebars
<p>A fraud alert was added to a sale.</p>
<p>Manual review is recommended.</p>
```

### `fraud_detection_create_success`

Uses the Fraud Detection object. This means payment was prevented because a Fraud Detection was created and attached to a sale.

```handlebars
<p>A fraud detection was created.</p>
<p>Payment was prevented due to fraud detection.</p>
```

Use nested Fraud Detection paths exactly as shown in the trigger input-data JSON.

### `invoice_create_success`

Uses the Invoice object. Use this to send an invoice email or notify internal teams that an invoice was generated.

```handlebars
<p>An invoice has been created.</p>

{#if customer.first_name}
<p>Customer: {customer.first_name} {customer.last_name}</p>
{/if}

{#if invoice_url}
<p><a href="{invoice_url}">View invoice</a></p>
{/if}
```

Confirm the exact invoice URL field name from the Invoice input-data JSON before using it in production.

### `shipping_item_created`

Uses the Shipping object. Useful for warehouse, fulfillment, or operational notifications.

```handlebars
<p>A shipment was created.</p>

{#if customer.first_name}
<p>Customer: {customer.first_name} {customer.last_name}</p>
{/if}
```

### `shipping_item_voided`

Uses the Shipping object. Use for internal shipment void alerts or customer-facing shipment cancellation notices.

```handlebars
<p>A shipment was voided.</p>

{#if customer.first_name}
<p>Customer: {customer.first_name} {customer.last_name}</p>
{/if}

{#if tracking_number}
<p>Tracking number: {tracking_number}</p>
{/if}
```

## Timing Notes for Expanded Triggers

- `api_direct` should be immediate and should not use timing.
- `subscription_renewal_upcoming` and `trial_expire_upcoming` are the triggers where `time_relative: "before"` applies.
- Most other event triggers can use `time_relative: "after"` when delayed delivery is desired.
- `pending_sale_no_payment` commonly uses delayed `after` timing for abandoned-cart style messaging.

## `trigger_sources_allowed` Reminder

`trigger_sources_allowed` still only applies to:

- `shipping_item_shipped`
- `shipping_item_delivered`

Allowed values remain:

```text
sale_create
subscription_renew
trial_expire
```


---
Document Parent Directory
* [Operations](https://revcent.com/documentation/markdown/mcp/operation/index.md) - AI/MCP details and overviews for operations available within the RevCent MCP.