---
title: "Compile template"
method: POST
path: "/api/templates.compile"
---

# Compile template

`POST /api/templates.compile`

Compiles an MJML template with provided data, returning the rendered HTML.
When `subject` and/or `subject_preview` are provided, they are rendered
through the same Liquid engine used at send time and returned alongside
the HTML so callers do not need to run a separate Liquid pass to preview
the subject line. Useful for previewing templates before saving.

## Request body

- CompileTemplateRequest
  - `workspace_id` string, required — The ID of the workspace
  - `message_id` string, required — Unique message ID for tracking
  - `visual_editor_tree` object, required — MJML visual editor tree structure (must have type 'mjml')
  - `subject` string — Optional email subject. When provided, it is rendered through the same Liquid engine the send path uses (with `test_data`) and the rendered result is returned as `subject` in the response. Liquid processing is skipped when `preserve_liquid` is true, `channel` is `web`, or `test_data` is empty.
  - `subject_preview` string — Optional inbox preview text (the snippet shown after the subject in most clients). Rendered through Liquid like `subject` and returned as `subject_preview` in the response.
  - `test_data` object — Data to use for Liquid templating
  - `tracking_settings` TrackingSettings
    - `enable_tracking` boolean — Whether to enable click/open tracking
    - `tracking_mode` 'inherit' | 'disabled' — Per-notification tri-state tracking preference. Absent or "inherit" follows the workspace tracking flag (the workspace flag always acts as a kill-switch and cannot be overridden). "disabled" suppresses all rewriting for this notification — no click-tracking redirect, no open pixel, and no UTM parameters — used for auth emails (e.g. Supabase magic links) whose single-use URLs must never be modified. Update semantics: an ABSENT tracking_mode field keeps the stored value (so partial edits cannot wipe an opt-out; an empty string is treated as absent); an explicit "inherit" resets the notification to follow the workspace flag; an explicit "disabled" opts it out. Note that the other tracking_settings fields (utm_*) are replaced wholesale on update — only tracking_mode has keep-when-absent semantics.
    - `endpoint` string — API endpoint for tracking redirects
    - `utm_source` string — UTM source parameter
    - `utm_medium` string — UTM medium parameter
    - `utm_campaign` string — UTM campaign parameter
    - `utm_content` string — UTM content parameter
    - `utm_term` string — UTM term parameter
    - `workspace_id` string — Workspace ID for tracking
    - `message_id` string — Message ID for tracking
  - `channel` 'email' | 'web' — Which channel this template targets. It selects the content object the template must carry: an `email` template supplies `email` and omits `web`, and a `web` template does the reverse.

## Response `200`

Template compiled successfully

- CompileTemplateResponse
  - `success` boolean — Whether compilation was successful
  - `mjml` string — Generated MJML markup
  - `html` string — Compiled HTML output
  - `subject` string — Rendered email subject. Present only when the request included a non-empty `subject`. Returned on both success and error paths so the caller can display the rendered subject alongside any compilation error.
  - `subject_preview` string — Rendered inbox preview text. Present only when the request included a non-empty `subject_preview`. Returned on both success and error paths.
  - `error` object — MJML compilation error details, if any
    - `message` string

## Other responses

- `400` — Bad request - compilation failed
- `401` — Unauthorized - invalid or missing authentication token
- `500` — Internal server error

## Changes

- **2026-07-21** `ab7f39922bbe` — 1 info
  - added the new optional request property `tracking_settings/tracking_mode`
- **2026-05-13** `1de3167ef51f` — 4 info
  - added the new optional request property `subject`
  - added the new optional request property `subject_preview`
  - added the optional property `subject` to the response with the `200` status
  - added the optional property `subject_preview` to the response with the `200` status
- **2025-12-19** `a1331825c4e5` — 3 breaking, 3 warning, 6 info
  - added the new required request property `message_id`
  - added the new required request property `visual_editor_tree`
  - added the new required request property `workspace_id`
  - removed the request property `template_content`
  - …8 more
- **2025-11-14** `940c5636d0b4` — 1 info
  - endpoint added

[Change history](https://skmtc.dev/pierre-b/apis/notifuse-api/changes/api/templates.compile/post.md)

---

[API](https://skmtc.dev/pierre-b/apis/notifuse-api.md) · [All operations](https://skmtc.dev/pierre-b/apis/notifuse-api/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/pierre-b/notifuse-api/revisions/d26605f2fc47/schema)
