NorthRelayNorthRelay
API Reference

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 (SDK client.designs, MCP *_email_design* tools). Every template id below is also a design id, and sending with templateId through POST /api/v1/emails/send is not deprecated. Until the sunset these endpoints keep working as adapters: reads return the template's live release, and writes publish immediately. Responses carry Deprecation: true, Sunset and Link: </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 /templates

Query Parameters

ParameterTypeDefaultDescription
pageinteger1Page number
limitinteger25Items per page (max 100)
searchstring--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 /templates

Request Body

FieldTypeRequiredDescription
namestringYesTemplate name (for internal reference)
subjectstringYesSubject line; supports {{variable}} syntax
htmlstringConditionalHTML body; at least one of html or text is required
textstringConditionalPlain-text body
themeIdstringNoTheme 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

FieldTypeRequiredDescription
namestringNoUpdated template name
subjectstringNoUpdated subject line
htmlstringNoUpdated HTML body
textstringNoUpdated plain-text body
themeIdstring | nullNoUpdated 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}/render

Request Body

FieldTypeRequiredDescription
variablesRecord<string, string>NoVariable 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}/test

Request Body

FieldTypeRequiredDescription
tostringYesRecipient email address for the test
fromEmailAddressYesSender address
variablesRecord<string, string>NoVariable 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 variables override top-level variables

Template Object Reference

FieldTypeDescription
idstringUnique template identifier
namestringInternal template name
subjectstringSubject line with optional {{variables}}
htmlstring | nullHTML body
textstring | nullPlain-text body
variablesstring[]Auto-extracted variable names
themeIdstring | nullAssociated theme ID
createdAtstringISO 8601 creation timestamp
updatedAtstringISO 8601 last update timestamp

On this page