Skip to content
Docs

Validate and render MJML and read the MJML reference. In alpha, open to the Emailit team only.

Base URLhttps://api.emailit.com/v2AuthenticationErrorsRate limits

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.

POST/mjml/validate

Body parameters

sourcestring | objectRequired

The 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.
POST/mjml/validate
Terminal
curl -X POST https://api.emailit.com/v2/mjml/validate \
  -H "Authorization: Bearer your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "source": "<mjml>\n  <mj-body>\n    <mj-column>\n      <mj-text colour=\"#333333\">Hi {{first_name}}</mj-text>\n    </mj-column>\n  </mj-body>\n</mjml>"
  }'
JSON
{
  "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": []
    }
  ]
}

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.

POST/mjml/render

Body parameters

sourcestring | objectRequired

The 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.

variablesobject

Temple 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.

POST/mjml/render
Terminal
curl -X POST https://api.emailit.com/v2/mjml/render \
  -H "Authorization: Bearer your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "source": "<mjml><mj-head><mj-title>Welcome</mj-title><mj-preview>Your account is ready</mj-preview></mj-head><mj-body><mj-section><mj-column><mj-text>Hi {{first_name|\"there\"}}, welcome aboard.</mj-text><mj-button href=\"{{activation_url}}\">Activate account</mj-button></mj-column></mj-section></mj-body></mjml>",
    "variables": {
      "first_name": "Ada",
      "activation_url": "https://example.com/activate?token=abc123"
    }
  }'
JSON
{
  "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"
}

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.

GET/mjml/reference

Returns

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).
GET/mjml/reference
Terminal
curl https://api.emailit.com/v2/mjml/reference \
  -H "Authorization: Bearer your_api_key"
JSON
{
  "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]. …"
}

Was this page helpful?

Thanks for the feedback.

Thanks, we read every message.