Recover no-show appointments with Calendly, Telegram & email alerts
Pull contacts, verify each address with BillionVerify, and continue to Calendly β only deliverable addresses get through.
Why verify before the send
Sending to invalid, risky, catch-all, or disposable addresses spikes your bounce rate and erodes sender reputation. A verification gate before the Calendly step removes that risk automatically β only deliverable addresses continue, the rest are flagged.
The workflow
BillionVerify β verification sits right before the send.
Node by node
- 1Hourly Check TriggerSourceΒ· n8n
Provides or transforms the contact data flowing through the workflow.
- 2Get Active Calendly AppointmentsSourceΒ· n8n
Provides or transforms the contact data flowing through the workflow.
- 3Filter No-Show Appointments (30+ min past)SourceΒ· n8n
Provides or transforms the contact data flowing through the workflow.
- 4Check If High Intent LeadLogicΒ· n8n
Branches on the verification result: only deliverable addresses continue to the send; the rest are skipped and flagged.
- 5Send Reschedule Link via TelegramSourceΒ· n8n
Provides or transforms the contact data flowing through the workflow.
- 6Verify Email (BillionVerify)VerifyΒ· billionverify
The BillionVerify node verifies the address β status (valid / invalid / risky / catch-all / role / disposable), is_deliverable, and a confidence score β before anything is sent.
- 7IF deliverableLogicΒ· n8n
Branches on the verification result: only deliverable addresses continue to the send; the rest are skipped and flagged.
- 8Alert Sales Rep via EmailSendΒ· n8n
Sends only to verified, deliverable addresses. Swap in your own provider node if you send elsewhere.
Workflow JSON
Copy or download this workflow, then import it in n8n (Workflows β Import from File / Paste). Install the BillionVerify community node first, then add your API key credential.
{
"name": "Recover no-show appointments with Calendly, Telegram & email alerts + BillionVerify",
"nodes": [
{
"id": "1ac4eb6c-6300-4ae5-b853-314a1fd7e482",
"name": "Hourly Check Trigger",
"type": "n8n-nodes-base.cron",
"position": [
-1120,
816
],
"parameters": {
"triggerTimes": {
"item": [
{
"mode": "everyHour"
}
]
}
},
"typeVersion": 1
},
{
"id": "2a5b2876-6fda-459b-b573-fcd354958dea",
"name": "Get Active Calendly Appointments",
"type": "n8n-nodes-base.httpRequest",
"position": [
-896,
816
],
"parameters": {
"url": "https://api.calendly.com/scheduled_events?user={{$env.CALENDLY_USER_URI}}&status=active",
"options": {}
},
"typeVersion": 3
},
{
"id": "a5008069-f79b-4ba8-a55f-5f7bedf187d4",
"name": "Filter No-Show Appointments (30+ min past)",
"type": "n8n-nodes-base.function",
"position": [
-656,
816
],
"parameters": {
"functionCode": "const now = new Date();\nconst thresholdMinutes = 30;\n\nconst missed = [];\nfor (const item of items[0].json.collection) {\n const endTime = new Date(item.end_time);\n const diffMinutes = (now - endTime) / 60000;\n if (diffMinutes > thresholdMinutes && !item.attended) {\n missed.push({ json: item });\n }\n}\nreturn missed;"
},
"typeVersion": 1
},
{
"id": "a4c3136a-8697-48dc-ac99-42b126a38d29",
"name": "Check If High Intent Lead",
"type": "n8n-nodes-base.if",
"position": [
-416,
816
],
"parameters": {
"conditions": {
"string": [
{
"value1": "={{ $json.metadata ? $json.metadata.contact_tags : '' }}",
"value2": "High Intent",
"operation": "contains"
}
]
}
},
"typeVersion": 1
},
{
"id": "e9cfd82c-7632-4957-9133-a80f742f6ff0",
"name": "Send Reschedule Link via Telegram",
"type": "n8n-nodes-base.telegram",
"position": [
-176,
768
],
"webhookId": "231fb58f-bed8-4c48-89c9-a29677e46a66",
"parameters": {
"text": "Hi {{$json.invitee_name}}, we missed you on our call earlier!\\nYou can reschedule here: {{$json.uri}}\\nβ Team Shoonya",
"chatId": "={{ $json.metadata ? $json.metadata.telegram_id : '' }}",
"additionalFields": {}
},
"credentials": {
"telegramApi": {
"id": "credential-id",
"name": "telegramApi Credential"
}
},
"typeVersion": 1
},
{
"id": "78f1d804-c3f8-48c5-87a0-6c15371470b1",
"name": "Alert Sales Rep via Email",
"type": "n8n-nodes-base.emailSend",
"position": [
64,
768
],
"parameters": {
"text": "The meeting with {{$json.invitee_name}} appears missed.\\nTelegram message sent successfully.\\nPlease follow up or reschedule here: {{$json.uri}}",
"options": {},
"subject": "Missed Appointment: {{$json.invitee_name}}",
"toEmail": "={{ $json.metadata ? $json.metadata.rep_email : 'sales@yourcompany.com' }}",
"fromEmail": "user@example.com"
},
"credentials": {
"smtp": {
"id": "credential-id",
"name": "smtp Credential"
}
},
"typeVersion": 1
},
{
"id": "ec4bb9a0-b81e-450e-b640-b593c8223f33",
"name": "Sticky Note - Overview",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1488,
448
],
"parameters": {
"width": 280,
"height": 268,
"content": "## π WORKFLOW START\n\n**Purpose:** Automatically detect and recover no-show appointments\n\n**Trigger:** Runs every hour to check for missed meetings\n\n**Target:** High-intent leads who didn't attend their scheduled calls"
},
"typeVersion": 1
},
{
"id": "51435d29-7443-496e-b7a2-c5eeec29509c",
"name": "Sticky Note - Fetch",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1056,
512
],
"parameters": {
"width": 280,
"height": 284,
"content": "## π
STEP 1: Fetch Appointments\n\n**Action:** Retrieves all active scheduled events from Calendly\n\n**API Endpoint:** Calendly scheduled_events API\n\n**Data Retrieved:** Meeting details, invitee info, attendance status, metadata"
},
"typeVersion": 1
},
{
"id": "4fe58a6e-b193-4fc7-b0c6-e83bf77521a8",
"name": "Sticky Note - Filter",
"type": "n8n-nodes-base.stickyNote",
"position": [
-736,
976
],
"parameters": {
"width": 280,
"height": 268,
"content": "## π STEP 2: Identify No-Shows\n\n**Logic:** Filters appointments where:\n- Meeting ended 30+ minutes ago\n- Attendee did NOT show up (attended = false)\n\n**Output:** List of missed appointments only"
},
"typeVersion": 1
},
{
"id": "0bf45c2b-5a96-452b-95e0-18a10ed3b56c",
"name": "Sticky Note - Condition",
"type": "n8n-nodes-base.stickyNote",
"position": [
-576,
512
],
"parameters": {
"width": 280,
"height": 268,
"content": "## π― STEP 3: Priority Check\n\n**Condition:** Only proceed if contact has \"High Intent\" tag\n\n**Why:** Focus recovery efforts on qualified leads\n\n**Source:** Checks metadata.contact_tags field"
},
"typeVersion": 1
},
{
"id": "71b384d7-a800-468a-8c0d-142ebf28bd8c",
"name": "Sticky Note - Telegram",
"type": "n8n-nodes-base.stickyNote",
"position": [
-256,
960
],
"parameters": {
"width": 280,
"height": 316,
"content": "## π¬ STEP 4: Customer Outreach\n\n**Action:** Sends friendly reschedule message via Telegram\n\n**Message Includes:**\n- Personalized greeting\n- Direct reschedule link\n- Company signature\n\n**Target:** Lead's Telegram ID from metadata"
},
"typeVersion": 1
},
{
"id": "7446d041-d351-4419-8a15-bd5882e04361",
"name": "Sticky Note - Email Alert",
"type": "n8n-nodes-base.stickyNote",
"position": [
-80,
400
],
"parameters": {
"width": 280,
"height": 348,
"content": "## π§ STEP 5: Internal Notification\n\n**Action:** Alerts assigned sales rep about the no-show\n\n**Email Contains:**\n- Customer name\n- Confirmation of Telegram message sent\n- Reschedule link for manual follow-up\n\n**Recipient:** Sales rep email from metadata"
},
"typeVersion": 1
},
{
"id": "2e2db44b-f716-4771-91ff-72f11659383a",
"name": "Sticky Note - Setup Requirements",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1472,
1056
],
"parameters": {
"width": 280,
"height": 300,
"content": "## βοΈ REQUIRED SETUP\n\n**Environment Variables:**\n- CALENDLY_USER_URI\n\n**Credentials:**\n- Telegram API (configured)\n- SMTP/Gmail (configured)\n\n**Metadata Fields Needed:**\n- contact_tags (for \"High Intent\")\n- telegram_id\n- rep_email"
},
"typeVersion": 1
},
{
"id": "4ffa2f77-867d-4bc8-8b4b-c13aa86e0bae",
"name": "Sticky Note - Benefits",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1472,
768
],
"parameters": {
"width": 280,
"height": 220,
"content": "## π‘ KEY BENEFITS\n\nβ
Automatic no-show detection\nβ
Immediate customer re-engagement\nβ
Sales team stays informed\nβ
Prioritizes high-value leads\nβ
Reduces manual follow-up work\nβ
Increases reschedule rate"
},
"typeVersion": 1
},
{
"parameters": {
"operation": "verify",
"email": "={{ $json.metadata ? $json.metadata.rep_email : 'sales@yourcompany.com' }}",
"additionalOptions": {}
},
"type": "n8n-nodes-billionverify.billionVerify",
"typeVersion": 1,
"position": [
-296,
768
],
"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": [
-116,
768
],
"name": "IF deliverable"
}
],
"connections": {
"Hourly Check Trigger": {
"main": [
[
{
"node": "Get Active Calendly Appointments",
"type": "main",
"index": 0
}
]
]
},
"Check If High Intent Lead": {
"main": [
[
{
"node": "Send Reschedule Link via Telegram",
"type": "main",
"index": 0
}
]
]
},
"Get Active Calendly Appointments": {
"main": [
[
{
"node": "Filter No-Show Appointments (30+ min past)",
"type": "main",
"index": 0
}
]
]
},
"Send Reschedule Link via Telegram": {
"main": [
[
{
"node": "Verify Email (BillionVerify)",
"type": "main",
"index": 0
}
]
]
},
"Filter No-Show Appointments (30+ min past)": {
"main": [
[
{
"node": "Check If High Intent Lead",
"type": "main",
"index": 0
}
]
]
},
"Verify Email (BillionVerify)": {
"main": [
[
{
"node": "IF deliverable",
"type": "main",
"index": 0
}
]
]
},
"IF deliverable": {
"main": [
[
{
"node": "Alert Sales Rep via Email",
"type": "main",
"index": 0
}
],
[]
]
}
},
"settings": {
"executionOrder": "v1"
}
}When to use this
- Cleaning a list before a Calendly send or sync.
- Protecting Calendly deliverability and sender reputation.
- Keeping bounce rates low so your sending is never throttled.
FAQ
Why verify before sending in Calendly?
Verifying first keeps your bounce rate low, which protects your sender reputation and your results.
How do I import this workflow?
Download the JSON, then in n8n go to Workflows β Import from File (or paste it). Install the BillionVerify community node and add your API key credential.
What happens to risky or catch-all addresses?
They are routed to the false branch and excluded from the send. You decide whether to retry, review, or drop them.
Add verification to your workflow
Create a free account, grab your API key, and stop bounces before they happen.
Get started free