MJML (alpha)
Validate and render MJML and read the MJML reference. In alpha, open to the Emailit team only.
Validate MJML
Checks MJML the way a template save does (XML syntax, MJML structure, attribute types and Temple syntax) and compiles it with MJML 5.4.1. Nothing is saved. Invalid MJML still returns 200, with valid: false and the diagnostics. Requires the full scope.
See Validation for what each check covers.
/mjml/validateBody parameters
sourcestring | objectRequiredThe MJML to check: MJML markup (<mjml>…</mjml>), MJML JSON, or an Emailit MJML document, such as a template’s stored source. See Source formats. Maximum 2 MB.
Returns
Returns 200 OK with the result, even when the MJML is invalid:
| Field | Type | Description |
|---|---|---|
valid |
boolean | true when there are no error diagnostics, so a template with this source can be saved. |
mjml_version |
string | The MJML version Emailit compiles with. |
format |
string or null | How the source was read: markup or json. null when it couldn’t be read. |
diagnostics |
array | Every error, warning and info diagnostic. |
valid: true means a template with this source would be accepted. Fix the warnings too: they usually point at real problems, such as a missing <mj-title>. To get the HTML, use Render MJML.
Returns 422 with message: "Validation failed" when source is missing or blank, and 403 with error: "mjml_alpha" without MJML access.
Diagnostic object
Fields that don’t apply are left out.
| Field | Type | Description |
|---|---|---|
severity |
string | error, warning or info. Only errors make valid false. |
code |
string | A stable code, for example mjml.invalid-child, xml.unclosed-tag or temple.unclosed-if. See Diagnostic codes. |
message |
string | A readable explanation. |
line |
integer | 1-based line in the markup. Markup sources only. |
column |
integer | 1-based column in the markup. Markup sources only. |
tag |
string | The element the diagnostic is about. |
attribute |
string | The attribute the diagnostic is about. |
path |
integer[] | Child-index path from the <mjml> root. |
{
"valid": false,
"mjml_version": "5.4.1",
"format": "markup",
"diagnostics": [
{
"severity": "error",
"code": "mjml.invalid-child",
"message": "<mj-column> cannot be placed inside <mj-body>. Allowed parents: <mj-group>, <mj-section>.",
"line": 3,
"column": 6,
"tag": "mj-column",
"path": [0, 0]
},
{
"severity": "error",
"code": "mjml.unknown-attribute",
"message": "<mj-text> has no attribute colour. Did you mean color?",
"line": 4,
"column": 16,
"tag": "mj-text",
"attribute": "colour",
"path": [0, 0, 0]
},
{
"severity": "warning",
"code": "mjml.missing-title",
"message": "Add an <mj-title> to <mj-head>; clients and screen readers use it.",
"line": 1,
"column": 2,
"tag": "mjml",
"path": []
},
{
"severity": "info",
"code": "mjml.missing-preview",
"message": "Add an <mj-preview> to control the inbox preview text.",
"line": 1,
"column": 2,
"tag": "mjml",
"path": []
}
]
}{
"valid": true,
"mjml_version": "5.4.1",
"format": "markup",
"diagnostics": []
}{
"valid": false,
"mjml_version": "5.4.1",
"format": null,
"diagnostics": [
{
"severity": "error",
"code": "document.unrecognized",
"message": "Expected MJML markup (<mjml>…), MJML JSON or an Emailit MJML document."
}
]
}{
"message": "Validation failed",
"errors": {
"source": ["The source field is required."]
}
}{
"error": "mjml_alpha",
"message": "MJML is in alpha and available only to Emailit platform admins."
}Render MJML
Compiles MJML to the HTML Emailit sends, with MJML 5.4.1. With variables, the response also includes rendered_html: the HTML after Temple is applied, as one recipient would get it. Nothing is saved or sent. Requires the full scope.
This endpoint is limited to 120 requests per minute.
/mjml/renderBody parameters
sourcestring | objectRequiredThe MJML to compile: MJML markup (<mjml>…</mjml>), MJML JSON, or an Emailit MJML document, such as a template’s stored source. See Source formats. Maximum 2 MB.
variablesobjectTemple variables for rendered_html, such as first_name, or a cf object with campaign custom fields. Nothing is filled in automatically: pass the variables the sending channel would provide. See Variables by channel. Must be an object; anything else returns 400.
Returns
Returns 200 OK with the result, even when the MJML is invalid:
| Field | Type | Description |
|---|---|---|
valid |
boolean | true when there are no error diagnostics. |
mjml_version |
string | The MJML version Emailit compiles with. |
html |
string or null | The compiled HTML, with Temple tags left in place, as Emailit stores it for a template. null when the MJML has errors. |
html_bytes |
integer | UTF-8 size of html. Gmail clips messages over about 102 KB. 0 when html is null. |
diagnostics |
array | Every error, warning and info diagnostic. See Validate MJML. |
rendered_html |
string or null | html with variables applied by Temple. Only present when you send variables, and null when the MJML has errors. |
Invalid MJML returns 200 with valid: false, html: null and the diagnostics. rendered_html uses exactly the variables you send: missing variables render as empty strings or as their default, so {{first_name|"there"}} renders there. Plain text isn’t generated from MJML.
Returns 422 with message: "Validation failed" when source is missing or blank, 400 when variables isn’t an object, and 403 with error: "mjml_alpha" without MJML access.
{
"valid": true,
"mjml_version": "5.4.1",
"html": "<!doctype html>\n<html lang=\"und\" dir=\"auto\" …>…Hi {{first_name|\"there\"}}, welcome aboard.…<a href=\"{{activation_url}}\" …>…</html>\n",
"html_bytes": 5267,
"diagnostics": [],
"rendered_html": "<!doctype html>\n<html lang=\"und\" dir=\"auto\" …>…Hi Ada, welcome aboard.…<a href=\"https://example.com/activate?token=abc123\" …>…</html>\n"
}{
"valid": false,
"mjml_version": "5.4.1",
"html": null,
"html_bytes": 0,
"diagnostics": [
{
"severity": "error",
"code": "mjml.invalid-child",
"message": "<mj-column> cannot be placed inside <mj-body>. Allowed parents: <mj-group>, <mj-section>.",
"line": 3,
"column": 6,
"tag": "mj-column",
"path": [0, 0]
},
{
"severity": "error",
"code": "mjml.unknown-attribute",
"message": "<mj-text> has no attribute colour. Did you mean color?",
"line": 4,
"column": 16,
"tag": "mj-text",
"attribute": "colour",
"path": [0, 0, 0]
},
{
"severity": "warning",
"code": "mjml.missing-title",
"message": "Add an <mj-title> to <mj-head>; clients and screen readers use it.",
"line": 1,
"column": 2,
"tag": "mjml",
"path": []
},
{
"severity": "info",
"code": "mjml.missing-preview",
"message": "Add an <mj-preview> to control the inbox preview text.",
"line": 1,
"column": 2,
"tag": "mjml",
"path": []
}
],
"rendered_html": null
}{
"message": "Validation failed",
"errors": {
"source": ["The source field is required."]
}
}{
"error": "mjml_alpha",
"message": "MJML is in alpha and available only to Emailit platform admins."
}Retrieve the MJML reference
Retrieves every MJML component and attribute of the MJML version Emailit compiles with, the current editor versions, the Temple guide and authoring rules. Use it to build tooling or to give an AI model what it needs to write valid MJML templates. Requires the full scope.
The same reference is available to AI agents as the get-mjml-reference MCP tool. See MJML for AI agents.
/mjml/referenceReturns
Returns 200 OK with the reference. The example above is shortened: components lists all 36 components with all of their attributes.
| Field | Type | Description |
|---|---|---|
mjml_version |
string | The MJML version Emailit compiles with. |
document_schema_version |
integer | The current schema_version of the stored MJML document. |
editors |
object | The current version and stage (alpha, beta or stable) of mjml-code and mjml-visual. |
components |
array | Every MJML component. See below. |
temple_guide |
string | How Temple works inside MJML: variables, defaults, conditionals and campaign variables. |
rules |
string | MJML authoring rules: structure, allowed attributes and accessibility. |
reference_text |
string | The whole component reference as compact plain text, for prompts. |
Returns 403 with error: "mjml_alpha" without MJML access.
Component object
| Field | Type | Description |
|---|---|---|
tag |
string | Tag name, for example mj-button. |
label |
string | Display name. |
description |
string | What the component does. |
category |
string | root, head, layout, content, interactive, child or advanced. |
ending_tag |
boolean | true when the content is raw HTML or text (mj-text, mj-button, mj-raw, …). |
parents |
string[] | Elements this component can be placed in. |
children |
string[] | Elements this component can contain. ["*"] means any component (mj-attributes). |
attributes |
array | Attributes, each with name, type (an MJML type such as color, unit(px,%){1,4} or enum(left,center,right)) and default (null when there’s none). |
{
"mjml_version": "5.4.1",
"document_schema_version": 1,
"editors": {
"mjml-code": { "version": "0.2.0", "stage": "alpha" },
"mjml-visual": { "version": "0.2.0", "stage": "alpha" }
},
"components": [
{
"tag": "mj-body",
"label": "Body",
"description": "The visible email. Holds sections, wrappers and heroes.",
"category": "root",
"ending_tag": false,
"parents": ["mjml"],
"children": ["mj-raw", "mj-section", "mj-wrapper", "mj-hero"],
"attributes": [
{ "name": "width", "type": "unit(px)", "default": "600px" },
{ "name": "background-color", "type": "color", "default": null },
{ "name": "id", "type": "string", "default": null },
{ "name": "mj-class", "type": "string", "default": null },
{ "name": "css-class", "type": "string", "default": null }
]
},
{
"tag": "mj-button",
"label": "Button",
"description": "A bulletproof call-to-action button. Content is the label.",
"category": "content",
"ending_tag": true,
"parents": ["mj-column", "mj-hero"],
"children": [],
"attributes": [
{ "name": "align", "type": "enum(left,center,right)", "default": "center" },
{ "name": "background-color", "type": "color", "default": "#414141" },
{ "name": "href", "type": "string", "default": null },
{ "name": "inner-padding", "type": "unit(px,%){1,4}", "default": "10px 25px" }
]
}
],
"temple_guide": "Temple is Emailit's templating language, evaluated per recipient at send time on the final HTML:\n- {{first_name}} inserts a variable; …",
"rules": "MJML rules:\n- Structure: <mjml> > <mj-head> (optional) + <mj-body>. …",
"reference_text": "MJML 5.4.1 component reference. Format: name=type[default]. …"
}{
"error": "mjml_alpha",
"message": "MJML is in alpha and available only to Emailit platform admins."
}