Developer GuideWorking with Templates

Working with Templates

Learn how to use templates when sending emails via the FormaMail API.

Overview

Templates in FormaMail are pre-designed email and attachment formats created in the dashboard. When sending emails via API, you reference these templates by their ID and provide variables for personalization.

Template Management: Templates can be created, updated, and deleted via both the Dashboard UI and JWT-authenticated API endpoints. The Dashboard provides a visual designer for easier template creation, while the API allows programmatic management for automation and integration purposes.


How Templates Work

1. Create Templates

Templates can be created in two ways:

Option A: Dashboard (Recommended for Design)

  • Navigate to Templates in the dashboard
  • Click Create Template
  • Use the visual drag-and-drop designer
  • Define variables for dynamic content
  • Save and publish your template

See the Templates User Guide for detailed instructions.

Option B: API (For Automation)

  • Use JWT-authenticated API endpoints
  • Programmatically create and manage templates
  • Ideal for CI/CD pipelines and automated workflows
  • Requires template schema knowledge

See the API Reference - Templates for API documentation.

2. Use Templates for Sending Emails

Once templates are created, reference them in API calls:

{
  templateId: 'tmpl_welcome',  // Required - references dashboard template
  to: [
    { email: 'user@example.com', name: 'John Doe' }
  ],
  variables: {  // Fills in template placeholders
    firstName: 'John',
    companyName: 'Acme Corp'
  }
}

Template Types

FormaMail supports two types of templates:

Email Templates

Used for sending HTML emails with personalized content:

  • Text, headings, paragraphs
  • Buttons and links
  • Images and logos
  • Tables for data display
  • Conditional blocks
  • Loops for repeating content

Usage:

curl https://api.formamail.com/api/emails/send \
  -H "Authorization: Bearer fm_sk_abc123..." \
  -H "Content-Type: application/json" \
  -X POST \
  -d '{
    "templateId": "tmpl_welcome",
    "to": [{ "email": "user@example.com", "name": "John Doe" }],
    "variables": { "firstName": "John" }
  }'

Attachment Templates

Used for generating PDF and Excel files:

  • All email components plus:
  • Native charts (bar, line, pie, area, scatter) with Excel interactivity
  • Advanced table formatting with calculated columns
  • Page breaks and headers/footers

Charts in Email Templates: Charts are also available in email templates! In emails, charts are rendered as high-resolution static images via QuickCharts API. In PDF/Excel attachments, charts are rendered natively with full interactivity in Excel.

Usage:

Attachment templates are generated automatically when sending emails if the email template includes attachment references:

{
  templateId: 'tmpl_invoice_email',  // Email template
  to: [{ email: 'customer@example.com' }],
  variables: {
    invoiceNumber: '12345',
    amount: 99.99
  },
  // Attachments are auto-generated from template configuration
}

Or generate attachments directly (if template is configured for it):

{
  templateId: 'tmpl_invoice_pdf',  // Attachment template
  to: [{ email: 'customer@example.com' }],
  variables: {
    invoiceNumber: '12345',
    items: [
      { name: 'Product A', price: 49.99 },
      { name: 'Product B', price: 49.99 }
    ]
  }
}

Using Template Variables

Variable Syntax

Templates use Handlebars syntax for variables:

Hello {{firstName}}!
 
Your order #{{orderNumber}} has been confirmed.
Total: ${{orderTotal}}

Providing Variable Values

Pass variable values in the variables object:

const response = await fetch('https://api.formamail.com/api/emails/send', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${apiKey}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    templateId: 'tmpl_order_confirmation',
    to: [{ email: 'customer@example.com' }],
    variables: {
      firstName: 'John',
      orderNumber: '12345',
      orderTotal: 99.99
    }
  })
});

Variable Types

Templates can use different variable types:

TypeExampleDescription
String{{firstName}}Text values
Number{{orderTotal}}Numeric values
Boolean{{isPremium}}True/false values
Array{{#each items}}...{{/each}}Lists of items
Object{{user.name}}Nested data

Complex Variables Example

{
  templateId: 'tmpl_invoice',
  to: [{ email: 'customer@example.com' }],
  variables: {
    // Simple values
    invoiceNumber: 'INV-12345',
    issueDate: '2025-11-07',
 
    // Object values
    customer: {
      name: 'John Doe',
      company: 'Acme Corp',
      email: 'john@acme.com'
    },
 
    // Array values
    items: [
      { name: 'Product A', quantity: 2, price: 49.99 },
      { name: 'Product B', quantity: 1, price: 29.99 }
    ],
 
    // Calculated values
    subtotal: 129.97,
    tax: 13.00,
    total: 142.97
  }
}

Required vs Optional Variables

Required Variables

Templates can define required variables. If you don’t provide them, the API will return an error:

{
  "statusCode": 400,
  "code": "ERR_TMPL_004",
  "message": "Missing required template variable",
  "relatedInfo": {
    "variable": "firstName",
    "templateId": "tmpl_welcome"
  }
}

Solution: Provide all required variables:

{
  templateId: 'tmpl_welcome',
  to: [{ email: 'user@example.com' }],
  variables: {
    firstName: 'John',     // Required
    lastName: 'Doe',       // Required
    companyName: 'Acme'    // Required
  }
}

Optional Variables

Optional variables can be omitted. The template handles missing values gracefully:

Hello {{firstName}}{{#if lastName}} {{lastName}}{{/if}}!

Conditional Content

Templates support conditional blocks using Handlebars helpers:

Template Design (Dashboard)

{{#if isPremium}}
  <p>Thanks for being a premium member! You get free shipping.</p>
{{else}}
  <p>Upgrade to premium for free shipping.</p>
{{/if}}

API Usage

{
  templateId: 'tmpl_order_confirmation',
  to: [{ email: 'user@example.com' }],
  variables: {
    isPremium: true  // Controls conditional block
  }
}

Loops and Repeating Content

Templates can loop through arrays of data:

Template Design (Dashboard)

<h2>Order Items</h2>
<table>
  {{#each items}}
    <tr>
      <td>{{this.name}}</td>
      <td>{{this.quantity}}</td>
      <td>${{this.price}}</td>
    </tr>
  {{/each}}
</table>

API Usage

{
  templateId: 'tmpl_invoice',
  to: [{ email: 'customer@example.com' }],
  variables: {
    items: [
      { name: 'Product A', quantity: 2, price: 49.99 },
      { name: 'Product B', quantity: 1, price: 29.99 },
      { name: 'Product C', quantity: 3, price: 19.99 }
    ]
  }
}

Finding Template IDs

Via Dashboard

  1. Navigate to Templates in the dashboard
  2. Click on a template to view details
  3. Copy the Template ID from the details page

Template IDs follow the format: tmpl_xxxxxxxxxx

Naming Convention

Use descriptive template IDs for clarity:

  • tmpl_welcome - Welcome email for new users
  • tmpl_invoice - Invoice generation
  • tmpl_password_reset - Password reset email
  • tmpl_order_confirmation - Order confirmation

Template Errors

Template Not Found

{
  "statusCode": 404,
  "code": "ERR_TMPL_002",
  "message": "Email template not found",
  "relatedInfo": {
    "templateId": "tmpl_invalid"
  }
}

Solution: Verify the template ID exists in your dashboard.

Template Not Published

{
  "statusCode": 400,
  "code": "ERR_TMPL_003",
  "message": "Template is not published",
  "relatedInfo": {
    "templateId": "tmpl_welcome",
    "status": "draft"
  }
}

Solution: Publish the template in the dashboard before using it via API.

Missing Required Variable

{
  "statusCode": 400,
  "code": "ERR_TMPL_004",
  "message": "Missing required template variable",
  "relatedInfo": {
    "variable": "firstName",
    "templateId": "tmpl_welcome"
  }
}

Solution: Provide all required variables in the variables object.


Best Practices

1. Use Descriptive Template Names

✅ Good:

  • tmpl_welcome_new_user
  • tmpl_invoice_monthly
  • tmpl_password_reset

❌ Bad:

  • tmpl_001
  • tmpl_test
  • tmpl_email

2. Define Clear Variable Names

✅ Good:

{
  variables: {
    customerFirstName: 'John',
    orderNumber: '12345',
    orderTotal: 99.99
  }
}

❌ Bad:

{
  variables: {
    fn: 'John',
    on: '12345',
    t: 99.99
  }
}

3. Validate Variable Data

Always validate data before sending:

function validateOrderData(order) {
  if (!order.number) throw new Error('Order number required');
  if (!order.customer.email) throw new Error('Customer email required');
  if (order.items.length === 0) throw new Error('Order must have items');
  return true;
}
 
// Use it
validateOrderData(orderData);
 
await sendEmail({
  templateId: 'tmpl_order_confirmation',
  to: [{ email: orderData.customer.email }],
  variables: orderData
});

4. Use Template Versioning

When templates are updated in the dashboard, the API automatically uses the latest published version. To ensure consistency:

  • Test template changes in a non-production environment first
  • Use separate templates for different environments (e.g., tmpl_welcome_dev, tmpl_welcome_prod)
  • Document template changes in your version control system

5. Handle Missing Optional Variables

Design templates to handle missing optional variables gracefully:

{{#if companyName}}
  <p>From: {{companyName}}</p>
{{/if}}

6. Keep Templates Simple

  • Break complex emails into smaller, reusable templates
  • Use consistent naming conventions
  • Document required and optional variables
  • Test templates with various data combinations

Testing Templates

Test with Real Data

Always test templates with realistic data:

// Production-like test data
const testVariables = {
  firstName: 'John',
  lastName: 'Doe',
  orderNumber: '12345',
  items: [
    { name: 'Product A', quantity: 2, price: 49.99 },
    { name: 'Product B', quantity: 1, price: 29.99 }
  ],
  total: 129.97
};
 
// Send to test email
await sendEmail({
  templateId: 'tmpl_invoice',
  to: [{ email: 'test@yourdomain.com' }],
  variables: testVariables
});

Testing Tips

When testing templates:

  • Send to email addresses you control
  • Use the template preview in the dashboard
  • Verify all variable substitutions work correctly

See Authentication for API key details.


Common Use Cases

Welcome Email

{
  templateId: 'tmpl_welcome',
  to: [{ email: user.email, name: user.name }],
  variables: {
    firstName: user.firstName,
    dashboardUrl: 'https://app.yourdomain.com/dashboard',
    supportEmail: 'support@yourdomain.com'
  }
}

Order Confirmation

{
  templateId: 'tmpl_order_confirmation',
  to: [{ email: customer.email, name: customer.name }],
  variables: {
    orderNumber: order.number,
    orderDate: order.date,
    items: order.items,
    subtotal: order.subtotal,
    tax: order.tax,
    shipping: order.shipping,
    total: order.total,
    trackingUrl: order.trackingUrl
  }
}

Password Reset

{
  templateId: 'tmpl_password_reset',
  to: [{ email: user.email }],
  variables: {
    resetLink: `https://app.yourdomain.com/reset-password?token=${resetToken}`,
    expiresIn: '1 hour'
  }
}

Invoice with PDF Attachment

{
  templateId: 'tmpl_invoice_email',
  to: [{ email: customer.email }],
  variables: {
    invoiceNumber: invoice.number,
    customer: {
      name: customer.name,
      company: customer.company,
      email: customer.email
    },
    items: invoice.items,
    total: invoice.total
  }
  // PDF attachment is auto-generated from template configuration
}

Next Steps


Related: Sending Emails | Authentication | Templates User Guide