> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lettr.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Using Templates

> Send Lettr templates with substitution data, pin template versions, retrieve merge tags, and manage templates via the API in the PHP SDK.

Lettr templates let you manage email designs in the Lettr dashboard while your application provides the dynamic data. This separation means designers can update email layouts without touching application code, and developers can change data without worrying about design.

This page covers sending templates, versioning, and managing templates programmatically via the API.

## Sending with Templates

The simplest way to send a template email:

```php theme={null}
$response = $lettr->emails()->sendTemplate(
    from: 'sender@yourdomain.com',
    to: 'user@example.com',
    subject: 'Welcome!',
    templateSlug: 'welcome-email',
    substitutionData: [
        'first_name' => 'John',
        'activation_url' => 'https://example.com/activate/abc123',
    ],
);
```

The array keys correspond to merge tags in your template (e.g., `{{first_name}}`). If a required merge tag is missing from the array, the tag renders as an empty string in the sent email. See [Merge Tags & Template Language](/learn/templates/template-language) for the full syntax including conditionals and loops.

<Tip>
  Use the [Get Merge Tags](#get-merge-tags) method to retrieve the list of available merge tags for a template. This helps you ensure you're providing all required data when sending.
</Tip>

## Template Versioning

Specify a template version to use a specific iteration:

```php theme={null}
$response = $lettr->emails()->sendTemplate(
    from: 'sender@yourdomain.com',
    to: 'user@example.com',
    subject: 'Welcome!',
    templateSlug: 'welcome-email',
    templateVersion: 2,
    substitutionData: ['first_name' => 'John'],
);
```

Omit the `templateVersion` parameter to use the active (published) version. Lettr always serves the most recently published version unless you explicitly request a different one.

**When to use versioning:**

* **Production safety** — Pin to a known-good version so publishing a new draft doesn't affect live emails
* **A/B testing** — Send different versions to different cohorts and compare metrics in [Analytics](/learn/analytics/introduction)
* **Gradual rollout** — Test a new version with a subset of users before publishing it as the active version

See [Template Versions](/learn/templates/versions) for how versioning works in the Lettr dashboard.

## Using the Builder

For more control, use the email builder with templates:

```php theme={null}
$response = $lettr->emails()->send(
    $lettr->emails()->create()
        ->from('sender@yourdomain.com')
        ->to(['recipient@example.com'])
        ->subject('Your Order #{{order_id}}')
        ->useTemplate('order-confirmation', version: 1, projectId: 123)
        ->substitutionData([
            'order_id' => '12345',
            'customer_name' => 'John Doe',
            'items' => [
                ['name' => 'Product A', 'price' => 29.99],
                ['name' => 'Product B', 'price' => 49.99],
            ],
            'total' => 79.98,
        ])
);
```

The builder combines template usage with other email features like tracking, metadata, and custom headers. Use it when you need fine-grained control over the email alongside template content.

<Tip>
  You can override the template's subject line by calling `->subject()` on the builder. This is useful for adding dynamic content to subjects, like order numbers or user names.
</Tip>

## Listing Templates

Retrieve available templates via the API:

```php theme={null}
use Lettr\Dto\Template\ListTemplatesFilter;

$response = $lettr->templates()->list();

foreach ($response->templates as $template) {
    echo $template->name . ' (' . $template->slug . ')';
}

// With pagination and filtering
$filter = ListTemplatesFilter::create()
    ->projectId(123)
    ->perPage(20)
    ->page(2);

$response = $lettr->templates()->list($filter);
```

The list method returns basic template information including name, slug, and active version. Use this to build dynamic template selectors in your application or verify that templates exist before sending.

<Tip>
  Cache the template list in your application to avoid repeated API calls. Templates don't change frequently, so a cache with a 5-10 minute TTL is usually sufficient.
</Tip>

## Get Template Details

```php theme={null}
$template = $lettr->templates()->get('welcome-email');

echo $template->name;
echo $template->slug;
echo $template->html;
echo $template->activeVersion;
echo $template->versionsCount;

// With specific project
$template = $lettr->templates()->get('welcome-email', projectId: 123);
```

The `html` property contains the full HTML content of the template, including merge tags. Use this to preview templates or implement custom template editing in your application.

<Note>
  The HTML returned from the API includes Lettr's merge tag syntax. You'll need to process substitutions yourself if you want to preview with actual data — or just send a test email using the API's built-in substitution engine.
</Note>

## Get Merge Tags

Retrieve merge tags (template variables) from a template:

```php theme={null}
$response = $lettr->templates()->getMergeTags('welcome-email');

foreach ($response->mergeTags as $tag) {
    echo $tag->key;       // e.g., 'user_name'
    echo $tag->required;  // true/false
    echo $tag->type;      // e.g., 'string', 'object'

    // Nested tags (for objects)
    if ($tag->children !== null) {
        foreach ($tag->children as $child) {
            echo $child->key;
            echo $child->type;
        }
    }
}

// With specific project and version
$response = $lettr->templates()->getMergeTags(
    'welcome-email',
    projectId: 123,
    version: 2,
);
```

Merge tags define the dynamic data your template expects. The response includes:

* `key` — The merge tag name (used in `{{key}}` syntax)
* `required` — Whether the tag must be provided when sending
* `type` — Data type (string, object, array)
* `children` — Nested tags for objects and arrays

Use this method to:

* Validate that you're providing all required data before sending
* Build dynamic forms for template data input
* Generate type-safe DTOs in statically-typed languages

<Tip>
  When working with nested data structures (objects and arrays), check the `children` property to understand the full shape of the expected data. This is especially important for loop blocks that iterate over arrays.
</Tip>

## Create a Template

```php theme={null}
use Lettr\Dto\Template\CreateTemplateData;

// With HTML content
$template = $lettr->templates()->create(new CreateTemplateData(
    name: 'My Template',
    slug: 'my-template',
    projectId: 123,
    html: '<html>...</html>',   // provide html OR json, not both
));

// Or with TOPOL.io JSON format
$template = $lettr->templates()->create(new CreateTemplateData(
    name: 'My Template',
    json: '{"blocks":[]}',      // TOPOL.io editor JSON
));

echo $template->id;
echo $template->slug;
```

Creating templates programmatically is useful for:

* Migrating templates from another email service
* Generating templates from a design system or component library
* Building template management features in your application

<Warning>
  Template slugs must be unique within your account. If you try to create a template with an existing slug, the API returns a `422` validation error.
</Warning>

## Delete a Template

```php theme={null}
$lettr->templates()->delete('my-template');

// With specific project
$lettr->templates()->delete('my-template', projectId: 123);
```

<Warning>
  Deleting a template is permanent and cannot be undone. All template versions are deleted. If any emails in your application reference this template slug, they will fail to send after deletion.
</Warning>

## What's Next

<CardGroup cols={2}>
  <Card title="Topol Email Editor" icon="paintbrush" href="/learn/templates/topol-editor">
    Design templates with the visual email editor
  </Card>

  <Card title="Template Language" icon="code" href="/learn/templates/template-language">
    Learn merge tag syntax, conditionals, and loops
  </Card>

  <Card title="API Reference" icon="book" href="/api-reference/templates/list-templates">
    Complete template API reference
  </Card>
</CardGroup>
