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

```bash
curl -X POST https://lumail.io/api/v1/emails \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "to": "user@example.com",
    "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": "hello@yourdomain.com"
  }'
```

```typescript
import { Lumail } from "lumail";
const lumail = new Lumail({ apiKey: "YOUR_API_TOKEN" });

await lumail.emails.send({
  to: "user@example.com",
  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: "hello@yourdomain.com",
});
```

## JSON Structure

Tiptap uses a tree-based JSON structure:

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

## Supported Node Types

### Text Nodes

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

### Headings

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

### Variables

Insert subscriber data with the `variable` node:

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

### Buttons

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

### Images

```json
{
  "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](/docs/features/surveys) for settings, filters
and the workflow trigger.

```json
{
  "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": "🙅" }
    ]
  }
}
```

| Attr | Required | Values |
| ---- | -------- | ------ |
| `surveyId` | yes | `svy_` + 10 alphanumeric characters, unique in the document |
| `question` | yes | 1–300 characters, no merge fields |
| `style` | no | `buttons` (default), `yes_no`, `nps`, `emoji` |
| `options` | yes* | 2–8 `{ id, label, emoji? }`. Ignored for `nps` (fixed `nps_0`…`nps_10`) |
| `allowComment` | no | `true` / `false` (default). Comment max 1000 characters |
| `npsLowLabel` / `npsHighLabel` | no | Author captions, max 60. `null` translates on the vote page |
| `alignment` | no | `left` (default), `center`, `right` |
| `buttonColor` / `textColor` | no | Hex. 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

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

### Horizontal Rule

```json
{
  "type": "horizontalRule"
}
```

### Columns (Two-Column Layout)

```json
{
  "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:

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

### Available Marks

| Mark        | Description     |
| ----------- | --------------- |
| `bold`      | Bold text       |
| `italic`    | Italic text     |
| `underline` | Underlined text |
| `strike`    | Strikethrough   |
| `link`      | Hyperlink       |

### Link Mark

```json
{
  "type": "text",
  "text": "Visit our website",
  "marks": [
    {
      "type": "link",
      "attrs": {
        "href": "https://example.com",
        "target": "_blank"
      }
    }
  ]
}
```

## Complete Example

```json
{
  "to": "customer@example.com",
  "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": "welcome@yourcompany.com",
  "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


## API Reference
**Method:** POST
**Endpoint:** /api/v1/emails
