Templates API
Legacy template API (deprecated, sunset 30 April 2027). Use the Studio designs API.
Templates API
Deprecated — sunset 30 April 2027. Templates are now NorthRelay Studio designs. Manage them with
/api/v1/designs(SDKclient.designs, MCP*_email_design*tools). Every template id below is also a design id, and sending withtemplateIdthroughPOST /api/v1/emails/sendis not deprecated. Until the sunset these endpoints keep working as adapters: reads return the template's live release, and writes publish immediately. Responses carryDeprecation: true,SunsetandLink: </api/v1/designs>; rel="successor-version"headers.
Templates let you define reusable email layouts with dynamic variables. Use Handlebars-style {{variable}} syntax for personalization. Templates can be referenced by ID when sending emails, keeping your sending code clean and your email content centrally managed.
Template import/render requests accept at most 8 MiB of JSON. Imported HTML/text fields and MJML source are limited to 1 MiB each; MJML compilation requests allow 2 MiB of JSON for encoding overhead. Imports accept up to 100 templates with up to 500 blocks each. MJML file includes are disabled. Read/preview operations require templates:read; imports and changes require templates:write. Oversized request bodies return HTTP 413.
MJML compilation has a five-second deadline and 4 MiB output limit. If the compiler is busy, retry shortly; reduce large templates if they exceed resource limits.
List Templates
Retrieve all templates for your account.
GET /templatesQuery Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
page | integer | 1 | Page number |
limit | integer | 25 | Items per page (max 100) |
search | string | -- | Search by template name |
Example Request
curl https://app.northrelay.ca/api/v1/templates \
-H "Authorization: Bearer nr_live_xxxxxxxxxxxx"Example Response
{
"data": [
{
"id": "tmpl_a1b2c3d4",
"name": "Welcome Email",
"subject": "Welcome to {{company_name}}, {{first_name}}!",
"html": "<h1>Welcome, {{first_name}}</h1><p>Thanks for joining {{company_name}}.</p>",
"text": "Welcome, {{first_name}}! Thanks for joining {{company_name}}.",
"variables": ["first_name", "company_name"],
"themeId": "theme_x1y2z3",
"createdAt": "2026-03-01T10:00:00.000Z",
"updatedAt": "2026-03-15T08:00:00.000Z"
}
],
"pagination": {
"page": 1,
"limit": 25,
"total": 12,
"totalPages": 1
}
}Get Template
Retrieve a single template by ID.
GET /templates/{id}Example Request
curl https://app.northrelay.ca/api/v1/templates/tmpl_a1b2c3d4 \
-H "Authorization: Bearer nr_live_xxxxxxxxxxxx"Create Template
Create a new email template.
POST /templatesRequest Body
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Template name (for internal reference) |
subject | string | Yes | Subject line; supports {{variable}} syntax |
html | string | Conditional | HTML body; at least one of html or text is required |
text | string | Conditional | Plain-text body |
themeId | string | No | Theme ID for consistent branding (header, footer, colors) |
Example Request
curl -X POST https://app.northrelay.ca/api/v1/templates \
-H "Authorization: Bearer nr_live_xxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"name": "Order Confirmation",
"subject": "Order #{{order_id}} confirmed",
"html": "<h1>Thank you, {{first_name}}!</h1><p>Your order #{{order_id}} has been confirmed.</p><p>Total: {{total}}</p>",
"text": "Thank you, {{first_name}}! Your order #{{order_id}} has been confirmed. Total: {{total}}"
}'Example Response
{
"id": "tmpl_e5f6g7h8",
"name": "Order Confirmation",
"subject": "Order #{{order_id}} confirmed",
"html": "<h1>Thank you, {{first_name}}!</h1><p>Your order #{{order_id}} has been confirmed.</p><p>Total: {{total}}</p>",
"text": "Thank you, {{first_name}}! Your order #{{order_id}} has been confirmed. Total: {{total}}",
"variables": ["order_id", "first_name", "total"],
"themeId": null,
"createdAt": "2026-03-19T14:30:00.000Z",
"updatedAt": "2026-03-19T14:30:00.000Z"
}The variables array is automatically extracted from {{variable}} placeholders in the subject, html, and text fields.
Update Template
Update an existing template. Only the fields you include are changed.
PUT /templates/{id}Request Body
| Field | Type | Required | Description |
|---|---|---|---|
name | string | No | Updated template name |
subject | string | No | Updated subject line |
html | string | No | Updated HTML body |
text | string | No | Updated plain-text body |
themeId | string | null | No | Updated theme ID; pass null to remove |
Example Request
curl -X PUT https://app.northrelay.ca/api/v1/templates/tmpl_e5f6g7h8 \
-H "Authorization: Bearer nr_live_xxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"subject": "Order #{{order_id}} confirmed - {{company_name}}",
"themeId": "theme_x1y2z3"
}'Delete Template
Permanently delete a template. Emails that reference this template by ID will fail to send after deletion.
DELETE /templates/{id}Example Request
curl -X DELETE https://app.northrelay.ca/api/v1/templates/tmpl_e5f6g7h8 \
-H "Authorization: Bearer nr_live_xxxxxxxxxxxx"Example Response
{
"id": "tmpl_e5f6g7h8",
"deleted": true
}Preview / Render Template
Render a template with sample variables without sending an email. Useful for previewing in your application or generating HTML for approval workflows.
POST /templates/{id}/renderRequest Body
| Field | Type | Required | Description |
|---|---|---|---|
variables | Record<string, string> | No | Variable values to substitute |
Example Request
curl -X POST https://app.northrelay.ca/api/v1/templates/tmpl_e5f6g7h8/render \
-H "Authorization: Bearer nr_live_xxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"variables": {
"first_name": "Alice",
"order_id": "1234",
"total": "$49.99"
}
}'Example Response
{
"subject": "Order #1234 confirmed",
"html": "<h1>Thank you, Alice!</h1><p>Your order #1234 has been confirmed.</p><p>Total: $49.99</p>",
"text": "Thank you, Alice! Your order #1234 has been confirmed. Total: $49.99"
}Unresolved variables remain as literal {{variable_name}} in the output.
Test Send
Send a rendered template to a test address. This counts against your monthly quota.
POST /templates/{id}/testRequest Body
| Field | Type | Required | Description |
|---|---|---|---|
to | string | Yes | Recipient email address for the test |
from | EmailAddress | Yes | Sender address |
variables | Record<string, string> | No | Variable values to substitute |
Example Request
curl -X POST https://app.northrelay.ca/api/v1/templates/tmpl_e5f6g7h8/test \
-H "Authorization: Bearer nr_live_xxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"to": "test@yourdomain.com",
"from": { "email": "hello@yourdomain.com", "name": "Acme Inc" },
"variables": {
"first_name": "Test User",
"order_id": "0000",
"total": "$0.00"
}
}'Example Response
{
"id": "msg_t1e2s3t4",
"status": "queued",
"templateId": "tmpl_e5f6g7h8"
}Using Templates When Sending
Reference a template by its templateId in the Send Email or Batch Send content object:
{
"from": { "email": "hello@yourdomain.com" },
"to": [{ "email": "alice@example.com" }],
"content": {
"templateId": "tmpl_e5f6g7h8"
},
"variables": {
"first_name": "Alice",
"order_id": "1234",
"total": "$49.99"
}
}When templateId is provided, the template's subject, HTML, and text are used. The subject field in the content object is optional and overrides the template subject if provided.
Template Variables
Variables use Handlebars-style double-brace syntax: {{variable_name}}.
- Variable names are case-sensitive
- Unresolved variables are left as-is in the rendered output
- Variables work in the subject line, HTML body, and plain-text body
- In batch sends, per-recipient
variablesoverride top-levelvariables
Template Object Reference
| Field | Type | Description |
|---|---|---|
id | string | Unique template identifier |
name | string | Internal template name |
subject | string | Subject line with optional {{variables}} |
html | string | null | HTML body |
text | string | null | Plain-text body |
variables | string[] | Auto-extracted variable names |
themeId | string | null | Associated theme ID |
createdAt | string | ISO 8601 creation timestamp |
updatedAt | string | ISO 8601 last update timestamp |