docs/.mintlify/skills/dashboard-workflows/references/email-step.md
Email step for detailed content, formal communications, receipts.
editorType)Required properties: subject, editorType, body.
| Field | Value |
|---|---|
subject | string — email subject line |
editorType | "block" |
body | object — email body in Maily TipTap JSON format |
Required properties: subject, editorType, body.
| Field | Value |
|---|---|
subject | string — email subject line |
editorType | "html" |
body | string — email body always in HTML format. Use semantic HTML with inline styles. Structure with headings, paragraphs, and styled buttons. |
body must be valid HTML with inline styles for email client compatibility.<h1>, <h2>, <p>, <a>, <table> for layout.style="color: #333; margin: 16px 0;").{{ subscriber.firstName }}, {{ payload.variableName }}.payload.items, payload.providers), use a LiquidJS {% for %} loop to iterate over it. Never hardcode or list individual array items as separate HTML elements.{% for item in payload.items %}<p>{{ item.name }}</p>{% endfor %}
<a href="{{ payload.actionUrl }}" style="display: inline-block; padding: 12px 24px; background-color: #007bff; color: #ffffff; text-decoration: none; border-radius: 4px; font-weight: 600;">Click Here</a>
heading nodes for titles (level 1 for main, level 2 for sections).text node for body text.spacer nodes between sections (height: 16 or 24).button nodes for CTAs with good contrast colors.Maily TipTap JSON format with proper node structure is required.
Variable names in node attributes must NEVER use curly braces {{ and }}. This applies to ALL attributes across ALL node types (url, text, src, id, each, href, externalLink, etc.).
"payload.actionUrl""{{ payload.actionUrl }}"Text variables should be defined using variable nodes with an id attribute like "id": "subscriber.firstName" or "id": "payload.variableName". The aliasFor attribute is optional and should be used only when the variable is accessed inside a repeat node.
The repeat node must always have the each attribute, for example "each": "payload.items".
To access the items in the array, you must use the variable node with:
id attribute (required)aliasFor attribute (required)Rules for the variable node only when used inside a repeat node:
The id attribute must use the special prefix current., for example "id": "current.variableName".
The aliasFor attribute must consist of: <each value> + . + <variable name>, for example "aliasFor": "payload.items.variableName".
Never use any other prefix than current. in the variable node id attribute when accessing array items.
Example:
{ "type": "variable", "attrs": { "id": "current.variableName", "aliasFor": "payload.items.variableName" } }
When the payload or available variables contain an array (e.g. payload.items, payload.providers), always use a repeat node to iterate over it. Never hardcode or list individual array items as separate nodes.
Never use the current.* variable outside of the repeat node.
button nodes: when url or text holds a variable, use the bare variable name and set the corresponding boolean flag.
{ "type": "button", "attrs": { "url": "payload.actionUrl", "isUrlVariable": true } }{ "type": "button", "attrs": { "url": "{{ payload.actionUrl }}", "isUrlVariable": true } }{ "type": "button", "attrs": { "text": "payload.label", "isTextVariable": true } }image nodes: same rule — bare variable name in src or externalLink with the matching boolean flag.
{ "type": "image", "attrs": { "src": "payload.imageUrl", "isSrcVariable": true } }{ "type": "image", "attrs": { "src": "{{ payload.imageUrl }}", "isSrcVariable": true } }inlineImage nodes: same rule for src with isSrcVariable and externalLink with isExternalLinkVariable.
{ "type": "inlineImage", "attrs": { "src": "payload.imageUrl", "isSrcVariable": true } }{ "type": "inlineImage", "attrs": { "externalLink": "payload.imageUrl", "isExternalLinkVariable": true } }steps.<digest-step-id>.events
steps.digest-step.eventssteps.digest-step-2.eventsrepeat node only to iterate over the digested events payload.payload data, use the variable node with attributes:
id attribute (required):
current.payload prefix."current.payload.<variableName>". Example: "id": "current.payload.variableName".current.payload in the variable node id attribute when accessing digested events.aliasFor attribute (required):
"aliasFor": "steps.<digest-step-id>.events.payload.<variableName>"."aliasFor": "steps.digest-step.events.payload.variableName".Example:
{ "type": "variable", "attrs": { "id": "current.payload.variableName", "aliasFor": "steps.digest-step.events.payload.variableName" } }
steps.<digest-step-id>.eventCount
steps.digest-step.eventCountsteps.digest-step-2.eventCountAvailable only for steps that come after an HTTP Request step that defines a responseBodySchema. Each property from the schema becomes a variable at steps.<http-step-id>.<property>.
variable node:
id: "steps.<http-step-id>.<property>"{ "type": "variable", "attrs": { "id": "steps.fetch-user.name" } }{{ steps.fetch-user.name }}.Only properties declared in the HTTP step's
responseBodySchemaare available — do not reference arbitrary response fields.
http-request-step.md — declare responseBodySchema so an email step can read response datadigest-step.md — when an email step is preceded by a digest, use the special variables abovestep-conditions.md — gate the email on subscriber state or previous step results