AutomationFlowsSlack & Telegram › Twilio Missed Call → Google Sheets Log & Slack Alert

Twilio Missed Call → Google Sheets Log & Slack Alert

Original n8n title: Recover Missed Calls with Twilio, Slack and Google Sheets

ByShashwat Singh @shashwatsingh on n8n.io

Never lose an inbound lead because someone missed the phone.

Webhook trigger★★★★☆ complexity13 nodesGoogle SheetsTwilioSlack
Slack & Telegram Trigger: Webhook Nodes: 13 Complexity: ★★★★☆ Added:

This workflow corresponds to n8n.io template #13535 — we link there as the canonical source.

This workflow follows the Google Sheets → Slack recipe pattern — see all workflows that pair these two integrations.

The workflow JSON

Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →

Download .json
{
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "nodes": [
    {
      "id": "f4fb7638-36e1-4b7c-a661-d7153a46af03",
      "name": "Skip - Call Was Answered",
      "type": "n8n-nodes-base.noOp",
      "position": [
        -416,
        560
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "458423f0-bbe4-45cd-a9ec-1a466e6381d9",
      "name": "Receive Missed Call Webhook",
      "type": "n8n-nodes-base.webhook",
      "notes": "No worker available",
      "position": [
        -864,
        464
      ],
      "parameters": {
        "path": "missed-calls",
        "options": {},
        "httpMethod": "POST"
      },
      "typeVersion": 2.1
    },
    {
      "id": "72cd9de6-675f-47c6-9f2f-e5b6c13da36b",
      "name": "Check Call Failed/Busy/No-Answer",
      "type": "n8n-nodes-base.if",
      "position": [
        -640,
        464
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "or",
          "conditions": [
            {
              "id": "72ae5243-9563-4ec1-b958-c66289082ebc",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.CallStatus }}",
              "rightValue": "no-answer"
            },
            {
              "id": "9c9d2c61-e6e4-4e16-829c-798eb19335fe",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.CallStatus }}",
              "rightValue": "busy"
            },
            {
              "id": "dc546949-4d0f-4f9a-a662-cc73e3021c69",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.CallStatus }}",
              "rightValue": "failed"
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "f4838746-3f2e-47fe-887f-ab1cecdfb2db",
      "name": "Check Business Hours",
      "type": "n8n-nodes-base.code",
      "position": [
        -416,
        368
      ],
      "parameters": {
        "jsCode": "// Use n8n's built-in $now which respects the n8n instance timezone\n// Set your timezone in n8n Settings > General > Timezone\nconst now = new Date();\n\n// Convert to your business timezone without luxon\nconst formatter = new Intl.DateTimeFormat('en-US', {\n  timeZone: 'America/New_York', // Change to your timezone\n  weekday: 'short',\n  hour: 'numeric',\n  hour12: false\n});\n\nconst parts = formatter.formatToParts(now);\nconst weekday = parts.find(p => p.type === 'weekday').value; // 'Mon', 'Tue', etc.\nconst hour = parseInt(parts.find(p => p.type === 'hour').value);\n\nconst isWeekday = !['Sat', 'Sun'].includes(weekday);\nconst isWorkingHour = hour >= 9 && hour < 17;\n\nreturn {\n  isBusinessHours: isWeekday && isWorkingHour\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "0819503f-36dd-421d-9a49-48a99b9314ad",
      "name": "Log Missed Call to Google Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -192,
        368
      ],
      "parameters": {
        "columns": {
          "value": {
            "To": "={{ $('Receive Missed Call Webhook').item.json.To }}",
            "SID": "={{ $('Receive Missed Call Webhook').item.json.CallSid }}",
            "Time": "={{ $now }}",
            "Direction": "={{ $('Receive Missed Call Webhook').item.json.Direction }}",
            "CallStatus": "={{ $('Receive Missed Call Webhook').item.json.CallStatus }}",
            "Lead Number": "={{ $('Receive Missed Call Webhook').item.json.From }}"
          },
          "schema": [
            {
              "id": "SID",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "SID",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Lead Number",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Lead Number",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "To",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "To",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "CallStatus",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "CallStatus",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Direction",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Direction",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Time",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Time",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1KJ4-6cNZduk71GyNVykqvg0_07VFn8eYsFUKEuwX-lQ/edit#gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1KJ4-6cNZduk71GyNVykqvg0_07VFn8eYsFUKEuwX-lQ",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1KJ4-6cNZduk71GyNVykqvg0_07VFn8eYsFUKEuwX-lQ/edit?usp=drivesdk",
          "cachedResultName": "Missed call recovery system"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "3f9cc7ed-8fc5-4833-97a1-d5b0109ad9ab",
      "name": "Is It Business Hours?",
      "type": "n8n-nodes-base.if",
      "position": [
        32,
        368
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "7d6cd1e2-e0f4-4a21-9ee0-696936514119",
              "operator": {
                "type": "boolean",
                "operation": "equals"
              },
              "leftValue": "={{ $('Check Business Hours').item.json.isBusinessHours }}",
              "rightValue": true
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "d022f704-5e65-4f30-be39-86597a502a8d",
      "name": "SMS - Call Back in 5 Minutes",
      "type": "n8n-nodes-base.twilio",
      "position": [
        256,
        272
      ],
      "parameters": {
        "to": "={{ $('Receive Missed Call Webhook').item.json.From }}",
        "from": "={{ $('Receive Missed Call Webhook').item.json.To }}",
        "message": "=Hi, we noticed your call. We missed it and will call you back as soon as possible, usually within the hour. Reply YES to confirm you are still available, or call us anytime at {{ $('Receive Missed Call Webhook').item.json.To }}. Reply STOP to opt out.",
        "options": {}
      },
      "typeVersion": 1
    },
    {
      "id": "71b26c9e-a542-4355-9364-cd2312fc8326",
      "name": "SMS - Will Contact in Business Hours",
      "type": "n8n-nodes-base.twilio",
      "position": [
        256,
        464
      ],
      "parameters": {
        "to": "={{ $('Receive Missed Call Webhook').item.json.From }}",
        "from": "={{ $('Receive Missed Call Webhook').item.json.To }}",
        "message": "=Hi, we noticed your call. Our team is currently outside business hours, Monday to Friday, 9am to 5pm ET. We will reach out first thing on the next business day. You can also call us back at {{ $('Receive Missed Call Webhook').item.json.To }}. Reply STOP to opt out.",
        "options": {}
      },
      "typeVersion": 1
    },
    {
      "id": "10303795-754a-449e-a2d7-0faa911f0318",
      "name": "Notify Team on Slack",
      "type": "n8n-nodes-base.slack",
      "position": [
        480,
        368
      ],
      "parameters": {
        "text": "=Missed call from {{ $('Receive Missed Call Webhook').item.json.From }} at {{ $now.format('hh:mm a') }}. Click to call back.",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "C0ABBRA98R3",
          "cachedResultName": "new-channel"
        },
        "otherOptions": {}
      },
      "credentials": {
        "slackApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.4
    },
    {
      "id": "fd720c49-849f-49c1-b144-74862aa40a61",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1472,
        16
      ],
      "parameters": {
        "width": 512,
        "height": 800,
        "content": "This workflow automatically recovers missed inbound calls so no potential lead is lost.\n\nWhen a call is missed in Twilio, the workflow captures the event, checks the call status, determines whether it occurred during business hours, logs the call to Google Sheets, sends an automatic SMS to the caller, and notifies your team in Slack.\n\nIt ensures callers receive immediate acknowledgment and your team has visibility for follow up.\n\n## How it works\n\n- Receives inbound call events from Twilio\n\n- Filters for failed, busy, or no answer calls\n\n- Checks whether the call happened during business hours\n\n- Logs call details to Google Sheets\n\n- Sends an SMS reply based on business hours\n\n- Notifies your team in Slack\n\n## Setup steps\n\n- Connect your Twilio account and set the webhook URL\n\n- Connect Google Sheets and choose your tracking sheet\n\n- Connect Slack and select a notification channel\n\n- Adjust business hours and timezone in the code node\n\n- Customize the SMS message if needed"
      },
      "typeVersion": 1
    },
    {
      "id": "c580a6c2-5def-4375-8a54-0a521391c35a",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -896,
        112
      ],
      "parameters": {
        "color": 7,
        "width": 416,
        "height": 624,
        "content": "## Call intake and filtering\n\nReceives inbound call events from Twilio via webhook. Filters for missed, busy, or failed calls and ignores answered ones. Only valid missed calls continue through the recovery flow to prevent unnecessary messages or notifications."
      },
      "typeVersion": 1
    },
    {
      "id": "9b4f1235-3327-46dd-96eb-3c1bafbe5f3f",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -464,
        112
      ],
      "parameters": {
        "color": 7,
        "width": 640,
        "height": 432,
        "content": "## Logging and business hour check\n\nLogs missed call details to Google Sheets for tracking and reporting. Then checks whether the call occurred during defined business hours to determine the correct SMS response logic."
      },
      "typeVersion": 1
    },
    {
      "id": "e358376d-2321-4fa9-bfcc-276602ab648b",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        192,
        112
      ],
      "parameters": {
        "color": 7,
        "width": 544,
        "height": 544,
        "content": "## Automated SMS and team notification\n\nSends an automatic SMS to the caller based on business hours, either promising a quick callback or setting next day expectations. Notifies the team in Slack with caller details so follow up can happen immediately."
      },
      "typeVersion": 1
    }
  ],
  "connections": {
    "Check Business Hours": {
      "main": [
        [
          {
            "node": "Log Missed Call to Google Sheets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Is It Business Hours?": {
      "main": [
        [
          {
            "node": "SMS - Call Back in 5 Minutes",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "SMS - Will Contact in Business Hours",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Receive Missed Call Webhook": {
      "main": [
        [
          {
            "node": "Check Call Failed/Busy/No-Answer",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "SMS - Call Back in 5 Minutes": {
      "main": [
        [
          {
            "node": "Notify Team on Slack",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Call Failed/Busy/No-Answer": {
      "main": [
        [
          {
            "node": "Check Business Hours",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Skip - Call Was Answered",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Log Missed Call to Google Sheets": {
      "main": [
        [
          {
            "node": "Is It Business Hours?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "SMS - Will Contact in Business Hours": {
      "main": [
        [
          {
            "node": "Notify Team on Slack",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

Credentials you'll need

Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.

Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

Never lose an inbound lead because someone missed the phone.

Source: https://n8n.io/workflows/13535/ — original creator credit. Request a take-down →

More Slack & Telegram workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

Slack & Telegram

This workflow is a complete, production-ready solution for recovering abandoned carts in Shopify stores using a multi-channel, multi-touch approach. It automates personalized follow-ups via Email, SMS

HTTP Request, Shopify, SendGrid +5
Slack & Telegram

Turn every sales meeting into a coaching opportunity. This workflow automatically analyzes tldv meeting recordings using OpenAI (GPT-4) to provide instant, actionable feedback to your sales team.

HTTP Request, Slack, Google Sheets
Slack & Telegram

Automated video processing system that monitors S3 for new uploads, generates thumbnails and preview clips, extracts metadata, transcodes to multiple formats, and distributes to CDN with webhook notif

HTTP Request, Google Sheets, Slack
Slack & Telegram

Eliminate manual data entry from your accounts payable process. This workflow transforms raw invoice scans into structured financial records by combining UploadToURL for hosting, AWS Textract for OCR

N8N Nodes Uploadtourl, HTTP Request, Google Sheets +1
Slack & Telegram

Connect Fireflies and WayinVideo to this workflow once and every recorded sales call automatically generates a set of training clips delivered to your Slack channel. The moment Fireflies finishes tran

HTTP Request, Google Sheets, Slack