Templates
Create, version, and publish email templates with approval workflows and lint checks.
Templates define the structure and content of your outbound emails. Each template has versioned content, automatic linting, and optional approval workflows.
Creating a template
curl -X POST https://api.molted.email/v1/templates \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"tenantId": "tenant-abc",
"slug": "order-confirmation",
"name": "Order Confirmation",
"type": "transactional",
"content": {
"subjectTemplate": "Your order {{orderId}} has been confirmed",
"htmlTemplate": "<h1>Order Confirmed</h1><p>Hi {{customerName}}, your order is on its way.</p>",
"textTemplate": "Order Confirmed. Hi {{customerName}}, your order is on its way."
},
"autoPublish": true
}'Request body
| Field | Type | Required | Description |
|---|---|---|---|
tenantId | string | Yes | Your tenant identifier. |
slug | string | Yes | URL-friendly identifier (e.g. order-confirmation). |
name | string | Yes | Human-readable template name. |
type | string | No | transactional or marketing. Defaults to transactional. |
approvalRequired | boolean | No | Whether publishing requires approval. Default false. |
content | object | No | Initial template content (see below). |
autoPublish | boolean | No | If true and content is provided, publishes immediately after creation. |
Content fields
| Field | Type | Required | Description |
|---|---|---|---|
subjectTemplate | string | Yes | Subject line with variable placeholders. |
htmlTemplate | string | Yes | HTML body with variable placeholders. |
textTemplate | string | No | Plain text fallback body. |
variables | array | No | Variable definitions for validation. |
Variables use double curly brace syntax: {{variableName}}.
Listing templates
curl https://api.molted.email/v1/templates?tenantId=tenant-abc \
-H "Authorization: Bearer YOUR_API_KEY"Returns templates with their current version number and lint status.
Getting a template
curl https://api.molted.email/v1/templates/TEMPLATE_ID \
-H "Authorization: Bearer YOUR_API_KEY"Returns the template with its current version's full content (subject, HTML, text templates, variables, and lint results).
Versioning
Templates are versioned. Each update creates a new version that must be published before it takes effect.
Adding a new version
curl -X POST https://api.molted.email/v1/templates/TEMPLATE_ID/versions \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"subjectTemplate": "Updated: Your order {{orderId}}",
"htmlTemplate": "<h1>Order Update</h1><p>Hi {{customerName}}.</p>"
}'New versions are automatically linted on creation. The lint results are stored with the version.
Publishing a version
curl -X POST https://api.molted.email/v1/templates/TEMPLATE_ID/publish \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "requestedBy": "operator@example.com" }'If the template has approvalRequired: true, this creates a pending approval instead of publishing directly:
{
"status": "pending_approval",
"approvalId": "...",
"versionId": "..."
}Otherwise it publishes immediately:
{
"status": "published",
"versionId": "..."
}Reviewing approvals
curl -X PATCH https://api.molted.email/v1/templates/approvals/APPROVAL_ID \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"reviewedBy": "admin@example.com",
"decision": "approved",
"comment": "Looks good"
}'Set decision to approved or rejected.
Test rendering
Preview how a template renders with sample data:
curl -X POST https://api.molted.email/v1/templates/TEMPLATE_ID/render \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"payload": {
"customerName": "Jane",
"orderId": "456"
}
}'Returns the rendered subject, HTML, and text with variables substituted.
Template linting
Every version is automatically linted when created. The lint checks validate:
- Variable usage (referenced variables exist in the template)
- HTML structure
- Subject line length
Sends using templates that fail linting are blocked by the policy engine with reason template_lint_failed.
Default template
Every new tenant is provisioned with a _default transactional template. This template is used when you send without specifying a templateId, or when the specified template is not found.