Appearance
Templates
Create and manage reusable email templates with substitution. Templates let you store a subject, HTML body, and plain-text body once, then send them with dynamic per-message values.
Base URL: https://app.krafter.dev/api/v1
Variable Syntax
Templates use double curly braces for placeholders:
html
<h1>Hello, {{name}}!</h1>
<p>Your order {{order_id}} has been shipped.</p>
<p>Estimated delivery: {{delivery_date}}</p>Variable names appearing in subject, html_content, and text_content are automatically extracted by the API on create and update — you do not declare them explicitly. Variables not provided at send time are replaced with an empty string.
Create Template
Creates a new email template.
POST /templatesRequired scope: templates:manage
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | A descriptive name for the template. |
subject | string | Yes | Subject line. Supports . |
html_content | string | one-of | HTML body. Supports . At least one of html_content or text_content is required. |
text_content | string | one-of | Plain-text body. Supports . At least one of html_content or text_content is required. |
Example Request
bash
curl -X POST https://app.krafter.dev/api/v1/templates \
-H "Authorization: Bearer kr_live_abc123def456" \
-H "Content-Type: application/json" \
-d '{
"name": "Order Confirmation",
"subject": "Order {{order_id}} confirmed",
"html_content": "<h1>Thank you, {{customer_name}}!</h1><p>Your order <strong>{{order_id}}</strong> has been confirmed.</p>",
"text_content": "Thank you, {{customer_name}}!\n\nYour order {{order_id}} has been confirmed."
}'Example Response
json
// 201 Created
{
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Order Confirmation",
"subject": "Order {{order_id}} confirmed",
"html_content": "<h1>Thank you, {{customer_name}}!</h1><p>Your order <strong>{{order_id}}</strong> has been confirmed.</p>",
"text_content": "Thank you, {{customer_name}}!\n\nYour order {{order_id}} has been confirmed.",
"variables": ["customer_name", "order_id"],
"version": 1,
"created_at": "2026-01-15T10:00:00Z",
"updated_at": "2026-01-15T10:00:00Z"
}
}The variables array is automatically extracted from placeholders and sorted alphabetically.
List Templates
Returns all templates owned by the authenticated team.
GET /templatesRequired scope: templates:manage
Example Request
bash
curl https://app.krafter.dev/api/v1/templates \
-H "Authorization: Bearer kr_live_abc123def456"Example Response
json
{
"data": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Order Confirmation",
"subject": "Order {{order_id}} confirmed",
"html_content": "<h1>Thank you, {{customer_name}}!</h1>...",
"text_content": "Thank you, {{customer_name}}!...",
"variables": ["customer_name", "order_id"],
"version": 1,
"created_at": "2026-01-15T10:00:00Z",
"updated_at": "2026-01-15T10:00:00Z"
}
]
}Get Template
Returns a single template by ID, including the full HTML and text content.
GET /templates/:idRequired scope: templates:manage
Example Request
bash
curl https://app.krafter.dev/api/v1/templates/550e8400-e29b-41d4-a716-446655440000 \
-H "Authorization: Bearer kr_live_abc123def456"Example Response
json
{
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Order Confirmation",
"subject": "Order {{order_id}} confirmed",
"html_content": "<h1>Thank you, {{customer_name}}!</h1>...",
"text_content": "Thank you, {{customer_name}}!...",
"variables": ["customer_name", "order_id"],
"version": 1,
"created_at": "2026-01-15T10:00:00Z",
"updated_at": "2026-01-15T10:00:00Z"
}
}Update Template
Updates an existing template. Only the fields you include in the request body are changed. Each successful update increments version by one and re-extracts the variables array.
PATCH /templates/:idRequired scope: templates:manage
Request Body
All fields are optional.
| Field | Type | Description |
|---|---|---|
name | string | Template name. |
subject | string | Subject line. Supports . |
html_content | string | HTML body. Supports . |
text_content | string | Plain-text body. Supports . |
Example Request
bash
curl -X PATCH https://app.krafter.dev/api/v1/templates/550e8400-e29b-41d4-a716-446655440000 \
-H "Authorization: Bearer kr_live_abc123def456" \
-H "Content-Type: application/json" \
-d '{
"subject": "Your order {{order_id}} is on its way!"
}'Example Response
json
{
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Order Confirmation",
"subject": "Your order {{order_id}} is on its way!",
"html_content": "<h1>Thank you, {{customer_name}}!</h1>...",
"text_content": "Thank you, {{customer_name}}!...",
"variables": ["customer_name", "order_id"],
"version": 2,
"created_at": "2026-01-15T10:00:00Z",
"updated_at": "2026-01-15T14:30:00Z"
}
}Delete Template
Permanently deletes a template. Emails that were previously sent using this template are not affected.
DELETE /templates/:idRequired scope: templates:manage
Example Request
bash
curl -X DELETE https://app.krafter.dev/api/v1/templates/550e8400-e29b-41d4-a716-446655440000 \
-H "Authorization: Bearer kr_live_abc123def456"Example Response
json
// 200 OK
{
"data": { "deleted": true }
}Sending with Templates
POST /emails accepts a template_id plus a variables object. When template_id is supplied, Krafter looks up the template, substitutes placeholders in the template's subject, html_content, and text_content using the values from variables, and replaces the request's subject, html, and text with the rendered values.
bash
curl -X POST https://app.krafter.dev/api/v1/emails \
-H "Authorization: Bearer kr_live_abc123def456" \
-H "Content-Type: application/json" \
-d '{
"from": "orders@yourdomain.com",
"to": ["alice@example.com"],
"stream": "transactional",
"template_id": "550e8400-e29b-41d4-a716-446655440000",
"variables": {
"customer_name": "Alice",
"order_id": "ORD-1042"
}
}'When template_id is set:
- The template's
subject,html_content, andtext_contentreplace anysubject/html/textyou also send in the body. - Every
in those three fields is replaced with the matching key invariables. Missing keys become empty strings. - The template must belong to the authenticated team. A 422 error with
"Template not found"is returned otherwise.
INFO
Substitution is a literal → value string replacement. There is no expression syntax, no conditionals, and no escaping — design your templates with that in mind.