{
  "nodes": [
    {
      "id": "ea803d08-d03d-4bae-b1a1-00845dedc9d0",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -880,
        -496
      ],
      "parameters": {
        "color": 7,
        "width": 2224,
        "height": 400,
        "content": "## 1) Generate warmup conversations (daily)\nCreates friendly conversation JSON and saves it to `warmup_conversations`.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "1eb066c2-6f60-478a-864c-e4fe3562c150",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -896,
        -16
      ],
      "parameters": {
        "color": 7,
        "width": 2240,
        "height": 672,
        "content": "## 2) Build warmup queue (daily)\nPairs inboxes + assigns messages into `warmup_queue`.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "7e835764-6937-44aa-ade3-56aceed17c8e",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -928,
        720
      ],
      "parameters": {
        "color": 7,
        "width": 3168,
        "height": 736,
        "content": "## 3) Send warmup messages (hourly)\nAssigns random send times and sends/replies via Gmail.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "a5067261-6354-434f-b42b-341502ed37fc",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1376,
        -496
      ],
      "parameters": {
        "color": 7,
        "width": 1072,
        "height": 1152,
        "content": "## 4) Mark warmup emails as read (hourly)\nRemoves UNREAD and updates `marked_read` in queue.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "4e97ce7d-6c01-41b0-9717-62aff4240536",
      "name": "generate warmup conversations",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -688,
        -320
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "triggerAtHour": 6
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "a36062d6-2e20-4d39-b92c-fdcd7f731de8",
      "name": "Get warmup accounts (cold_email_accounts)",
      "type": "n8n-nodes-base.dataTable",
      "position": [
        -400,
        -320
      ],
      "parameters": {
        "operation": "get",
        "returnAll": true,
        "dataTableId": {
          "__rl": true,
          "mode": "list",
          "value": "mqNBBTqxgRm7R9v0",
          "cachedResultUrl": "/projects/gWyT6ct8nsEBW0XK/datatables/mqNBBTqxgRm7R9v0",
          "cachedResultName": "cold_email_accounts"
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "8e24409c-2c25-42f8-af46-993b196f30de",
      "name": "Build conversation generation loop",
      "type": "n8n-nodes-base.code",
      "position": [
        -144,
        -320
      ],
      "parameters": {
        "jsCode": "let daily_limit = $input.first().json.warmup_daily_limit\n\nlet simArray = []\nfor (let i = 0; i < daily_limit; i++) {\n  simArray.push({\n    index: i+1\n  })\n}\n\nreturn simArray"
      },
      "typeVersion": 2
    },
    {
      "id": "52c5312c-215c-4e20-8b83-3323f44187d4",
      "name": "Loop: generate conversations",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        176,
        -320
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "3ce03cdc-2f71-4aa3-a5bf-b098f5934c71",
      "name": "Generate conversations (OpenAI)",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "position": [
        400,
        -400
      ],
      "parameters": {
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4o-mini",
          "cachedResultName": "GPT-4O-MINI"
        },
        "options": {
          "textFormat": {
            "textOptions": {
              "type": "json_object"
            }
          }
        },
        "responses": {
          "values": [
            {
              "role": "system",
              "content": "Generate a natural, friendly email conversation between two people.\n\nRequirements:\n- Include 2 to 3 messages total always.\n- Alternate between Person A and Person B.\n- Each message MUST be self-contained as a standalone email.\n- Do NOT reference previous messages.\n- No signatures, no links, no phone numbers.\n- Tone: casual, friendly, human.\n- Add light variety like greetings, emojis, small talk, scheduling questions, etc.\n- No sales content.\n- Keep it neutral.\n- Do NOT include spammy words (\u201cfree\u201d, \u201cbuy\u201d, \u201cdiscount\u201d, etc.)\n- Output ONLY as JSON formatlike:\n\n{\nconversations: [\n  { \"sender\": \"A\", \"subject\": \"Hello!\", \"body\": \"Message text...\" },\n  { \"sender\": \"B\", \"subject\": \"Re: Hello!\", \"body\": \"Message text...\" },\n  ...\n]\n}\n"
            },
            {
              "role": "system",
              "content": "[\n  {\n    \"sender\": \"A\",\n    \"subject\": \"Quick check-in\",\n    \"body\": \"Hi! Just wanted to say hello and see how things are going on your side.\"\n  },\n  {\n    \"sender\": \"B\",\n    \"subject\": \"Re: Quick check-in\",\n    \"body\": \"Hey! Things are pretty smooth so far. Just juggling some small tasks today.\"\n  }\n]\n"
            },
            {
              "role": "system",
              "content": "[\n  {\n    \"sender\": \"A\",\n    \"subject\": \"Hello!\",\n    \"body\": \"Hey! Just touching base hope you're doing well today.\"\n  },\n  {\n    \"sender\": \"B\",\n    \"subject\": \"Re: Hello!\",\n    \"body\": \"Hi! Doing alright. Was just organizing my week. How about you?\"\n  }\n]\n"
            },
            {
              "role": "system",
              "content": "[\n  {\n    \"sender\": \"A\",\n    \"subject\": \"Hey\",\n    \"body\": \"Morning! Random thought do you drink coffee or tea? I'm trying to switch \ud83e\udd23\"\n  },\n  {\n    \"sender\": \"B\",\n    \"subject\": \"Re: Hey\",\n    \"body\": \"Hahaha I\u2019m team coffee all the way But I\u2019ve been trying tea lately too.\"\n  }\n]\n"
            },
            {
              "role": "system",
              "content": "[\n  {\n    \"sender\": \"A\",\n    \"subject\": \"Checking in\",\n    \"body\": \"Hi there, hope your day is going well so far.\"\n  },\n  {\n    \"sender\": \"B\",\n    \"subject\": \"Re: Checking in\",\n    \"body\": \"Hello! Everything is going okay here, just catching up on tasks. How about yourself?\"\n  },\n  {\n    \"sender\": \"A\",\n    \"subject\": \"Re: Checking in\",\n    \"body\": \"Pretty similar doing some small cleanups and planning out the rest of the week.\"\n  }\n]\n"
            }
          ]
        },
        "builtInTools": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2
    },
    {
      "id": "c5874af0-4e83-4919-a40a-eb251c429647",
      "name": "Format conversations for Data Table",
      "type": "n8n-nodes-base.code",
      "position": [
        752,
        -400
      ],
      "parameters": {
        "jsCode": "// Loop over input items and add a new field called 'myNewField' to the JSON of each one\nfor (const item of $input.all()) {\n  let conversation = item.json.output[0].content[0].text.conversations\n  item.json.conversation_string = JSON.stringify(conversation);\n}\n\nreturn $input.all();"
      },
      "typeVersion": 2
    },
    {
      "id": "03282eb8-d2bc-4845-b714-0ba005401d51",
      "name": "Save conversations (warmup_conversations)",
      "type": "n8n-nodes-base.dataTable",
      "position": [
        976,
        -320
      ],
      "parameters": {
        "columns": {
          "value": {
            "messages": "={{ $json.conversation_string }}"
          },
          "schema": [
            {
              "id": "messages",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "messages",
              "defaultMatch": false
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "messages"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "dataTableId": {
          "__rl": true,
          "mode": "list",
          "value": "zFEHqfRDGsYVDTxX",
          "cachedResultUrl": "/projects/gWyT6ct8nsEBW0XK/datatables/zFEHqfRDGsYVDTxX",
          "cachedResultName": "warmup_conversations"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "7420f840-f366-42e3-b154-23af9c1f289d",
      "name": "Daily trigger: build warmup queue",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -832,
        336
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "triggerAtHour": 6,
              "triggerAtMinute": 25
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "cfb4dc7d-4428-4076-b4e1-6621bab61b91",
      "name": "Get warmup accounts for queue",
      "type": "n8n-nodes-base.dataTable",
      "position": [
        -608,
        336
      ],
      "parameters": {
        "limit": {},
        "operation": "get",
        "dataTableId": {
          "__rl": true,
          "mode": "list",
          "value": "mqNBBTqxgRm7R9v0",
          "cachedResultUrl": "/projects/gWyT6ct8nsEBW0XK/datatables/mqNBBTqxgRm7R9v0",
          "cachedResultName": "cold_email_accounts"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "a9001fc2-6e13-4349-8ad1-c34476eef65a",
      "name": "Loop: build queue per inbox",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        -384,
        336
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "4044866f-0468-440b-b9fd-ee22ab4afc0a",
      "name": "Calculate daily warmup target",
      "type": "n8n-nodes-base.code",
      "position": [
        -160,
        336
      ],
      "parameters": {
        "jsCode": "const base = 5;          // starting point\nconst max = 40;          // max warm-up per inbox\nconst growth = 2;        // +2 per day\n\nconst todayCount = Math.min(\n  $json.warmup_sent_today + growth,\n  max\n);\n\nreturn [{\n  json: {\n    ...$json,\n    warmup_target_today: todayCount\n  }\n}]\n"
      },
      "typeVersion": 2
    },
    {
      "id": "28899f7f-ff7a-4f82-aba6-72047d5007c8",
      "name": "Get recipient inboxes (excluding sender)",
      "type": "n8n-nodes-base.dataTable",
      "position": [
        64,
        432
      ],
      "parameters": {
        "limit": {},
        "filters": {
          "conditions": [
            {
              "keyName": "email",
              "keyValue": "={{ $json.email }}",
              "condition": "neq"
            }
          ]
        },
        "operation": "get",
        "dataTableId": {
          "__rl": true,
          "mode": "list",
          "value": "mqNBBTqxgRm7R9v0",
          "cachedResultUrl": "/projects/gWyT6ct8nsEBW0XK/datatables/mqNBBTqxgRm7R9v0",
          "cachedResultName": "cold_email_accounts"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "2f27a0a9-f33b-4538-bc4e-8fe89bae4118",
      "name": "Pick random recipient inboxes",
      "type": "n8n-nodes-base.code",
      "position": [
        288,
        432
      ],
      "parameters": {
        "jsCode": "const sender = $(\"Calculate daily warmup target\").all()[0].json.email;\nconst target = $(\"Calculate daily warmup target\").all()[0].json.warmup_target_today;\n\n// Incoming items from Data Tables (other inboxes)\nconst recipients = $(\"Get recipient inboxes (excluding sender)\").all().map(i => i.json);\n\n// Shuffle array\nfor (let i = recipients.length - 1; i > 0; i--) {\n  const j = Math.floor(Math.random() * (i + 1));\n  [recipients[i], recipients[j]] = [recipients[j], recipients[i]];\n}\n\n// Pick target count, or all if fewer\nconst selected = recipients.slice(0, target);\n\nreturn selected.map(r => ({\n  json: {\n    inboxA: sender,\n    inboxB: r.email,\n    target\n  }\n}));\n\n"
      },
      "typeVersion": 2
    },
    {
      "id": "3e94e231-670d-49ea-98c7-1af579b2054b",
      "name": "Get conversations from table",
      "type": "n8n-nodes-base.dataTable",
      "position": [
        64,
        240
      ],
      "parameters": {
        "limit": "={{ $json.warmup_daily_limit }}",
        "operation": "get",
        "dataTableId": {
          "__rl": true,
          "mode": "list",
          "value": "zFEHqfRDGsYVDTxX",
          "cachedResultUrl": "/projects/gWyT6ct8nsEBW0XK/datatables/zFEHqfRDGsYVDTxX",
          "cachedResultName": "warmup_conversations"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "41b5e014-f181-4547-9acb-74383662de41",
      "name": "Parse conversation JSON",
      "type": "n8n-nodes-base.code",
      "position": [
        288,
        240
      ],
      "parameters": {
        "jsCode": "let items = $input.all()\nlet allmessages = []\nfor (let i = 0; i < items.length; i++) {\n  const messages = JSON.parse(items[i].json.messages || \"[]\");\n  allmessages.push({\n    conversation_id: items[i].json.id,\n    message: messages\n  })\n}\n// return messages.map(m => ({ json: m }));\nreturn allmessages"
      },
      "typeVersion": 2
    },
    {
      "id": "a8604c91-31d1-403f-bf05-2df5c1100ad1",
      "name": "Merge recipients + conversations",
      "type": "n8n-nodes-base.merge",
      "position": [
        512,
        336
      ],
      "parameters": {
        "mode": "combine",
        "options": {},
        "combineBy": "combineByPosition"
      },
      "typeVersion": 3.2
    },
    {
      "id": "574c087d-c6bf-4659-9b50-8961c8522512",
      "name": "Loop: match conversations to recipients",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        736,
        336
      ],
      "parameters": {
        "options": {
          "reset": true
        },
        "batchSize": "={{ $json.target }}"
      },
      "typeVersion": 3
    },
    {
      "id": "c1afc47c-18ea-48ca-a530-a9cd7542c739",
      "name": "Split conversation into scheduled messages",
      "type": "n8n-nodes-base.code",
      "position": [
        960,
        416
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "const message = $input.item.json.message;\nlet conversation_id = $input.item.json.conversation_id\nlet inboxA = $input.item.json.inboxA;\nlet inboxB = $input.item.json.inboxB;\n\nlet conversations = [];\nconst now = new Date();\n\nfor (let i = 0; i < message.length; i++) {\n\n  // sender / receiver\n  const isA = message[i].sender === \"A\";\n  const sender_inbox = isA ? inboxA : inboxB;\n  const receiver_inbox = isA ? inboxB : inboxA;\n\n  // Calculate scheduled_date = today + i days\n  const scheduledDateObj = new Date(now);\n  scheduledDateObj.setDate(now.getDate() + i);\n\n  const scheduledDate = scheduledDateObj.toISOString().split(\"T\")[0];\n\n  conversations.push({\n    sender_inbox,\n    receiver_inbox,\n    subject: message[i].subject,\n    body: message[i].body,\n    scheduled_date: scheduledDate,  // ONLY DATE, no time\n    scheduled_at: null,             // sender engine assigns actual time later\n    sent: false,\n    conversation_id,\n    conversation_index: i\n  });\n}\n\nreturn { conversation: conversations };\n"
      },
      "typeVersion": 2
    },
    {
      "id": "24442941-657d-4dd2-ba0d-d2bc3489deb6",
      "name": "Flatten message list",
      "type": "n8n-nodes-base.code",
      "position": [
        -160,
        48
      ],
      "parameters": {
        "jsCode": "let conversationsArray = $input.all()\nlet conversations = []\n\nfor (let i = 0; i < conversationsArray.length; i++) {\n  for (let j = 0; j < conversationsArray[i].json.conversation.length; j++) {\n  conversations.push(conversationsArray[i].json.conversation[j])\n  }\n}\n\nreturn conversations;"
      },
      "typeVersion": 2
    },
    {
      "id": "2ccfc8d7-35a1-45c9-9bad-1b5493460a66",
      "name": "Insert messages into warmup_queue",
      "type": "n8n-nodes-base.dataTable",
      "position": [
        64,
        48
      ],
      "parameters": {
        "columns": {
          "value": {
            "body": "={{ $json.body }}",
            "sent": "={{ $json.sent }}",
            "subject": "={{ $json.subject }}",
            "marked_read": false,
            "sender_inbox": "={{ $json.sender_inbox }}",
            "receiver_inbox": "={{ $json.receiver_inbox }}",
            "scheduled_date": "={{ $json.scheduled_date }}",
            "conversation_id": "={{ $json.conversation_id }}",
            "conversation_index": "={{ $json.conversation_index }}"
          },
          "schema": [
            {
              "id": "sender_inbox",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "sender_inbox",
              "defaultMatch": false
            },
            {
              "id": "receiver_inbox",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "receiver_inbox",
              "defaultMatch": false
            },
            {
              "id": "subject",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "subject",
              "defaultMatch": false
            },
            {
              "id": "body",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "body",
              "defaultMatch": false
            },
            {
              "id": "scheduled_date",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "scheduled_date",
              "defaultMatch": false
            },
            {
              "id": "scheduled_at",
              "type": "dateTime",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "scheduled_at",
              "defaultMatch": false
            },
            {
              "id": "sent",
              "type": "boolean",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "sent",
              "defaultMatch": false
            },
            {
              "id": "message_id",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "message_id",
              "defaultMatch": false
            },
            {
              "id": "thread_id",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "thread_id",
              "defaultMatch": false
            },
            {
              "id": "receiver_message_id",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "receiver_message_id",
              "defaultMatch": false
            },
            {
              "id": "receiver_thread_id",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "receiver_thread_id",
              "defaultMatch": false
            },
            {
              "id": "marked_read",
              "type": "boolean",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "marked_read",
              "defaultMatch": false
            },
            {
              "id": "conversation_id",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "conversation_id",
              "defaultMatch": false
            },
            {
              "id": "conversation_index",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "conversation_index",
              "defaultMatch": false
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "dataTableId": {
          "__rl": true,
          "mode": "list",
          "value": "JOPX8e7E4d6cjAWa",
          "cachedResultUrl": "/projects/gWyT6ct8nsEBW0XK/datatables/JOPX8e7E4d6cjAWa",
          "cachedResultName": "warmup_queue"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "c833ce57-1ea1-4f95-b215-f346a42f0eb4",
      "name": "Hourly trigger: send scheduled warmup emails",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -768,
        1024
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "hours"
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "808504b6-3b21-40e4-9fe3-a3c540680738",
      "name": "Get today unsent warmups",
      "type": "n8n-nodes-base.dataTable",
      "position": [
        -560,
        1024
      ],
      "parameters": {
        "limit": {},
        "filters": {
          "conditions": [
            {
              "keyName": "scheduled_date",
              "keyValue": "={{ $now.format('yyyy-MM-dd') }}"
            },
            {
              "keyName": "sent",
              "condition": "isFalse"
            }
          ]
        },
        "matchType": "allConditions",
        "operation": "get",
        "dataTableId": {
          "__rl": true,
          "mode": "list",
          "value": "JOPX8e7E4d6cjAWa",
          "cachedResultUrl": "/projects/gWyT6ct8nsEBW0XK/datatables/JOPX8e7E4d6cjAWa",
          "cachedResultName": "warmup_queue"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "5c1d8c50-4b08-4d68-9119-2743836a747e",
      "name": "Assign random send time (IST window)",
      "type": "n8n-nodes-base.code",
      "position": [
        -160,
        912
      ],
      "parameters": {
        "jsCode": "const startHour = 8;   // daily window start\nconst endHour = 22;    // daily window end\n\nfunction createISTDate(hour, minute = 0) {\n  const now = new Date();\n  \n  // Convert today's date to IST\n  const ist = new Date(\n    now.getFullYear(),\n    now.getMonth(),\n    now.getDate(),\n    hour,\n    minute,\n    0,\n    0\n  );\n\n  // IST \u2192 UTC\n  const utc = new Date(ist.getTime() - (5.5 * 60 * 60 * 1000));\n  return utc;\n}\n\nfunction randomTimeInWindow(startHour, endHour) {\n  const now = new Date();\n  \n  const start = createISTDate(startHour);\n  const end = createISTDate(endHour);\n  \n  // Random time between start and end\n  const randomMs = start.getTime() + Math.random() * (end.getTime() - start.getTime());\n\n  return new Date(randomMs);\n}\n\n\n// These come from DB fetch via n8n\nlet warmups = $input.all();  \n\nlet updatedRows = [];\n\nfor (let item of warmups) {\n  let row = item.json;\n\n  // Assign a random timestamp ONLY if it's scheduled for today and not assigned yet\n  if (!row.scheduled_at) {\n    row.scheduled_at = randomTimeInWindow(startHour, endHour).toISOString();\n  }\n\n  updatedRows.push(row);\n}\n\nreturn updatedRows;\n"
      },
      "typeVersion": 2
    },
    {
      "id": "5ec0eb3e-9a32-4330-99d4-72caddd3d9aa",
      "name": "Update scheduled_at in queue",
      "type": "n8n-nodes-base.dataTable",
      "position": [
        32,
        912
      ],
      "parameters": {
        "columns": {
          "value": {
            "sent": false,
            "marked_read": false,
            "scheduled_at": "={{ $json.scheduled_at }}"
          },
          "schema": [
            {
              "id": "sender_inbox",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "sender_inbox",
              "defaultMatch": false
            },
            {
              "id": "receiver_inbox",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "receiver_inbox",
              "defaultMatch": false
            },
            {
              "id": "subject",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "subject",
              "defaultMatch": false
            },
            {
              "id": "body",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "body",
              "defaultMatch": false
            },
            {
              "id": "scheduled_date",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "scheduled_date",
              "defaultMatch": false
            },
            {
              "id": "scheduled_at",
              "type": "dateTime",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "scheduled_at",
              "defaultMatch": false
            },
            {
              "id": "sent",
              "type": "boolean",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "sent",
              "defaultMatch": false
            },
            {
              "id": "message_id",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "message_id",
              "defaultMatch": false
            },
            {
              "id": "thread_id",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "thread_id",
              "defaultMatch": false
            },
            {
              "id": "receiver_message_id",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "receiver_message_id",
              "defaultMatch": false
            },
            {
              "id": "receiver_thread_id",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "receiver_thread_id",
              "defaultMatch": false
            },
            {
              "id": "marked_read",
              "type": "boolean",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "marked_read",
              "defaultMatch": false
            },
            {
              "id": "conversation_id",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "conversation_id",
              "defaultMatch": false
            },
            {
              "id": "conversation_index",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "conversation_index",
              "defaultMatch": false
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "filters": {
          "conditions": [
            {
              "keyValue": "={{ $json.id }}"
            }
          ]
        },
        "options": {},
        "operation": "update",
        "dataTableId": {
          "__rl": true,
          "mode": "list",
          "value": "JOPX8e7E4d6cjAWa",
          "cachedResultUrl": "/projects/gWyT6ct8nsEBW0XK/datatables/JOPX8e7E4d6cjAWa",
          "cachedResultName": "warmup_queue"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "d89a6fff-dd14-4dfc-939c-f327fb3021f2",
      "name": "If scheduled_at is empty",
      "type": "n8n-nodes-base.if",
      "position": [
        -368,
        1024
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "4801ab32-3dde-4236-8c5e-16b8c574ae58",
              "operator": {
                "type": "dateTime",
                "operation": "empty",
                "singleValue": true
              },
              "leftValue": "={{ $json.scheduled_at }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "80391bba-e8c0-438c-80b3-133959eda31e",
      "name": "Filter messages due now",
      "type": "n8n-nodes-base.code",
      "position": [
        208,
        1056
      ],
      "parameters": {
        "jsCode": "const now = new Date();\nlet due = [];\n\nfor (let item of $input.all()) {\n  const row = item.json;\n  if (row.scheduled_at && new Date(row.scheduled_at) <= now) {\n    due.push(row);\n  }\n}\n\nreturn due;\n"
      },
      "typeVersion": 2
    },
    {
      "id": "be7d31d6-2ab9-47d0-be06-833715ea2a54",
      "name": "Get accounts (for credentials)",
      "type": "n8n-nodes-base.dataTable",
      "position": [
        208,
        1216
      ],
      "parameters": {
        "operation": "get",
        "returnAll": true,
        "dataTableId": {
          "__rl": true,
          "mode": "list",
          "value": "mqNBBTqxgRm7R9v0",
          "cachedResultUrl": "/projects/gWyT6ct8nsEBW0XK/datatables/mqNBBTqxgRm7R9v0",
          "cachedResultName": "cold_email_accounts"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "b2d8d6b1-9568-482a-9875-9596f9ffdac1",
      "name": "Merge queue with account credentials",
      "type": "n8n-nodes-base.merge",
      "position": [
        400,
        1072
      ],
      "parameters": {
        "mode": "combine",
        "options": {
          "clashHandling": {
            "values": {
              "resolveClash": "preferInput1"
            }
          }
        },
        "advanced": true,
        "mergeByFields": {
          "values": [
            {
              "field1": "sender_inbox",
              "field2": "email"
            }
          ]
        }
      },
      "typeVersion": 3.2
    },
    {
      "id": "d133bd11-328d-49f7-a3da-d8ef3f599e90",
      "name": "Loop: send warmup message",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        592,
        1072
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "4ed85c55-ae2e-4c74-aecd-88be839f8b8d",
      "name": "If first message in thread",
      "type": "n8n-nodes-base.if",
      "position": [
        832,
        1088
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "11280a4c-bb8c-424b-8531-1bc3435d52a2",
              "operator": {
                "name": "filter.operator.equals",
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.conversation_index }}",
              "rightValue": "0"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "2d0f3169-f438-4c23-b19e-eb423e62671a",
      "name": "Send Gmail message (new thread)",
      "type": "n8n-nodes-run-node-with-credentials-x.runNodeWithCredentialsX",
      "position": [
        1136,
        992
      ],
      "parameters": {
        "nodeJson": "={\n  \"nodes\": [\n    {\n      \"parameters\": {\n        \"sendTo\": \"={{ $json.receiver_inbox }}\",\n        \"subject\": \"={{ $json.subject }}\",\n        \"emailType\": \"text\",\n        \"message\": \"={{ $json.body }}\",\n        \"options\": {\n          \"appendAttribution\": false\n        }\n      },\n      \"type\": \"n8n-nodes-base.gmail\",\n      \"typeVersion\": 2.1,\n      \"position\": [\n        1920,\n        2544\n      ],\n      \"id\": \"90be2479-0140-4ca1-b1fa-55d4339f48a8\",\n      \"name\": \"Send a message\",\n      \"webhookId\": \"98b6ca9f-c412-4aae-a114-9938a3ba94e5\",\n      \"credentials\": {\n        \"gmailOAuth2\": {\n          \"id\": \"mhyVQDjPrVLEOGCr\",\n          \"name\": \"jatin.k@get\"\n        }\n      }\n    }\n  ],\n  \"connections\": {\n    \"Send a message\": {\n      \"main\": [\n        []\n      ]\n    }\n  },\n  \"pinData\": {},\n  \"meta\": {\n    \"templateCredsSetupCompleted\": true,\n    \"instanceId\": \"f5d0c13b222abccfa4b21baa9b6cd543e62d86b4c7c9b6917990da9dc767ae69\"\n  }\n}",
        "credentialsId": "={{ $json.cred_id }}"
      },
      "typeVersion": 1
    },
    {
      "id": "610d87c3-dd31-4051-9f34-44c4cc81b483",
      "name": "Get previous message (thread context)",
      "type": "n8n-nodes-base.dataTable",
      "position": [
        1040,
        1152
      ],
      "parameters": {
        "filters": {
          "conditions": [
            {
              "keyValue": "={{ $json.id - 1 }}"
            }
          ]
        },
        "matchType": "allConditions",
        "operation": "get",
        "dataTableId": {
          "__rl": true,
          "mode": "list",
          "value": "JOPX8e7E4d6cjAWa",
          "cachedResultUrl": "/projects/gWyT6ct8nsEBW0XK/datatables/JOPX8e7E4d6cjAWa",
          "cachedResultName": "warmup_queue"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "e8bb9300-ad97-40fe-9661-339f0bca742e",
      "name": "Reply in existing Gmail thread",
      "type": "n8n-nodes-run-node-with-credentials-x.runNodeWithCredentialsX",
      "position": [
        1232,
        1152
      ],
      "parameters": {
        "nodeJson": "={\n  \"nodes\": [\n    {\n      \"parameters\": {\n        \"resource\": \"thread\",\n        \"operation\": \"reply\",\n        \"threadId\": \"={{ $json.receiver_thread_id }}\",\n        \"messageId\": \"={{ $json.receiver_thread_id }}\",\n        \"message\": \"={{ $('If first message in thread').item.json.body }}\",\n        \"options\": {}\n      },\n      \"type\": \"n8n-nodes-base.gmail\",\n      \"typeVersion\": 2.1,\n      \"position\": [\n        1920,\n        2736\n      ],\n      \"id\": \"d09a475e-785d-4311-b877-9fd665fbfa76\",\n      \"name\": \"Reply to a message\",\n      \"webhookId\": \"aeface07-8c1d-471c-84cb-c7b796a734f6\",\n      \"credentials\": {\n        \"gmailOAuth2\": {\n          \"id\": \"mhyVQDjPrVLEOGCr\",\n          \"name\": \"jatin.k@get\"\n        }\n      },\n      \"onError\": \"continueErrorOutput\"\n    }\n  ],\n  \"connections\": {\n    \"Reply to a message\": {\n      \"main\": [\n        [],\n        []\n      ]\n    }\n  },\n  \"pinData\": {},\n  \"meta\": {\n    \"templateCredsSetupCompleted\": true,\n    \"instanceId\": \"f5d0c13b222abccfa4b21baa9b6cd543e62d86b4c7c9b6917990da9dc767ae69\"\n  }\n}",
        "credentialsId": "={{ $('If first message in thread').item.json.cred_id }}"
      },
      "typeVersion": 1
    },
    {
      "id": "193aaa95-df1f-4446-bae1-cdaf3fca7db9",
      "name": "Label sent warmup email",
      "type": "n8n-nodes-run-node-with-credentials-x.runNodeWithCredentialsX",
      "position": [
        1472,
        1072
      ],
      "parameters": {
        "nodeJson": "={\n  \"nodes\": [\n    {\n      \"parameters\": {\n        \"operation\": \"addLabels\",\n        \"messageId\": \"={{ $json.id }}\",\n        \"labelIds\": [\n          \"IMPORTANT\",\n          \"Label_1\"\n        ]\n      },\n      \"type\": \"n8n-nodes-base.gmail\",\n      \"typeVersion\": 2.1,\n      \"position\": [\n        2144,\n        2640\n      ],\n      \"id\": \"8b7b1177-9588-41c5-bf26-90f969722730\",\n      \"name\": \"Add label to message2\",\n      \"webhookId\": \"892a0e29-d34a-4aba-a61b-f58f3c6cbeef\",\n      \"credentials\": {\n        \"gmailOAuth2\": {\n          \"id\": \"mhyVQDjPrVLEOGCr\",\n          \"name\": \"jatin.k@get\"\n        }\n      }\n    }\n  ],\n  \"connections\": {\n    \"Add label to message2\": {\n      \"main\": [\n        []\n      ]\n    }\n  },\n  \"pinData\": {},\n  \"meta\": {\n    \"templateCredsSetupCompleted\": true,\n    \"instanceId\": \"f5d0c13b222abccfa4b21baa9b6cd543e62d86b4c7c9b6917990da9dc767ae69\"\n  }\n}",
        "credentialsId": "={{ $('If first message in thread').item.json.cred_id }}"
      },
      "typeVersion": 1
    },
    {
      "id": "893a4bcf-2ffd-4e22-8b00-2e83af877181",
      "name": "Update queue: sent + message/thread IDs",
      "type": "n8n-nodes-base.dataTable",
      "position": [
        1760,
        1072
      ],
      "parameters": {
        "columns": {
          "value": {
            "sent": true,
            "thread_id": "={{ $json.threadId }}",
            "message_id": "={{ $json.id }}",
            "marked_read": false
          },
          "schema": [
            {
              "id": "sender_inbox",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "sender_inbox",
              "defaultMatch": false
            },
            {
              "id": "receiver_inbox",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "receiver_inbox",
              "defaultMatch": false
            },
            {
              "id": "subject",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "subject",
              "defaultMatch": false
            },
            {
              "id": "body",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "body",
              "defaultMatch": false
            },
            {
              "id": "scheduled_date",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "scheduled_date",
              "defaultMatch": false
            },
            {
              "id": "scheduled_at",
              "type": "dateTime",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "scheduled_at",
              "defaultMatch": false
            },
            {
              "id": "sent",
              "type": "boolean",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "sent",
              "defaultMatch": false
            },
            {
              "id": "message_id",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "message_id",
              "defaultMatch": false
            },
            {
              "id": "thread_id",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "thread_id",
              "defaultMatch": false
            },
            {
              "id": "receiver_message_id",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "receiver_message_id",
              "defaultMatch": false
            },
            {
              "id": "receiver_thread_id",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "receiver_thread_id",
              "defaultMatch": false
            },
            {
              "id": "marked_read",
              "type": "boolean",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "marked_read",
              "defaultMatch": false
            },
            {
              "id": "conversation_id",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "conversation_id",
              "defaultMatch": false
            },
            {
              "id": "conversation_index",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "conversation_index",
              "defaultMatch": false
            },
            {
              "id": "status",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "status",
              "defaultMatch": false
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "filters": {
          "conditions": [
            {
              "keyValue": "={{ $('Loop: send warmup message').item.json.id }}"
            }
          ]
        },
        "options": {},
        "operation": "update",
        "dataTableId": {
          "__rl": true,
          "mode": "list",
          "value": "JOPX8e7E4d6cjAWa",
          "cachedResultUrl": "/projects/gWyT6ct8nsEBW0XK/datatables/JOPX8e7E4d6cjAWa",
          "cachedResultName": "warmup_queue"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "82e1e8cd-49b9-45ee-bd97-be8dc5bf7a76",
      "name": "Hourly trigger: mark warmups as read",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        1408,
        -320
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "hours",
              "triggerAtMinute": 25
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "1f6525ab-531c-417b-9a19-fec4e87234ce",
      "name": "Get sent warmups to mark read",
      "type": "n8n-nodes-base.dataTable",
      "position": [
        1760,
        -416
      ],
      "parameters": {
        "limit": {},
        "filters": {
          "conditions": [
            {
              "keyName": "sent",
              "condition": "isTrue"
            },
            {
              "keyName": "marked_read",
              "condition": "isFalse"
            },
            {
              "keyName": "scheduled_at",
              "keyValue": "={{ DateTime.now().setZone('Asia/Kolkata').toISO() }}",
              "condition": "lt"
            }
          ]
        },
        "matchType": "allConditions",
        "operation": "get",
        "dataTableId": {
          "__rl": true,
          "mode": "list",
          "value": "JOPX8e7E4d6cjAWa",
          "cachedResultUrl": "/projects/gWyT6ct8nsEBW0XK/datatables/JOPX8e7E4d6cjAWa",
          "cachedResultName": "warmup_queue"
        }
      },
      "typeVersion": 1,
      "alwaysOutputData": true
    },
    {
      "id": "d5bff093-3664-41c9-bd36-f61de7f601cf",
      "name": "Loop: mark warmups read",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        1488,
        16
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "bf1eee80-b7a4-40f8-840f-ff3cd5970257",
      "name": "If warmup row exists",
      "type": "n8n-nodes-base.if",
      "position": [
        1872,
        32
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "3b61da83-92fd-42fa-a1b2-8fc743061594",
              "operator": {
                "type": "object",
                "operation": "notEmpty",
                "singleValue": true
              },
              "leftValue": "={{ $json }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "5f6a72fe-ccd2-41b2-ba3a-bb297f5a9230",
      "name": "Fetch unread messages from sender",
      "type": "n8n-nodes-run-node-with-credentials-x.runNodeWithCredentialsX",
      "position": [
        1696,
        32
      ],
      "parameters": {
        "nodeJson": "={\n  \"nodes\": [\n    {\n      \"parameters\": {\n        \"operation\": \"getAll\",\n        \"filters\": {\n          \"readStatus\": \"unread\",\n          \"sender\": \"={{ $json.sender_inbox }}\"\n        }\n      },\n      \"type\": \"n8n-nodes-base.gmail\",\n      \"typeVersion\": 2.1,\n      \"position\": [\n        -1024,\n        672\n      ],\n      \"id\": \"f3019944-af88-44b1-a81e-da273831ec8e\",\n      \"name\": \"Get many messages9\",\n      \"webhookId\": \"f70a494c-722f-4e93-adb3-a77f52ef946a\",\n      \"alwaysOutputData\": true,\n      \"credentials\": {\n        \"gmailOAuth2\": {\n          \"id\": \"mhyVQDjPrVLEOGCr\",\n          \"name\": \"jatin.k@get\"\n        }\n      }\n    }\n  ],\n  \"connections\": {\n    \"Get many messages9\": {\n      \"main\": [\n        []\n      ]\n    }\n  },\n  \"pinData\": {},\n  \"meta\": {\n    \"templateCredsSetupCompleted\": true,\n    \"instanceId\": \"f5d0c13b222abccfa4b21baa9b6cd543e62d86b4c7c9b6917990da9dc767ae69\"\n  }\n}",
        "credentialsId": "={{ $json.cred_id }}"
      },
      "typeVersion": 1
    },
    {
      "id": "9d08d6e0-f602-4982-bda4-d16d418c7661",
      "name": "Get accounts (for receiver creds)",
      "type": "n8n-nodes-base.dataTable",
      "position": [
        1760,
        -240
      ],
      "parameters": {
        "limit": {},
        "operation": "get",
        "dataTableId": {
          "__rl": true,
          "mode": "list",
          "value": "mqNBBTqxgRm7R9v0",
          "cachedResultUrl": "/projects/gWyT6ct8nsEBW0XK/datatables/mqNBBTqxgRm7R9v0",
          "cachedResultName": "cold_email_accounts"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "e48b6981-84c8-4771-b717-78a128c782ac",
      "name": "Merge receiver inbox credentials",
      "type": "n8n-nodes-base.merge",
      "position": [
        2144,
        -336
      ],
      "parameters": {
        "mode": "combine",
        "options": {},
        "advanced": true,
        "mergeByFields": {
          "values": [
            {
              "field1": "receiver_inbox",
              "field2": "email"
            }
          ]
        }
      },
      "typeVersion": 3.2
    },
    {
      "id": "4834504f-ca2c-43d5-9854-5aa405e5a16e",
      "name": "Label warmup message (receiver)",
      "type": "n8n-nodes-run-node-with-credentials-x.runNodeWithCredentialsX",
      "position": [
        2064,
        -64
      ],
      "parameters": {
        "nodeJson": "={\n  \"nodes\": [\n    {\n      \"parameters\": {\n        \"operation\": \"addLabels\",\n        \"messageId\": \"={{ $json.id }}\",\n        \"labelIds\": [\n          \"IMPORTANT\",\n          \"Label_1\"\n        ]\n      },\n      \"type\": \"n8n-nodes-base.gmail\",\n      \"typeVersion\": 2.1,\n      \"position\": [\n        -432,\n        688\n      ],\n      \"id\": \"3a58c9b3-9f7d-476d-afb6-6d7439569396\",\n      \"name\": \"Add label to message9\",\n      \"webhookId\": \"70ea19d6-af1d-48f9-9e41-ce508fd5a069\",\n      \"credentials\": {\n        \"gmailOAuth2\": {\n          \"id\": \"mhyVQDjPrVLEOGCr\",\n          \"name\": \"jatin.k@get\"\n        }\n      }\n    }\n  ],\n  \"connections\": {\n    \"Add label to message9\": {\n      \"main\": [\n        []\n      ]\n    }\n  },\n  \"pinData\": {},\n  \"meta\": {\n    \"templateCredsSetupCompleted\": true,\n    \"instanceId\": \"f5d0c13b222abccfa4b21baa9b6cd543e62d86b4c7c9b6917990da9dc767ae69\"\n  }\n}",
        "credentialsId": "={{ $('Loop Over Items5').item.json.cred_id }}"
      },
      "typeVersion": 1
    },
    {
      "id": "589ae7f2-936a-47da-b11a-37d3e1b39cf0",
      "name": "Remove UNREAD label (mark read)",
      "type": "n8n-nodes-run-node-with-credentials-x.runNodeWithCredentialsX",
      "position": [
        2240,
        -64
      ],
      "parameters": {
        "nodeJson": "={\n  \"nodes\": [\n    {\n      \"parameters\": {\n        \"operation\": \"removeLabels\",\n        \"messageId\": \"={{ $json.id }}\",\n        \"labelIds\": [\n          \"UNREAD\"\n        ]\n      },\n      \"type\": \"n8n-nodes-base.gmail\",\n      \"typeVersion\": 2.1,\n      \"position\": [\n        -208,\n        688\n      ],\n      \"id\": \"ea9d7630-707e-413b-bfd3-9d4aed0d696a\",\n      \"name\": \"Remove label from message9\",\n      \"webhookId\": \"d7b034cd-dfb1-48cb-897b-b4f8a3def8f9\",\n      \"credentials\": {\n        \"gmailOAuth2\": {\n          \"id\": \"mhyVQDjPrVLEOGCr\",\n          \"name\": \"jatin.k@get\"\n        }\n      }\n    }\n  ],\n  \"connections\": {\n    \"Remove label from message9\": {\n      \"main\": [\n        []\n      ]\n    }\n  },\n  \"pinData\": {},\n  \"meta\": {\n    \"templateCredsSetupCompleted\": true,\n    \"instanceId\": \"f5d0c13b222abccfa4b21baa9b6cd543e62d86b4c7c9b6917990da9dc767ae69\"\n  }\n}",
        "credentialsId": "={{ $('Loop Over Items5').item.json.cred_id }}"
      },
      "typeVersion": 1
    },
    {
      "id": "58afed9d-4db3-4a4f-b8a4-027d28d7a13c",
      "name": "Update queue: marked_read = true",
      "type": "n8n-nodes-base.dataTable",
      "position": [
        2240,
        368
      ],
      "parameters": {
        "columns": {
          "value": {
            "sent": true,
            "marked_read": true,
            "receiver_thread_id": "={{ $json.threadId }}",
            "receiver_message_id": "={{ $json.id }}"
          },
          "schema": [
            {
              "id": "sender_inbox",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "sender_inbox",
              "defaultMatch": false
            },
            {
              "id": "receiver_inbox",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "receiver_inbox",
              "defaultMatch": false
            },
            {
              "id": "subject",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "subject",
              "defaultMatch": false
            },
            {
              "id": "body",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "body",
              "defaultMatch": false
            },
            {
              "id": "scheduled_at",
              "type": "dateTime",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "scheduled_at",
              "defaultMatch": false
            },
            {
              "id": "sent",
              "type": "boolean",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "sent",
              "defaultMatch": false
            },
            {
              "id": "message_id",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "message_id",
              "defaultMatch": false
            },
            {
              "id": "thread_id",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "thread_id",
              "defaultMatch": false
            },
            {
              "id": "receiver_message_id",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "receiver_message_id",
              "defaultMatch": false
            },
            {
              "id": "receiver_thread_id",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "receiver_thread_id",
              "defaultMatch": false
            },
            {
              "id": "marked_read",
              "type": "boolean",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "marked_read",
              "defaultMatch": false
            },
            {
              "id": "conversation_id",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "conversation_id",
              "defaultMatch": false
            },
            {
              "id": "conversation_index",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "conversation_index",
              "defaultMatch": false
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "filters": {
          "conditions": [
            {
              "keyValue": "={{ $('Loop: mark warmups read').item.json.id }}"
            }
          ]
        },
        "options": {},
        "operation": "update",
        "dataTableId": {
          "__rl": true,
          "mode": "list",
          "value": "JOPX8e7E4d6cjAWa",
          "cachedResultUrl": "/projects/gWyT6ct8nsEBW0XK/datatables/JOPX8e7E4d6cjAWa",
          "cachedResultName": "warmup_queue"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "afa63fe5-da49-46c1-b446-6b4fdf71c904",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1696,
        -496
      ],
      "parameters": {
        "width": 720,
        "height": 448,
        "content": "## How it works\nThis workflow warms up Gmail inboxes by sending natural, non-sales email conversations between your own inboxes. It generates friendly multi-message conversations using OpenAI, stores them in `warmup_conversations`, builds a daily send plan in `warmup_queue`, and assigns randomized send times within a safe daily window. Messages are sent using the correct Gmail OAuth credential for each inbox, replies happen in the same thread, and warmup emails are automatically marked as read to mimic human inbox activity.\n\n## Setup steps\n1) Create 3 Data Tables: `cold_email_accounts`, `warmup_conversations`, `warmup_queue`\n2) Add at least 2 inboxes to `cold_email_accounts` with `email`, `cred_id`, and `warmup_daily_limit`\n3) Create one Gmail OAuth2 credential per inbox and paste the credential ID into `cred_id`\n4) Add your OpenAI API credential to the OpenAI node\n5) Enable schedule triggers and execute once to test\n"
      },
      "typeVersion": 1
    }
  ],
  "connections": {
    "Flatten message list": {
      "main": [
        [
          {
            "node": "Insert messages into warmup_queue",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If warmup row exists": {
      "main": [
        [
          {
            "node": "Label warmup message (receiver)",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Loop: mark warmups read",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter messages due now": {
      "main": [
        [
          {
            "node": "Merge queue with account credentials",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Label sent warmup email": {
      "main": [
        [
          {
            "node": "Update queue: sent + message/thread IDs",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop: mark warmups read": {
      "main": [
        [],
        [
          {
            "node": "Fetch unread messages from sender",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse conversation JSON": {
      "main": [
        [
          {
            "node": "Merge recipients + conversations",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get today unsent warmups": {
      "main": [
        [
          {
            "node": "If scheduled_at is empty",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If scheduled_at is empty": {
      "main": [
        [
          {
            "node": "Assign random send time (IST window)",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Filter messages due now",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop: send warmup message": {
      "main": [
        [],
        [
          {
            "node": "If first message in thread",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If first message in thread": {
      "main": [
        [
          {
            "node": "Send Gmail message (new thread)",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Get previous message (thread context)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop: build queue per inbox": {
      "main": [
        [
          {
            "node": "Flatten message list",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Calculate daily warmup target",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get conversations from table": {
      "main": [
        [
          {
            "node": "Parse conversation JSON",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop: generate conversations": {
      "main": [
        [],
        [
          {
            "node": "Generate conversations (OpenAI)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Update scheduled_at in queue": {
      "main": [
        [
          {
            "node": "Filter messages due now",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Calculate daily warmup target": {
      "main": [
        [
          {
            "node": "Get recipient inboxes (excluding sender)",
            "type": "main",
            "index": 0
          },
          {
            "node": "Get conversations from table",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get sent warmups to mark read": {
      "main": [
        [
          {
            "node": "Merge receiver inbox credentials",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get warmup accounts for queue": {
      "main": [
        [
          {
            "node": "Loop: build queue per inbox",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Pick random recipient inboxes": {
      "main": [
        [
          {
            "node": "Merge recipients + conversations",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "generate warmup conversations": {
      "main": [
        [
          {
            "node": "Get warmup accounts (cold_email_accounts)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get accounts (for credentials)": {
      "main": [
        [
          {
            "node": "Merge queue with account credentials",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Reply in existing Gmail thread": {
      "main": [
        [
          {
            "node": "Label sent warmup email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate conversations (OpenAI)": {
      "main": [
        [
          {
            "node": "Format conversations for Data Table",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Label warmup message (receiver)": {
      "main": [
        [
          {
            "node": "Remove UNREAD label (mark read)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Remove UNREAD label (mark read)": {
      "main": [
        [
          {
            "node": "Update queue: marked_read = true",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Gmail message (new thread)": {
      "main": [
        [
          {
            "node": "Label sent warmup email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge receiver inbox credentials": {
      "main": [
        [
          {
            "node": "Loop: mark warmups read",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge recipients + conversations": {
      "main": [
        [
          {
            "node": "Loop: match conversations to recipients",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Update queue: marked_read = true": {
      "main": [
        [
          {
            "node": "Loop: mark warmups read",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Daily trigger: build warmup queue": {
      "main": [
        [
          {
            "node": "Get warmup accounts for queue",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch unread messages from sender": {
      "main": [
        [
          {
            "node": "If warmup row exists",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get accounts (for receiver creds)": {
      "main": [
        [
          {
            "node": "Merge receiver inbox credentials",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Insert messages into warmup_queue": {
      "main": [
        []
      ]
    },
    "Build conversation generation loop": {
      "main": [
        [
          {
            "node": "Loop: generate conversations",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format conversations for Data Table": {
      "main": [
        [
          {
            "node": "Save conversations (warmup_conversations)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Assign random send time (IST window)": {
      "main": [
        [
          {
            "node": "Update scheduled_at in queue",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Hourly trigger: mark warmups as read": {
      "main": [
        [
          {
            "node": "Get sent warmups to mark read",
            "type": "main",
            "index": 0
          },
          {
            "node": "Get accounts (for receiver creds)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge queue with account credentials": {
      "main": [
        [
          {
            "node": "Loop: send warmup message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get previous message (thread context)": {
      "main": [
        [
          {
            "node": "Reply in existing Gmail thread",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop: match conversations to recipients": {
      "main": [
        [],
        [
          {
            "node": "Split conversation into scheduled messages",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Update queue: sent + message/thread IDs": {
      "main": [
        [
          {
            "node": "Loop: send warmup message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get recipient inboxes (excluding sender)": {
      "main": [
        [
          {
            "node": "Pick random recipient inboxes",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get warmup accounts (cold_email_accounts)": {
      "main": [
        [
          {
            "node": "Build conversation generation loop",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Save conversations (warmup_conversations)": {
      "main": [
        [
          {
            "node": "Loop: generate conversations",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split conversation into scheduled messages": {
      "main": [
        [
          {
            "node": "Loop: build queue per inbox",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Hourly trigger: send scheduled warmup emails": {
      "main": [
        [
          {
            "node": "Get today unsent warmups",
            "type": "main",
            "index": 0
          },
          {
            "node": "Get accounts (for credentials)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}