Send Email in Tiptap

Send transactional emails using Tiptap JSON format (same as Lumail editor)

MethodPOST
/api/v1/emails

The TIPTAP content type uses the same JSON format as the Lumail email editor. This is ideal for programmatically generating complex email layouts with rich components like buttons, images, columns, and more.

Quick Example

curl -X POST https://lumail.io/api/v1/emails \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "to": "[email protected]",
    "subject": "Welcome!",
    "contentType": "TIPTAP",
    "content": "{\"type\":\"doc\",\"content\":[{\"type\":\"heading\",\"attrs\":{\"level\":1},\"content\":[{\"type\":\"text\",\"text\":\"Hello \"}]},{\"type\":\"paragraph\",\"content\":[{\"type\":\"text\",\"text\":\"Welcome to our platform!\"}]}]}",
    "from": "[email protected]"
  }'
import { Lumail } from "lumail";
const lumail = new Lumail({ apiKey: "YOUR_API_TOKEN" });

await lumail.emails.send({
  to: "[email protected]",
  subject: "Welcome!",
  contentType: "TIPTAP",
  content: JSON.stringify({
    type: "doc",
    content: [
      {
        type: "heading",
        attrs: { level: 1 },
        content: [{ type: "text", text: "Hello " }],
      },
      {
        type: "paragraph",
        content: [{ type: "text", text: "Welcome to our platform!" }],
      },
    ],
  }),
  from: "[email protected]",
});

JSON Structure

Tiptap uses a tree-based JSON structure:

{
  "type": "doc",
  "content": [
    {
      "type": "paragraph",
      "content": [
        {
          "type": "text",
          "text": "Hello world!"
        }
      ]
    }
  ]
}

Supported Node Types

Text Nodes

{
  "type": "paragraph",
  "content": [
    {
      "type": "text",
      "text": "Regular text"
    }
  ]
}

Headings

{
  "type": "heading",
  "attrs": { "level": 1 },
  "content": [{ "type": "text", "text": "Heading 1" }]
}

Variables

Insert subscriber data with the variable node:

{
  "type": "variable",
  "attrs": {
    "id": "name",
    "fallback": "Friend"
  }
}

Buttons

{
  "type": "button",
  "attrs": {
    "text": "Click Here",
    "url": "https://example.com",
    "variant": "filled",
    "buttonColor": "#007bff",
    "textColor": "#ffffff"
  }
}

Images

{
  "type": "image",
  "attrs": {
    "src": "https://example.com/image.png",
    "alt": "Description",
    "width": 600,
    "alignment": "center"
  }
}

Survey

One-question poll. Recipients click an answer in the inbox. Same node as the campaign editor — see Surveys for settings, filters and the workflow trigger.

{
  "type": "survey",
  "attrs": {
    "surveyId": "svy_abcdefghij",
    "question": "What should we write about next?",
    "style": "buttons",
    "allowComment": false,
    "alignment": "left",
    "buttonColor": "#000000",
    "textColor": "#ffffff",
    "options": [
      { "id": "opt_a1b2c3d4e5", "label": "Talk about AI", "emoji": "🤖" },
      { "id": "opt_f6g7h8i9j0", "label": "No AI please", "emoji": "🙅" }
    ]
  }
}
AttrRequiredValues
surveyIdyessvy_ + 10 alphanumeric characters, unique in the document
questionyes1–300 characters, no merge fields
stylenobuttons (default), yes_no, nps, emoji
optionsyes*2–8 { id, label, emoji? }. Ignored for nps (fixed nps_0nps_10)
allowCommentnotrue / false (default). Comment max 1000 characters
npsLowLabel / npsHighLabelnoAuthor captions, max 60. null translates on the vote page
alignmentnoleft (default), center, right
buttonColor / textColornoHex. Defaults black / white

surveyId is the join key for every recorded answer. Do not reuse one across campaigns. Copying a campaign regenerates it. Surveys cannot live inside a repeat block.

Spacer

{
  "type": "spacer",
  "attrs": {
    "height": 20
  }
}

Horizontal Rule

{
  "type": "horizontalRule"
}

Columns (Two-Column Layout)

{
  "type": "columns",
  "attrs": {
    "borderColor": "",
    "borderRadius": "0",
    "borderWidth": "0"
  },
  "content": [
    {
      "type": "column",
      "attrs": { "width": 50 },
      "content": [
        {
          "type": "paragraph",
          "content": [{ "type": "text", "text": "Left column" }]
        }
      ]
    },
    {
      "type": "column",
      "attrs": { "width": 50 },
      "content": [
        {
          "type": "paragraph",
          "content": [{ "type": "text", "text": "Right column" }]
        }
      ]
    }
  ]
}

Text Formatting (Marks)

Apply formatting with marks:

{
  "type": "text",
  "text": "Bold and italic",
  "marks": [{ "type": "bold" }, { "type": "italic" }]
}

Available Marks

MarkDescription
boldBold text
italicItalic text
underlineUnderlined text
strikeStrikethrough
linkHyperlink
{
  "type": "text",
  "text": "Visit our website",
  "marks": [
    {
      "type": "link",
      "attrs": {
        "href": "https://example.com",
        "target": "_blank"
      }
    }
  ]
}

Complete Example

{
  "to": "[email protected]",
  "subject": "Welcome to our platform!",
  "contentType": "TIPTAP",
  "content": {
    "type": "doc",
    "content": [
      {
        "type": "heading",
        "attrs": { "level": 1, "textAlign": "center" },
        "content": [
          { "type": "text", "text": "Welcome, " },
          {
            "type": "variable",
            "attrs": { "id": "name", "fallback": "Friend" }
          },
          { "type": "text", "text": "!" }
        ]
      },
      {
        "type": "paragraph",
        "content": [
          {
            "type": "text",
            "text": "Thanks for signing up. We're excited to have you on board."
          }
        ]
      },
      {
        "type": "spacer",
        "attrs": { "height": 20 }
      },
      {
        "type": "button",
        "attrs": {
          "text": "Get Started",
          "url": "https://example.com/dashboard",
          "variant": "filled",
          "buttonColor": "#007bff",
          "textColor": "#ffffff",
          "alignment": "center"
        }
      },
      {
        "type": "spacer",
        "attrs": { "height": 30 }
      },
      {
        "type": "horizontalRule"
      },
      {
        "type": "footer",
        "attrs": { "textAlign": "center" },
        "content": [
          {
            "type": "text",
            "text": "You received this email because you signed up on our website."
          }
        ]
      }
    ]
  },
  "from": "[email protected]",
  "preview": "Welcome to our platform"
}

Exporting from Lumail Editor

You can get the Tiptap JSON from the Lumail email editor:

  1. Create your email in the Lumail editor
  2. Open browser developer tools (F12)
  3. In the console, access the editor's getJSON() method
  4. Copy the JSON structure for API use

Automatic Features

When using Tiptap format, Lumail automatically:

  • Adds unsubscribe footer if no {{unsubscribeUrl}} is present
  • Replaces variables with subscriber data
  • Tracks opens via invisible pixel
  • Tracks clicks by wrapping links
  • Generates plain text version

Best Practices

  1. Use the Lumail editor to prototype your email structure
  2. Test with variables to ensure fallbacks work correctly
  3. Keep layouts simple for better email client compatibility
  4. Use buttons for important calls-to-action
  5. Include alt text for all images