{
  "id": "QpilLWi7ZJID0IK3",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Decrease No-Shows from Calendly Meetings (Template)",
  "tags": [],
  "nodes": [
    {
      "id": "1fb2d001-2f04-4f5e-8f93-0c7668f246e0",
      "name": "Send Reminder Email",
      "type": "n8n-nodes-base.emailSend",
      "position": [
        1680,
        -80
      ],
      "parameters": {
        "text": "Hi {{$json[\"invitee_name\"]}},\\n\\nJust a quick reminder about our strategy call scheduled for {{$json[\"meeting_time\"]}}, {{$json[\"meeting_date\"]}} (EET).\\n\\nWe'll discuss how to scale smarter with AI and data-driven systems.\\n\\nJoin via: {{$json[\"meeting_link\"]}}\\n\\nTalk soon,\\n[HOST_NAME]",
        "options": {},
        "subject": "Reminder: Your AI Strategy Call {{ $json.type === '24h' ? 'Tomorrow' : 'in 1 hour' }}",
        "toEmail": "={{ $('extract from email').item.json.output.invitee_email }}",
        "fromEmail": "[HOST_EMAIL]"
      },
      "typeVersion": 2
    },
    {
      "id": "4ca79811-a7eb-42af-b461-f4166824172b",
      "name": "Structured Output Parser",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        96,
        160
      ],
      "parameters": {
        "jsonSchemaExample": "{\n  \"invitee_name\": \"string\",\n  \"invitee_email\": \"string\",\n  \"phone_number\": \"string\",\n  \"meeting_date\": \"date\",\n  \"meeting_time\": \"time\",\n  \"meeting_link\": \"string\",\n  \"meeting_goal\": \"string\",\n  \"needs_more_info\": \"boolean\",\n  \"additional_info\": \"string\"\n}\n"
      },
      "typeVersion": 1.3
    },
    {
      "id": "12c9c9e9-9d62-4f69-83fb-ad4f16947201",
      "name": "Calculator",
      "type": "@n8n/n8n-nodes-langchain.toolCalculator",
      "position": [
        -32,
        160
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "54205d4e-0f6c-4f54-acb0-4f98a5d2b326",
      "name": "Notification received",
      "type": "n8n-nodes-base.emailReadImap",
      "position": [
        -384,
        -64
      ],
      "parameters": {
        "options": {},
        "postProcessAction": "nothing"
      },
      "typeVersion": 2.1
    },
    {
      "id": "3a212390-ff8a-4d0b-8db1-7290a5a348fa",
      "name": "LLM model",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "position": [
        -160,
        160
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 1
    },
    {
      "id": "f043a10a-ec90-4702-82fa-344ff68951be",
      "name": "Check if More Info is Needed",
      "type": "n8n-nodes-base.if",
      "position": [
        304,
        -64
      ],
      "parameters": {
        "conditions": {
          "string": [
            {
              "value1": "={{ $json.output.needs_more_info }}",
              "value2": "true"
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "id": "252ae5b4-7342-41e1-861d-d9f091e391f2",
      "name": "Calculate Waiting Time",
      "type": "n8n-nodes-base.code",
      "position": [
        800,
        -64
      ],
      "parameters": {
        "jsCode": "// === Parse email received date ===\nconst emailReceivedStr = $('Notification received').first().json.date; // e.g., \"Tue, 28 Oct 2025 22:34:56 +0200\"\nconst emailReceived = new Date(emailReceivedStr);\n\n// === Parse meeting date and time from Output Parser ===\nconst meetingDateStr = $input.first().json.output.meeting_date; // e.g., \"2025-10-29\"\nconst meetingTimeStr = $input.first().json.output.meeting_time; // e.g., \"16:00\"\n\n// === Combine meeting date and time with EET offset (+02:00) ===\nconst meetingDateTime = new Date(`${meetingDateStr}T${meetingTimeStr}:00+02:00`);\n\n// === Calculate difference in hours between meeting and email received ===\nconst diffHrs = (meetingDateTime - emailReceived) / (1000 * 60 * 60);\n\n// === Prepare wait times for reminders ===\nconst waitOutput = {\n    wait_24h: 0, // Reminder 24h before meeting\n    wait_1h: 0   // Reminder 1h before meeting\n};\n\n// If the difference is more than 24h, calculate 24h reminder\nif (diffHrs > 24) {\n    waitOutput.wait_24h = Math.floor(diffHrs - 24);\n}\n\n// If the difference is less than 24h, calculate 1h reminder\nif (diffHrs < 24) {\n    waitOutput.wait_1h = Math.floor(diffHrs - 1);\n}\n\n// Ensure both fields are numbers (null replaced with 0)\nwaitOutput.wait_24h = waitOutput.wait_24h || 0;\nwaitOutput.wait_1h = waitOutput.wait_1h || 0;\n\n// === Return JSON object ===\nreturn [\n    {\n        json: waitOutput\n    }\n];\n"
      },
      "typeVersion": 2,
      "alwaysOutputData": true
    },
    {
      "id": "edb48348-1a46-4486-8a2c-188bb8971b00",
      "name": "When to send",
      "type": "n8n-nodes-base.if",
      "position": [
        1056,
        -64
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "5029e2f0-c526-4ff9-8b51-ce763c11bcba",
              "operator": {
                "type": "number",
                "operation": "equals"
              },
              "leftValue": "={{ $json.wait_24h }}",
              "rightValue": 0
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "902b64a0-ba2b-429e-af79-38327a4c6d7a",
      "name": "Wait to send 1h before meeting",
      "type": "n8n-nodes-base.wait",
      "position": [
        1296,
        -256
      ],
      "parameters": {
        "amount": "={{ $json.wait_24h }}"
      },
      "typeVersion": 1
    },
    {
      "id": "841cafba-7dba-4fe7-adf3-57d68f00f51c",
      "name": "Wait to send 24h before meeting",
      "type": "n8n-nodes-base.wait",
      "position": [
        1296,
        -16
      ],
      "parameters": {
        "amount": "={{ $('Calculate Waiting Time').item.json.wait_24h }}"
      },
      "typeVersion": 1
    },
    {
      "id": "bcf10853-cb1b-43d7-b7b5-1a09ff272c08",
      "name": "Wait to send 1h before meeting after 24h",
      "type": "n8n-nodes-base.wait",
      "position": [
        1296,
        224
      ],
      "parameters": {
        "amount": "={{ $('Calculate Waiting Time').item.json.wait_1h }}+{{ $('Calculate Waiting Time').item.json.wait_24h }}"
      },
      "typeVersion": 1
    },
    {
      "id": "8b82159a-c4ca-4efb-adc6-86b2df259d57",
      "name": "Send Clarification request",
      "type": "n8n-nodes-base.emailSend",
      "position": [
        528,
        -80
      ],
      "parameters": {
        "text": "Hi {{$json[\"invitee_name\"]}},\\n\\nI noticed you mentioned '{{$json[\"additional_info\"]}}'. Could you please share more details before our call? This will help me tailor our session to your goals.\\n\\nLooking forward to our meeting,\\n\\n[HOST_NAME]",
        "options": {},
        "subject": "Quick question before our strategy call",
        "toEmail": "={{$json[\"invitee_email\"]}}",
        "fromEmail": "[HOST_EMAIL]"
      },
      "typeVersion": 2
    },
    {
      "id": "cff10792-a670-4e93-983e-ecc3a5e4e664",
      "name": "Send WhatsApp Reminder",
      "type": "n8n-nodes-base.twilio",
      "position": [
        1680,
        112
      ],
      "parameters": {
        "to": "=whatsapp:={{ $('extract from email').item.json.output.phone_number.replace(/\\s+/g,'').replace('+','') }}",
        "from": "whatsapp:[TWILIO_WHATSAPP_FROM]",
        "message": "Hi {{ $('analyze email').item.json.output.invitee_name }}, just a reminder that your AI strategy call is {{ $('analyze email').item.json.output.meeting_date }} @ {{ $('analyze email').item.json.output.meeting_time }} (EET).\\nJoin via: {{ $('analyze email').item.json.output.meeting_link }}\\nLooking forward! - [HOST_NAME]",
        "options": {}
      },
      "typeVersion": 1
    },
    {
      "id": "3701bdb4-d51e-4e4c-b252-c8f6b1abfde6",
      "name": "extract from email",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        -112,
        -64
      ],
      "parameters": {
        "text": "=You are an AI assistant that extracts meeting information from Calendly booking emails.\nRead the email and return a structured JSON with the following fields:\n- invitee_name\n- invitee_email\n- phone_number\n- meeting_date (format YYYY-MM-DD)\n- meeting_time (HH:mm)\n- meeting_link\n- meeting_goal\n- needs_more_info (true/false)\n- additional_info (brief summary if attendee provided extra notes)\n\nTime zone is always Eastern European Time (EET).\nKeep the output strictly in JSON format, no additional text.\nemail: {{ $json.textPlain }}",
        "options": {},
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 2.2,
      "alwaysOutputData": true
    },
    {
      "id": "8493d399-3f6e-45ae-9968-45489bdb8765",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -928,
        -608
      ],
      "parameters": {
        "color": 6,
        "width": 464,
        "height": 912,
        "content": "## Decrease no-shows with customizable reminders and follow-ups \nThis n8n workflow automates communication with meeting invitees to decrease no-show rates by sending timely email and WhatsApp reminders, and a clarification request if more information is needed to prepare the meeting.\n\nOverview of the Flow\nThe workflow is triggered by an incoming email notification (presumably from a system like Calendly or an online form) about a newly scheduled meeting.\n\nIt uses AI to extract key meeting data from the email content.\n\nIt checks if the invitee didn't provide sufficient information, and, if there is a need for more information, sends a clarification request email.\n\nIt calculates the waiting time required for the 24-hour and 1-hour reminders.\n\nIt uses an If node to determine the correct waiting path based on the meeting time.\n\nIt uses Wait nodes for timing the reminders correctly.\n\nFinally, it sends a reminder email and a WhatsApp reminder before the meeting."
      },
      "typeVersion": 1
    },
    {
      "id": "f5806527-1eff-4634-b287-4d78959054fd",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -448,
        -336
      ],
      "parameters": {
        "width": 224,
        "height": 432,
        "content": "## Notification received \n\nPurpose: This node is the trigger. It monitors an IMAP email account for new meeting notification emails (e.g., from Calendly).\n\nAction: Ensure the IMAP account credential is properly set up."
      },
      "typeVersion": 1
    },
    {
      "id": "f0a2b1b2-7c64-469d-953a-cb1d8e79da65",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -160,
        -608
      ],
      "parameters": {
        "width": 336,
        "height": 704,
        "content": "## Data Extraction \nAI Processing:\nextract from email (AI Agent):\n\nPurpose: Uses an LLM (Large Language Model) to analyze the plain text of the notification email and extract structured data.\n\nConfiguration: Verify the prompt to ensure it accurately instructs the model to extract invitee_name, invitee_email, phone_number, meeting_date (YYYY-MM-DD), meeting_time (HH:mm), meeting_link, meeting_goal, needs_more_info (boolean), and additional_info.\n\nCredentials: Ensure the Google Gemini(PaLM) API account credential is set up for the LLM model node.\n\nLLM model (Chat Google Gemini): Connects to the AI model used by the Agent.\n\nCalculator and Structured Output Parser: These nodes are configured to support the AI Agent's structured data extraction."
      },
      "typeVersion": 1
    },
    {
      "id": "a5323425-53b1-470d-b14a-5d6585b437a2",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        256,
        -400
      ],
      "parameters": {
        "width": 432,
        "height": 496,
        "content": "## Is More Info Needed?\n\nPurpose: Checks the boolean output needs_more_info from the \"extract from email\" node.\n\nCondition: If $json.output.needs_more_info is true, the workflow proceeds to the next step on the true branch.\n\nSend Clarification request (Email Send):\n\nPurpose: Sends an email to the invitee asking for more details based on the additional_info provided.\n\nCustomization: Replace [HOST_EMAIL] and [HOST_NAME] with your actual information."
      },
      "typeVersion": 1
    },
    {
      "id": "0e523bfa-76e5-4c6c-a190-78621e4bc791",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        736,
        -400
      ],
      "parameters": {
        "height": 496,
        "content": "## Calculate Waiting Time:\n\nPurpose: Calculates the wait time in hours for the 24-hour and 1-hour reminders, accounting for the email's received time and the meeting time (in EET).\n\nCode Details: The code compares the meeting time with the email received time to calculate wait_24h and wait_1h (or 0 if the time has passed)."
      },
      "typeVersion": 1
    },
    {
      "id": "c8d6b1ac-4606-4186-8621-d964e4342fa4",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        992,
        -672
      ],
      "parameters": {
        "width": 464,
        "height": 1072,
        "content": "## When to send?\n\nPurpose: Directs the workflow to the correct path based on the calculated wait times.\n\nConditions: The false branch (Wait to send 24h before meeting/Wait to send 1h before meeting after 24h) is for meetings more than one hour away. The true branch (Wait to send 1h before meeting) is for meetings that are one hour or less away (where wait_24h is 0).\n\nWait Nodes (Wait to send 24h..., Wait to send 1h..., Wait to send 1h... after 24h):\n\nPurpose: Pauses the workflow for the calculated number of hours to ensure the reminders are sent at the optimal time (24h and 1h before the meeting).\n\nExpression: The amount field uses the calculated values from the \"Calculate Waiting Time\" node."
      },
      "typeVersion": 1
    },
    {
      "id": "074fc85b-63a4-464a-98f9-d02121c40396",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1536,
        -672
      ],
      "parameters": {
        "width": 352,
        "height": 976,
        "content": "## Send Reminders\nPurpose: Sends the main meeting reminder email.\n\nCustomization:\n\nReplace [HOST_EMAIL] and [HOST_NAME].\n\nThe subject line dynamically changes to include Tomorrow (24h reminder) or in 1 hour (1h reminder) using the ternary expression: {{ $json.type === '24h' ? 'Tomorrow' : 'in 1 hour' }}.\n\nSend WhatsApp Reminder (Twilio):\n\nPurpose: Sends a final reminder via WhatsApp (requires a Twilio account configured for WhatsApp).\n\nCustomization:\n\nReplace [TWILIO_WHATSAPP_FROM] with your Twilio WhatsApp sender number.\n\nReplace [HOST_NAME].\n\nEnsure the expression for the To field correctly formats the invitee's phone number for Twilio"
      },
      "typeVersion": 1
    },
    {
      "id": "06d9170c-a147-4f43-be32-c3dd4a927a57",
      "name": "Sticky Note7",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -320,
        400
      ],
      "parameters": {
        "color": 3,
        "width": 1072,
        "height": 224,
        "content": "## Requirements and Customization Credentials:\n\nIMAP (for \"Notification received\").\n\nGoogle Gemini(PaLM) API (for \"LLM model\"). Can be replaced with preferred model.\n\nTwilio (for \"Send WhatsApp Reminder\").\n\nPlaceholders: Replace [HOST_EMAIL], [HOST_NAME], and [TWILIO_WHATSAPP_FROM] with your information in the respective Email Send and Twilio nodes."
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "callerPolicy": "workflowsFromSameOwner",
    "availableInMCP": false,
    "executionOrder": "v1",
    "saveExecutionProgress": true,
    "timeSavedPerExecution": 4
  },
  "versionId": "c7304cad-6675-47fd-b991-2ec8ce6de7ca",
  "connections": {
    "LLM model": {
      "ai_languageModel": [
        [
          {
            "node": "extract from email",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Calculator": {
      "ai_tool": [
        [
          {
            "node": "extract from email",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "When to send": {
      "main": [
        [
          {
            "node": "Wait to send 1h before meeting",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Wait to send 24h before meeting",
            "type": "main",
            "index": 0
          },
          {
            "node": "Wait to send 1h before meeting after 24h",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "extract from email": {
      "main": [
        [
          {
            "node": "Check if More Info is Needed",
            "type": "main",
            "index": 0
          },
          {
            "node": "Calculate Waiting Time",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Notification received": {
      "main": [
        [
          {
            "node": "extract from email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Calculate Waiting Time": {
      "main": [
        [
          {
            "node": "When to send",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Structured Output Parser": {
      "ai_outputParser": [
        [
          {
            "node": "extract from email",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Check if More Info is Needed": {
      "main": [
        [
          {
            "node": "Send Clarification request",
            "type": "main",
            "index": 0
          }
        ],
        []
      ]
    },
    "Wait to send 1h before meeting": {
      "main": [
        [
          {
            "node": "Send Reminder Email",
            "type": "main",
            "index": 0
          },
          {
            "node": "Send WhatsApp Reminder",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait to send 24h before meeting": {
      "main": [
        [
          {
            "node": "Send Reminder Email",
            "type": "main",
            "index": 0
          },
          {
            "node": "Send WhatsApp Reminder",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait to send 1h before meeting after 24h": {
      "main": [
        [
          {
            "node": "Send Reminder Email",
            "type": "main",
            "index": 0
          },
          {
            "node": "Send WhatsApp Reminder",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}