← All Productivity

Cal.com email verification with BillionVerify

Cal.com is an open-source scheduling platform that lets individuals and teams manage bookings, appointments, and calendar availability. Every booking captures an attendee email, making Cal.com a natural integration point for BillionVerify to ensure confirmation emails and reminders reach real inboxes.

Why verify before the send

Scheduling tools depend on email to deliver booking confirmations, reminders, and cancellation notices. If an attendee provides a fake or mistyped address, they miss their own confirmation and your no-show rate climbs. BillionVerify validates emails at booking time, reducing no-shows caused by missed communications and keeping your calendar data reliable.

Ready-to-use n8n workflow

Import this workflow into n8n — it verifies every address with BillionVerify before Cal.com sends, so only deliverable contacts are emailed. Install the BillionVerify community node first, then add your API key. Adapted from this n8n template

verify-emails-in-cal-com.json
{
  "name": "Pre-meeting email nurturing sequence with Cal.com and Gmail + BillionVerify",
  "nodes": [
    {
      "id": "f63b66f8-d376-46a0-8966-f66fe5739a38",
      "name": "Cal.com Trigger",
      "type": "n8n-nodes-base.calTrigger",
      "position": [
        240,
        464
      ],
      "webhookId": "419db506-3586-4c55-908b-d15efb6677a0",
      "parameters": {
        "events": [
          "BOOKING_CREATED"
        ],
        "options": {}
      },
      "credentials": {
        "calApi": {
          "id": "credential-id",
          "name": "calApi Credential"
        }
      },
      "typeVersion": 2
    },
    {
      "id": "b1d64da4-5a5e-47ad-bd1d-e8741a675157",
      "name": "If",
      "type": "n8n-nodes-base.if",
      "position": [
        688,
        464
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "425c0f1f-dd29-4a73-9f75-b4a26e4435f9",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "leftValue": "={{ $json.is_company_email }}",
              "rightValue": "true"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "035248af-3e48-4a48-b552-4ec9ff71dde6",
      "name": "Calculate time",
      "type": "n8n-nodes-base.code",
      "position": [
        912,
        464
      ],
      "parameters": {
        "jsCode": "// Get meeting start time from original Cal.com data\nconst meetingStartTime = $('Extract prospect').item.json.meeting_start_time;\n\n// Calculate days until meeting\nconst meetingDate = new Date(meetingStartTime);\nconst today = new Date();\nconst diffTime = meetingDate - today;\nconst diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));\n\n// Get all previous data\nconst prospectData = $('Extract prospect').item.json;\nconst aiData = $input.item.json;\n\nreturn {\n  json: {\n    // Original prospect data\n    attendee_email: prospectData.attendee_email,\n    attendee_name: prospectData.attendee_name,\n    meeting_start_time: prospectData.meeting_start_time,\n    meeting_title: prospectData.meeting_title,\n    email_domain: prospectData.email_domain,\n    company_name: prospectData.company_name,  // ← ADDED\n    website_url: prospectData.website_url,\n    \n    // AI analysis data\n    has_website_data: aiData.has_website_data,\n    business_type: aiData.business_type,\n    tech_stack: aiData.tech_stack,\n    likely_pain_points: aiData.likely_pain_points,\n    personalization_hook: aiData.personalization_hook,\n    \n    // Days calculation\n    days_until_meeting: diffDays\n  }\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "70c2a2c4-02db-42c1-bdad-fcbb5469bb49",
      "name": "Extract prospect",
      "type": "n8n-nodes-base.code",
      "position": [
        464,
        464
      ],
      "parameters": {
        "jsCode": "// Get attendee email from Cal.com webhook\nconst attendeeEmail = $input.item.json.attendees[0].email;\nconst attendeeName = $input.item.json.attendees[0].name;\nconst meetingStartTime = $input.item.json.startTime;\nconst meetingTitle = $input.item.json.eventTitle;\n\n// Get company name from custom field (if provided)\nconst companyName = $input.item.json.responses['Company-Name']?.value || null;\n\n// Extract domain from email\nconst domain = attendeeEmail.split('@')[1];\n\n// List of consumer email providers\nconst consumerDomains = [\n  'gmail.com', 'yahoo.com', 'outlook.com', 'hotmail.com',\n  'aol.com', 'icloud.com', 'protonmail.com', 'mail.com',\n  'live.com', 'msn.com', 'ymail.com', 'googlemail.com'\n];\n\n// Check if it's a company email\nconst isCompanyEmail = !consumerDomains.includes(domain.toLowerCase());\n\n// Build website URL - use company name if provided and consumer email, otherwise use domain\nlet websiteUrl = null;\nif (companyName && !isCompanyEmail) {\n  // They gave us company name but have Gmail - try to build URL from company name\n  websiteUrl = `https://${companyName.toLowerCase().replace(/\\s+/g, '')}.com`;\n} else if (isCompanyEmail) {\n  // Company email - use domain\n  websiteUrl = `https://${domain}`;\n}\n\nreturn {\n  json: {\n    attendee_email: attendeeEmail,\n    attendee_name: attendeeName,\n    meeting_start_time: meetingStartTime,\n    meeting_title: meetingTitle,\n    email_domain: domain,\n    company_name: companyName,\n    is_company_email: isCompanyEmail,\n    website_url: websiteUrl\n  }\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "14f95913-ea00-4041-aacd-329ac4770e65",
      "name": "Wait 1 Day",
      "type": "n8n-nodes-base.wait",
      "position": [
        1584,
        464
      ],
      "webhookId": "3c81bf74-3632-4011-b07f-e2486e12ebe6",
      "parameters": {},
      "typeVersion": 1.1
    },
    {
      "id": "65db5d98-cca3-4ba0-89b9-d583e8b4fb75",
      "name": "Switch: Days Until Meeting",
      "type": "n8n-nodes-base.switch",
      "position": [
        1136,
        448
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "outputKey": "0–1 days",
              "conditions": {
                "options": {
                  "version": 1,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "loose"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "operator": {
                      "type": "number",
                      "operation": "lte"
                    },
                    "leftValue": "={{ $json.days_until_meeting }}",
                    "rightValue": 1
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "2–7 days",
              "conditions": {
                "options": {
                  "version": 1,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "loose"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "operator": {
                      "type": "number",
                      "operation": "lte"
                    },
                    "leftValue": "={{ $json.days_until_meeting }}",
                    "rightValue": 7
                  },
                  {
                    "operator": {
                      "type": "number",
                      "operation": "gt"
                    },
                    "leftValue": "={{ $json.days_until_meeting }}",
                    "rightValue": 1
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "8+ days",
              "conditions": {
                "options": {
                  "version": 1,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "loose"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "dd9c015f-4dcc-4577-9c12-a610e167dccb",
                    "operator": {
                      "type": "number",
                      "operation": "gt"
                    },
                    "leftValue": "={{ $json.days_until_meeting }}",
                    "rightValue": 7
                  }
                ]
              },
              "renameOutput": true
            }
          ]
        },
        "options": {
          "fallbackOutput": "none",
          "looseTypeValidation": true
        }
      },
      "typeVersion": 3
    },
    {
      "id": "074aa12d-bc36-46a6-b10f-6dc144d76ce6",
      "name": "Quick prep email",
      "type": "n8n-nodes-base.set",
      "position": [
        1360,
        272
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "a008a6aa-e391-4684-87d7-42c0a19540ae",
              "name": "email",
              "type": "string",
              "value": "={{(() => {\n  const firstName = $json.attendee_name.split(' ')[0];\n  const company = $json.company_name;\n  const rawDate = new Date($json.meeting_start_time);\n  const now = new Date();\n\n  const isTomorrow = rawDate.getDate() === (now.getDate() + 1) &&\n                     rawDate.getMonth() === now.getMonth() &&\n                     rawDate.getFullYear() === now.getFullYear();\n\n  const options = { hour: 'numeric', minute: '2-digit', hour12: true };\n  const timeString = rawDate.toLocaleTimeString('en-US', options).toLowerCase().replace(':00', '');\n\n  const daysOfWeek = ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'];\n  const dayName = daysOfWeek[rawDate.getDay()];\n\n  const friendlyTime = isTomorrow ? `${timeString} tomorrow` : `${timeString} on ${dayName}`;\n\n  return `Hey ${firstName},\n\nAppreciate you booking — looking forward to chatting at ${friendlyTime}.\n\nTo make this actually useful for both of us, quick q’s:\n\n– What’s the biggest thing you’re stuck on right now?\n– Are you the main decider on this, or is someone else looped in?\n\nDoesn’t need to be a long reply — just gives me a bit of context so I can prep around what matters for ${company}.\n\nCatch you soon 🙏`;\n})()}}\n"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "a88320c9-184a-40b3-9cac-14b5d2cdddf5",
      "name": "Casual flex",
      "type": "n8n-nodes-base.gmail",
      "position": [
        1360,
        464
      ],
      "webhookId": "5bdbdeb7-29c5-464c-ab86-9a31ebcded9b",
      "parameters": {
        "sendTo": "={{ $('Calculate time').item.json.attendee_email }}",
        "message": "=Looking forward to chat about how we can connect {{ $('Calculate time').item.json.company_name }} with ideal clients before your competitors\n\nTo prep: Think about your ideal client profile and how many intros per month would move the needle for you.\n\nPS: not to flex here but — we helped Vention add $85K last quarter using the same system\n\nCatch you then 🙏\n\n— Maks\n",
        "options": {},
        "subject": "=Meeting confirmed 👋🏻",
        "emailType": "text"
      },
      "credentials": {
        "gmailOAuth2": {
          "id": "credential-id",
          "name": "gmailOAuth2 Credential"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "d72e7083-48db-4ca6-821c-84ce0f64270b",
      "name": "Casual press",
      "type": "n8n-nodes-base.gmail",
      "position": [
        1808,
        464
      ],
      "webhookId": "5bdbdeb7-29c5-464c-ab86-9a31ebcded9b",
      "parameters": {
        "sendTo": "={{ $('Calculate time').item.json.attendee_email }}",
        "message": "=Hey {{ $json.attendee_name.split(' ')[0] }}—\n\nQuick context about who I am:\n\nI’ve been deep in the industry for a while now. At this point, I’ve seen what works (and what doesn’t) when referals dry up\n\nOver time, I started connecting the right firms to the right buyers — not with ads or cold pitches, but through early, quiet convos before things go live.\n\nI’m not an agency — I’m more like a researcher/network hub depending on the setup.\n\nRight now I’m helping companies in your space connect with folks who’ve already proven they can deliver.\n\nThought I’d share this to give you a quick idea before we chat 🙏\n\nCheers\n\n— Maks",
        "options": {},
        "subject": "=Meeting confirmed 👋🏻",
        "emailType": "text"
      },
      "credentials": {
        "gmailOAuth2": {
          "id": "credential-id",
          "name": "gmailOAuth2 Credential"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "1d8e95e9-aa8b-4e61-bd4f-643dc22ba075",
      "name": "Casual knowledge flex",
      "type": "n8n-nodes-base.gmail",
      "position": [
        2256,
        464
      ],
      "webhookId": "2166b2e3-0908-479f-8293-cc4232136c4b",
      "parameters": {
        "sendTo": "={{ $('Calculate time').item.json.attendee_email }}",
        "message": "=Hey again {{ $json.attendee_name.split(' ')[0] }},  \n\nMaks here\n\nA lot of teams we’ve worked with hit the same wall — outbound either burns cash or burns out their team.\n\nReferrals slow down, ads get expensive, and internal SDRs can’t scale.\n\nOne thing that tends to move the needle early:\n\nRunning early-intro campaigns that quietly connect you to decision-makers before roles go public, since:\n\n- you skip the queue — connect before roles/postings go live\n- you stay invisible to competitors — no noisy job boards or bidding wars\n- you own the timing — you’re not waiting for inbound or referral luck\n\nLet me know if this resonates — happy to adapt our call.\n\n— Maks",
        "options": {},
        "subject": "quick thought"
      },
      "credentials": {
        "gmailOAuth2": {
          "id": "credential-id",
          "name": "gmailOAuth2 Credential"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "162b2e87-a79c-48f5-998c-de9bf5f5f27e",
      "name": "Send it",
      "type": "n8n-nodes-base.gmail",
      "position": [
        1584,
        272
      ],
      "webhookId": "3c58d302-25c8-4bb8-9332-601402d43958",
      "parameters": {
        "sendTo": "={{ $('Calculate time').item.json.attendee_email }}",
        "message": "={{ $json.email }}",
        "options": {
          "appendAttribution": false
        },
        "subject": "Quick prep for tomorrow's call 🙏🏻",
        "emailType": "text"
      },
      "credentials": {
        "gmailOAuth2": {
          "id": "credential-id",
          "name": "gmailOAuth2 Credential"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "e494daf8-064a-445e-924f-97623573764b",
      "name": "Wait another day",
      "type": "n8n-nodes-base.wait",
      "position": [
        2032,
        464
      ],
      "webhookId": "b5bee3b1-ee44-4c0c-8daa-f98e5704a27d",
      "parameters": {},
      "typeVersion": 1.1
    },
    {
      "id": "5fa9f448-f8e8-4a57-bbfd-150e9c3e9cb6",
      "name": "Wait 1 Day1",
      "type": "n8n-nodes-base.wait",
      "position": [
        1584,
        656
      ],
      "webhookId": "3c81bf74-3632-4011-b07f-e2486e12ebe6",
      "parameters": {},
      "typeVersion": 1.1
    },
    {
      "id": "292b1910-34c4-4b3c-9da7-5624f605c301",
      "name": "Casual flex 8+ days",
      "type": "n8n-nodes-base.gmail",
      "position": [
        1360,
        656
      ],
      "webhookId": "5bdbdeb7-29c5-464c-ab86-9a31ebcded9b",
      "parameters": {
        "sendTo": "={{ $('Calculate time').item.json.attendee_email }}",
        "message": "=Excited to connect with {{ $('Calculate time').item.json.company_name }} soon — plenty of time to prep, so I’ll keep it light for now.\n\nIf you get a spare moment, it’s worth reflecting on your ideal client profile — and how many intros per month would make a real difference for your team.\n\nPS: We helped Vention add $85K last quarter using this same system. Looking forward to exploring how it could map to your setup too.\n\nCatch you soon 🙏\n\n— Maks\n",
        "options": {},
        "subject": "=Looking ahead to our call 👋🏻",
        "emailType": "text"
      },
      "credentials": {
        "gmailOAuth2": {
          "id": "credential-id",
          "name": "gmailOAuth2 Credential"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "48e0d4d3-64bb-49df-8b2f-d950b3f39ca0",
      "name": "Casual press 8+days",
      "type": "n8n-nodes-base.gmail",
      "position": [
        1808,
        656
      ],
      "webhookId": "5bdbdeb7-29c5-464c-ab86-9a31ebcded9b",
      "parameters": {
        "sendTo": "={{ $('Calculate time').item.json.attendee_email }}",
        "message": "=Hey {{ $json.attendee_name.split(' ')[0] }}—\n\nQuick context about who I am:\n\nI’ve been deep in the  indusry for a while now. At this point, I’ve seen what works (and what doesn’t) when referals dry up\n\nOver time, I started connecting the right firms to the right buyers — not with ads or cold pitches, but through early, quiet convos before things go live.\n\nI’m not an agency — I’m more like a researcher/network hub depending on the setup.\n\nRight now I’m helping companines in your space connect with folks who’ve already proven they can deliver.\n\nThought I’d share this to give you a quick idea before we chat 🙏\n\nCheers\n\n— Maks",
        "options": {},
        "subject": "=Meeting confirmed 👋🏻",
        "emailType": "text"
      },
      "credentials": {
        "gmailOAuth2": {
          "id": "credential-id",
          "name": "gmailOAuth2 Credential"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "17645622-c90a-4df3-b682-fee7aa2bd402",
      "name": "Wait another day  8+days",
      "type": "n8n-nodes-base.wait",
      "position": [
        2032,
        656
      ],
      "webhookId": "b5bee3b1-ee44-4c0c-8daa-f98e5704a27d",
      "parameters": {},
      "typeVersion": 1.1
    },
    {
      "id": "50b296d1-235c-45fe-8859-25633979854d",
      "name": "Casual knowledge flex 8+days",
      "type": "n8n-nodes-base.gmail",
      "position": [
        2256,
        656
      ],
      "webhookId": "2166b2e3-0908-479f-8293-cc4232136c4b",
      "parameters": {
        "sendTo": "={{ $('Calculate time').item.json.attendee_email }}",
        "message": "=Hey again {{ $json.attendee_name.split(' ')[0] }},  \n\nMaks here\n\nA lot of {{ $json.business_type }} teams we worked with struggle with {{ $json.likely_pain_points }}.  \n\nHere's one thing that tends to move the needle early: [Insert tactic, framework, or article]  \n\nLet me know if this resonates — happy to adapt our call.\n\n— Maks",
        "options": {},
        "subject": "insight"
      },
      "credentials": {
        "gmailOAuth2": {
          "id": "credential-id",
          "name": "gmailOAuth2 Credential"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "cdebfebe-b561-4560-92ea-a5574babeeb6",
      "name": "Wait",
      "type": "n8n-nodes-base.wait",
      "position": [
        2480,
        464
      ],
      "webhookId": "f3d26cc4-72be-4b47-89f4-a0c5bd3a19ea",
      "parameters": {
        "unit": "days",
        "amount": 1
      },
      "typeVersion": 1.1
    },
    {
      "id": "ea936593-456d-487d-9568-140428c19c36",
      "name": "Quick prep email2",
      "type": "n8n-nodes-base.set",
      "position": [
        2704,
        656
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "a008a6aa-e391-4684-87d7-42c0a19540ae",
              "name": "email",
              "type": "string",
              "value": "={{(() => {\n  const firstName = $json.attendee_name.split(' ')[0];\n  const company = $json.company_name;\n  const rawDate = new Date($json.meeting_start_time);\n  const now = new Date();\n\n  const isTomorrow = rawDate.getDate() === (now.getDate() + 1) &&\n                     rawDate.getMonth() === now.getMonth() &&\n                     rawDate.getFullYear() === now.getFullYear();\n\n  const options = { hour: 'numeric', minute: '2-digit', hour12: true };\n  const timeString = rawDate.toLocaleTimeString('en-US', options).toLowerCase().replace(':00', '');\n\n  const daysOfWeek = ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'];\n  const dayName = daysOfWeek[rawDate.getDay()];\n\n  const friendlyTime = isTomorrow ? `${timeString} tomorrow` : `${timeString} on ${dayName}`;\n\n  return `Hey ${firstName},\n\nAppreciate you booking — looking forward to chatting at ${friendlyTime}.\n\nTo make this actually useful for both of us, quick q’s:\n\n– What’s the biggest thing you’re stuck on right now?\n– Are you the main decider on this, or is someone else looped in?\n\nDoesn’t need to be a long reply — just gives me a bit of context so I can prep around what matters for ${company}.\n\nCatch you soon 🙏`;\n})()}}\n"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "7ee51230-b333-4f40-a0fd-aa39b23c8013",
      "name": "Quick prep",
      "type": "n8n-nodes-base.gmail",
      "position": [
        2928,
        464
      ],
      "webhookId": "3c58d302-25c8-4bb8-9332-601402d43958",
      "parameters": {
        "sendTo": "={{ $('Calculate time').item.json.attendee_email }}",
        "message": "={{ $json.email }}",
        "options": {
          "appendAttribution": true
        },
        "subject": "Quick prep for tomorrow's call 🙏🏻",
        "emailType": "text"
      },
      "credentials": {
        "gmailOAuth2": {
          "id": "credential-id",
          "name": "gmailOAuth2 Credential"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "630c45e5-5fb5-417e-83f6-fee3f56998d3",
      "name": "Quick prep +8days",
      "type": "n8n-nodes-base.gmail",
      "position": [
        2928,
        656
      ],
      "webhookId": "3c58d302-25c8-4bb8-9332-601402d43958",
      "parameters": {
        "sendTo": "={{ $('Calculate time').item.json.attendee_email }}",
        "message": "={{ $json.email }}",
        "options": {
          "appendAttribution": true
        },
        "subject": "Quick prep for tomorrow's call 🙏🏻",
        "emailType": "text"
      },
      "credentials": {
        "gmailOAuth2": {
          "id": "credential-id",
          "name": "gmailOAuth2 Credential"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "e4b7cae4-af14-40b2-bc33-04e14f450cea",
      "name": "Quick prep email (2)",
      "type": "n8n-nodes-base.set",
      "position": [
        2704,
        464
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "a008a6aa-e391-4684-87d7-42c0a19540ae",
              "name": "email",
              "type": "string",
              "value": "={{(() => {\n  const firstName = $json.attendee_name.split(' ')[0];\n  const company = $json.company_name;\n  const rawDate = new Date($json.meeting_start_time);\n  const now = new Date();\n\n  const isTomorrow = rawDate.getDate() === (now.getDate() + 1) &&\n                     rawDate.getMonth() === now.getMonth() &&\n                     rawDate.getFullYear() === now.getFullYear();\n\n  const options = { hour: 'numeric', minute: '2-digit', hour12: true };\n  const timeString = rawDate.toLocaleTimeString('en-US', options).toLowerCase().replace(':00', '');\n\n  const daysOfWeek = ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'];\n  const dayName = daysOfWeek[rawDate.getDay()];\n\n  const friendlyTime = isTomorrow ? `${timeString} tomorrow` : `${timeString} on ${dayName}`;\n\n  return `Hey ${firstName},\n\nAppreciate you booking — looking forward to chatting at ${friendlyTime}.\n\nTo make this actually useful for both of us, quick q’s:\n\n– What’s the biggest thing you’re stuck on right now?\n– Are you the main decider on this, or is someone else looped in?\n\nDoesn’t need to be a long reply — just gives me a bit of context so I can prep around what matters for ${company}.\n\nCatch you soon 🙏`;\n})()}}\n"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "e317772f-47fa-4007-8166-3a67e1a60512",
      "name": "Wait1",
      "type": "n8n-nodes-base.wait",
      "position": [
        2480,
        656
      ],
      "webhookId": "8b5c6e4f-41d6-4817-996d-909ac6f94f8c",
      "parameters": {
        "unit": "days",
        "amount": 1
      },
      "typeVersion": 1.1
    },
    {
      "id": "210fa6ca-168f-437b-8f18-0ac5e2004521",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -448,
        0
      ],
      "parameters": {
        "width": 592,
        "height": 720,
        "content": "# ⭐ Overview \n**Automated Pre-Meeting Email Sequence for Cal.com Bookings**\n\nThis workflow automatically warms up your leads between the moment they book a meeting and the day the meeting happens. It pulls in new Cal.com bookings, checks how many days remain until the meeting, and sends a series of pre-written emails spaced over time. The goal is to increase show-up rates, set expectations, and gently steer the user toward understanding the “connector” or sales-oriented purpose of the call.\n\nInstead of manually sending reminders or hoping your lead reads the booking confirmation, this workflow creates a structured drip sequence leading up to the meeting. Each email is triggered based on time intervals (for example: immediately, 3 days before, 1 day before). You have full control over the email content and timing.\n\n### How it works\n1. Trigger fires when someone books a meeting in Cal.com.  \n2. The workflow calculates how many days remain before the call.  \n3. Based on timing, the appropriate warm-up emails are sent via Gmail.  \n4. Additional Wait nodes space out messages to ensure natural engagement.\n\n### Setup steps\n1. Add your **Cal.com API key** in the Trigger node.  \n2. Authenticate your **Google account** for Gmail.  \n3. Customize each email message to match your tone and purpose.  \n4. Test internally with sample bookings before enabling it live.\n\n### Customization\nAdjust wait durations, timing logic, or create separate sequences for different event types in Cal.com. You can also use other calendar apps like calendly. You just need to change the trigger. "
      },
      "typeVersion": 1
    },
    {
      "id": "fe992484-d156-46f1-8cff-51380e5fcaee",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1312,
        144
      ],
      "parameters": {
        "color": 7,
        "width": 1840,
        "height": 720,
        "content": "## Nurturing Message\nYou can change the message for your needs and duration before sending the messages in here."
      },
      "typeVersion": 1
    },
    {
      "parameters": {
        "operation": "verify",
        "email": "={{ $('Calculate time').item.json.attendee_email }}",
        "additionalOptions": {}
      },
      "type": "n8n-nodes-billionverify.billionVerify",
      "typeVersion": 1,
      "position": [
        1000,
        464
      ],
      "name": "Verify Email (BillionVerify)",
      "credentials": {
        "billionVerifyApi": {
          "id": "",
          "name": "BillionVerify account"
        }
      }
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "loose"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "is-deliverable",
              "leftValue": "={{ $json.is_deliverable }}",
              "rightValue": "",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              }
            }
          ]
        }
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        1180,
        464
      ],
      "name": "IF deliverable"
    },
    {
      "parameters": {
        "operation": "verify",
        "email": "={{ $('Calculate time').item.json.attendee_email }}",
        "additionalOptions": {}
      },
      "type": "n8n-nodes-billionverify.billionVerify",
      "typeVersion": 1,
      "position": [
        1448,
        464
      ],
      "name": "Verify Email (BillionVerify) 2",
      "credentials": {
        "billionVerifyApi": {
          "id": "",
          "name": "BillionVerify account"
        }
      }
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "loose"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "is-deliverable",
              "leftValue": "={{ $json.is_deliverable }}",
              "rightValue": "",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              }
            }
          ]
        }
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        1628,
        464
      ],
      "name": "IF deliverable 2"
    },
    {
      "parameters": {
        "operation": "verify",
        "email": "={{ $('Calculate time').item.json.attendee_email }}",
        "additionalOptions": {}
      },
      "type": "n8n-nodes-billionverify.billionVerify",
      "typeVersion": 1,
      "position": [
        1896,
        464
      ],
      "name": "Verify Email (BillionVerify) 3",
      "credentials": {
        "billionVerifyApi": {
          "id": "",
          "name": "BillionVerify account"
        }
      }
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "loose"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "is-deliverable",
              "leftValue": "={{ $json.is_deliverable }}",
              "rightValue": "",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              }
            }
          ]
        }
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        2076,
        464
      ],
      "name": "IF deliverable 3"
    },
    {
      "parameters": {
        "operation": "verify",
        "email": "={{ $('Calculate time').item.json.attendee_email }}",
        "additionalOptions": {}
      },
      "type": "n8n-nodes-billionverify.billionVerify",
      "typeVersion": 1,
      "position": [
        1224,
        272
      ],
      "name": "Verify Email (BillionVerify) 4",
      "credentials": {
        "billionVerifyApi": {
          "id": "",
          "name": "BillionVerify account"
        }
      }
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "loose"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "is-deliverable",
              "leftValue": "={{ $json.is_deliverable }}",
              "rightValue": "",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              }
            }
          ]
        }
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        1404,
        272
      ],
      "name": "IF deliverable 4"
    },
    {
      "parameters": {
        "operation": "verify",
        "email": "={{ $('Calculate time').item.json.attendee_email }}",
        "additionalOptions": {}
      },
      "type": "n8n-nodes-billionverify.billionVerify",
      "typeVersion": 1,
      "position": [
        1000,
        656
      ],
      "name": "Verify Email (BillionVerify) 5",
      "credentials": {
        "billionVerifyApi": {
          "id": "",
          "name": "BillionVerify account"
        }
      }
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "loose"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "is-deliverable",
              "leftValue": "={{ $json.is_deliverable }}",
              "rightValue": "",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              }
            }
          ]
        }
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        1180,
        656
      ],
      "name": "IF deliverable 5"
    },
    {
      "parameters": {
        "operation": "verify",
        "email": "={{ $('Calculate time').item.json.attendee_email }}",
        "additionalOptions": {}
      },
      "type": "n8n-nodes-billionverify.billionVerify",
      "typeVersion": 1,
      "position": [
        1448,
        656
      ],
      "name": "Verify Email (BillionVerify) 6",
      "credentials": {
        "billionVerifyApi": {
          "id": "",
          "name": "BillionVerify account"
        }
      }
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "loose"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "is-deliverable",
              "leftValue": "={{ $json.is_deliverable }}",
              "rightValue": "",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              }
            }
          ]
        }
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        1628,
        656
      ],
      "name": "IF deliverable 6"
    },
    {
      "parameters": {
        "operation": "verify",
        "email": "={{ $('Calculate time').item.json.attendee_email }}",
        "additionalOptions": {}
      },
      "type": "n8n-nodes-billionverify.billionVerify",
      "typeVersion": 1,
      "position": [
        1896,
        656
      ],
      "name": "Verify Email (BillionVerify) 7",
      "credentials": {
        "billionVerifyApi": {
          "id": "",
          "name": "BillionVerify account"
        }
      }
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "loose"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "is-deliverable",
              "leftValue": "={{ $json.is_deliverable }}",
              "rightValue": "",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              }
            }
          ]
        }
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        2076,
        656
      ],
      "name": "IF deliverable 7"
    },
    {
      "parameters": {
        "operation": "verify",
        "email": "={{ $('Calculate time').item.json.attendee_email }}",
        "additionalOptions": {}
      },
      "type": "n8n-nodes-billionverify.billionVerify",
      "typeVersion": 1,
      "position": [
        2568,
        464
      ],
      "name": "Verify Email (BillionVerify) 8",
      "credentials": {
        "billionVerifyApi": {
          "id": "",
          "name": "BillionVerify account"
        }
      }
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "loose"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "is-deliverable",
              "leftValue": "={{ $json.is_deliverable }}",
              "rightValue": "",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              }
            }
          ]
        }
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        2748,
        464
      ],
      "name": "IF deliverable 8"
    },
    {
      "parameters": {
        "operation": "verify",
        "email": "={{ $('Calculate time').item.json.attendee_email }}",
        "additionalOptions": {}
      },
      "type": "n8n-nodes-billionverify.billionVerify",
      "typeVersion": 1,
      "position": [
        2568,
        656
      ],
      "name": "Verify Email (BillionVerify) 9",
      "credentials": {
        "billionVerifyApi": {
          "id": "",
          "name": "BillionVerify account"
        }
      }
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "loose"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "is-deliverable",
              "leftValue": "={{ $json.is_deliverable }}",
              "rightValue": "",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              }
            }
          ]
        }
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        2748,
        656
      ],
      "name": "IF deliverable 9"
    }
  ],
  "connections": {
    "If": {
      "main": [
        [
          {
            "node": "Calculate time",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait": {
      "main": [
        [
          {
            "node": "Quick prep email (2)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait1": {
      "main": [
        [
          {
            "node": "Quick prep email2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait 1 Day": {
      "main": [
        [
          {
            "node": "Verify Email (BillionVerify) 2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Casual flex": {
      "main": [
        [
          {
            "node": "Wait 1 Day",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait 1 Day1": {
      "main": [
        [
          {
            "node": "Verify Email (BillionVerify) 6",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Casual press": {
      "main": [
        [
          {
            "node": "Wait another day",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Calculate time": {
      "main": [
        [
          {
            "node": "Switch: Days Until Meeting",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Cal.com Trigger": {
      "main": [
        [
          {
            "node": "Extract prospect",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract prospect": {
      "main": [
        [
          {
            "node": "If",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Quick prep email": {
      "main": [
        [
          {
            "node": "Verify Email (BillionVerify) 4",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait another day": {
      "main": [
        [
          {
            "node": "Verify Email (BillionVerify) 3",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Quick prep email2": {
      "main": [
        [
          {
            "node": "Verify Email (BillionVerify) 9",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Casual flex 8+ days": {
      "main": [
        [
          {
            "node": "Wait 1 Day1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Casual press 8+days": {
      "main": [
        [
          {
            "node": "Wait another day  8+days",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Quick prep email (2)": {
      "main": [
        [
          {
            "node": "Verify Email (BillionVerify) 8",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Casual knowledge flex": {
      "main": [
        [
          {
            "node": "Wait",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait another day  8+days": {
      "main": [
        [
          {
            "node": "Verify Email (BillionVerify) 7",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Switch: Days Until Meeting": {
      "main": [
        [
          {
            "node": "Quick prep email",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Verify Email (BillionVerify)",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Verify Email (BillionVerify) 5",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Casual knowledge flex 8+days": {
      "main": [
        [
          {
            "node": "Wait1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Verify Email (BillionVerify)": {
      "main": [
        [
          {
            "node": "IF deliverable",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF deliverable": {
      "main": [
        [
          {
            "node": "Casual flex",
            "type": "main",
            "index": 0
          }
        ],
        []
      ]
    },
    "Verify Email (BillionVerify) 2": {
      "main": [
        [
          {
            "node": "IF deliverable 2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF deliverable 2": {
      "main": [
        [
          {
            "node": "Casual press",
            "type": "main",
            "index": 0
          }
        ],
        []
      ]
    },
    "Verify Email (BillionVerify) 3": {
      "main": [
        [
          {
            "node": "IF deliverable 3",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF deliverable 3": {
      "main": [
        [
          {
            "node": "Casual knowledge flex",
            "type": "main",
            "index": 0
          }
        ],
        []
      ]
    },
    "Verify Email (BillionVerify) 4": {
      "main": [
        [
          {
            "node": "IF deliverable 4",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF deliverable 4": {
      "main": [
        [
          {
            "node": "Send it",
            "type": "main",
            "index": 0
          }
        ],
        []
      ]
    },
    "Verify Email (BillionVerify) 5": {
      "main": [
        [
          {
            "node": "IF deliverable 5",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF deliverable 5": {
      "main": [
        [
          {
            "node": "Casual flex 8+ days",
            "type": "main",
            "index": 0
          }
        ],
        []
      ]
    },
    "Verify Email (BillionVerify) 6": {
      "main": [
        [
          {
            "node": "IF deliverable 6",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF deliverable 6": {
      "main": [
        [
          {
            "node": "Casual press 8+days",
            "type": "main",
            "index": 0
          }
        ],
        []
      ]
    },
    "Verify Email (BillionVerify) 7": {
      "main": [
        [
          {
            "node": "IF deliverable 7",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF deliverable 7": {
      "main": [
        [
          {
            "node": "Casual knowledge flex 8+days",
            "type": "main",
            "index": 0
          }
        ],
        []
      ]
    },
    "Verify Email (BillionVerify) 8": {
      "main": [
        [
          {
            "node": "IF deliverable 8",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF deliverable 8": {
      "main": [
        [
          {
            "node": "Quick prep",
            "type": "main",
            "index": 0
          }
        ],
        []
      ]
    },
    "Verify Email (BillionVerify) 9": {
      "main": [
        [
          {
            "node": "IF deliverable 9",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF deliverable 9": {
      "main": [
        [
          {
            "node": "Quick prep +8days",
            "type": "main",
            "index": 0
          }
        ],
        []
      ]
    }
  },
  "settings": {
    "executionOrder": "v1"
  }
}

Workflow templates with Cal.com

Ready-to-use workflows that verify emails before Cal.com sends.

How it works

  1. 1

    Set up a Cal.com webhook or use the n8n Cal.com trigger to fire on each new booking.

  2. 2

    Extract the attendee's email address from the booking payload.

  3. 3

    Send the address to BillionVerify via the n8n community node or REST API for real-time validation.

  4. 4

    If the address is valid, allow the booking confirmation to proceed normally.

  5. 5

    If invalid or disposable, flag the booking for review or send an alternate notification prompting the attendee to provide a working email.

When to use this

Confirm attendee emails before sending booking confirmations

When someone books a slot through Cal.com, verify their email with BillionVerify before the confirmation is sent. Invalid addresses are flagged immediately, giving you the opportunity to follow up through an alternative channel rather than losing the booking silently.

Filter disposable emails from high-volume booking pages

Public booking pages can attract spam submissions using disposable addresses. BillionVerify identifies these domains and lets you reject or flag those bookings, keeping your calendar filled with genuine appointments.

Maintain clean attendee lists for recurring events

For webinars or recurring meetings scheduled through Cal.com, run attendee emails through BillionVerify before adding them to your mailing list. This prevents bounces when sending follow-up materials or event recordings.

FAQ

Does BillionVerify support Cal.com directly?

BillionVerify connects to Cal.com via n8n (using Cal.com's trigger node alongside the BillionVerify community node) or through Integrately's 1-click setup, with no custom coding required.

Will verifying emails delay the booking confirmation?

BillionVerify typically responds in under a second, so attendees experience no noticeable delay. The check runs server-side in your automation workflow before the confirmation email is dispatched.

What should I do with bookings that have invalid emails?

Common approaches include holding the booking in a pending state, sending an SMS if a phone number was provided, or displaying an in-flow message asking the user to re-enter their email.

Can BillionVerify help reduce no-shows?

Indirectly, yes. No-shows caused by missed confirmation emails drop significantly when you ensure every attendee address is deliverable before the confirmation and reminder sequence begins.

Verify emails in Cal.com

Create a free account, grab your API key, and stop bounces before they happen.

Get started free