This workflow corresponds to n8n.io template #skynetlabs-20 — we link there as the canonical source.
This workflow follows the Google Sheets → HTTP Request 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 →
{
"name": "20 - Clinic Missed Call WA Recovery",
"nodes": [
{
"parameters": {
"httpMethod": "POST",
"path": "twilio-missed-call",
"responseMode": "responseNode",
"options": {}
},
"id": "webhook-call",
"name": "Twilio status webhook",
"type": "n8n-nodes-base.webhook",
"typeVersion": 2,
"position": [
200,
300
]
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"typeValidation": "strict"
},
"conditions": [
{
"leftValue": "={{ $json.body.CallStatus }}",
"rightValue": "no-answer",
"operator": {
"type": "string",
"operation": "equals"
}
},
{
"leftValue": "={{ $json.body.Direction }}",
"rightValue": "inbound",
"operator": {
"type": "string",
"operation": "equals"
}
}
],
"combinator": "or"
}
},
"id": "if-missed",
"name": "If missed inbound",
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [
420,
300
]
},
{
"parameters": {
"operation": "lookup",
"documentId": {
"__rl": true,
"value": "REPLACE_ME_SHEET_ID",
"mode": "id"
},
"sheetName": {
"__rl": true,
"value": "patients_db",
"mode": "name"
},
"lookupColumn": "phone",
"lookupValue": "={{ $('Twilio status webhook').first().json.body.From }}",
"options": {}
},
"id": "patient-lookup",
"name": "Lookup patient",
"type": "n8n-nodes-base.googleSheets",
"typeVersion": 4.5,
"position": [
640,
300
],
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"url": "=https://api.cal.com/v1/availability",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"sendQuery": true,
"queryParameters": {
"parameters": [
{
"name": "eventTypeId",
"value": "REPLACE_ME_CALCOM_EVENT_ID"
},
{
"name": "dateFrom",
"value": "={{ $now.toISO() }}"
},
{
"name": "dateTo",
"value": "={{ $now.plus({days: 3}).toISO() }}"
}
]
},
"options": {}
},
"id": "fetch-slots",
"name": "Fetch Cal.com slots",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
860,
300
],
"credentials": {
"httpHeaderAuth": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"jsCode": "const slots = $input.first().json.busy ? [] : ($input.first().json.availabilities || []);\nconst now = new Date();\nconst nextTwo = slots.filter(s => new Date(s.start) > now).slice(0, 2);\nconst formatSlot = (s) => {\n const d = new Date(s.start);\n return d.toLocaleString('en-US', {weekday: 'short', month: 'short', day: 'numeric', hour: 'numeric', minute: '2-digit'});\n};\nconst patient = $('Lookup patient').first().json;\nconst from = $('Twilio status webhook').first().json.body.From;\nreturn [{\n json: {\n patient_name: patient.full_name || 'there',\n patient_phone: from,\n is_returning: !!patient.last_visit_at,\n slot_1: nextTwo[0] ? formatSlot(nextTwo[0]) : 'tomorrow 10:00 AM',\n slot_2: nextTwo[1] ? formatSlot(nextTwo[1]) : 'tomorrow 2:00 PM',\n booking_link: `https://cal.com/REPLACE_ME_CALCOM_USER/REPLACE_ME_EVENT_SLUG?phone=${encodeURIComponent(from)}`\n }\n}];"
},
"id": "compose",
"name": "Compose WA params",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1080,
300
]
},
{
"parameters": {
"resource": "message",
"operation": "send",
"from": "whatsapp:REPLACE_ME_TWILIO_FROM",
"to": "=whatsapp:{{ $json.patient_phone }}",
"toWhatsapp": true,
"message": "=Hi {{ $json.patient_name }}, sorry we missed your call to the clinic. Two slots open in the next 3 days: {{ $json.slot_1 }} or {{ $json.slot_2 }}. Book direct here: {{ $json.booking_link }}. If urgent, reply URGENT and the front desk will call back within 30 min.",
"options": {
"contentSid": "REPLACE_ME_WA_TEMPLATE_SID"
}
},
"id": "twilio-wa",
"name": "Send WA recovery",
"type": "n8n-nodes-base.twilio",
"typeVersion": 1,
"position": [
1300,
300
],
"credentials": {
"twilioApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"method": "POST",
"url": "https://services.leadconnectorhq.com/contacts/upsert",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"locationId\": \"REPLACE_ME_GHL_LOCATION\",\n \"phone\": \"{{ $('Compose WA params').first().json.patient_phone }}\",\n \"firstName\": \"{{ $('Compose WA params').first().json.patient_name }}\",\n \"tags\": [\"missed-call-recovered\", \"wa-followup-sent\"],\n \"source\": \"clinic-missed-call-bot\"\n}",
"options": {}
},
"id": "ghl-upsert",
"name": "Upsert to GHL CRM",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
1520,
300
],
"credentials": {
"httpHeaderAuth": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"operation": "append",
"documentId": {
"__rl": true,
"value": "REPLACE_ME_SHEET_ID",
"mode": "id"
},
"sheetName": {
"__rl": true,
"value": "missed_call_log",
"mode": "name"
},
"columns": {
"mappingMode": "defineBelow",
"value": {
"ts": "={{ $now.toISO() }}",
"from_phone": "={{ $('Compose WA params').first().json.patient_phone }}",
"patient_name": "={{ $('Compose WA params').first().json.patient_name }}",
"is_returning": "={{ $('Compose WA params').first().json.is_returning }}",
"slot_1_offered": "={{ $('Compose WA params').first().json.slot_1 }}",
"slot_2_offered": "={{ $('Compose WA params').first().json.slot_2 }}",
"wa_sid": "={{ $('Send WA recovery').first().json.sid }}",
"status": "wa_sent"
}
},
"options": {}
},
"id": "sheet-log",
"name": "Log missed call",
"type": "n8n-nodes-base.googleSheets",
"typeVersion": 4.5,
"position": [
1740,
300
],
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
}
}
],
"connections": {
"Twilio status webhook": {
"main": [
[
{
"node": "If missed inbound",
"type": "main",
"index": 0
}
]
]
},
"If missed inbound": {
"main": [
[
{
"node": "Lookup patient",
"type": "main",
"index": 0
}
],
[]
]
},
"Lookup patient": {
"main": [
[
{
"node": "Fetch Cal.com slots",
"type": "main",
"index": 0
}
]
]
},
"Fetch Cal.com slots": {
"main": [
[
{
"node": "Compose WA params",
"type": "main",
"index": 0
}
]
]
},
"Compose WA params": {
"main": [
[
{
"node": "Send WA recovery",
"type": "main",
"index": 0
}
]
]
},
"Send WA recovery": {
"main": [
[
{
"node": "Upsert to GHL CRM",
"type": "main",
"index": 0
}
]
]
},
"Upsert to GHL CRM": {
"main": [
[
{
"node": "Log missed call",
"type": "main",
"index": 0
}
]
]
}
},
"settings": {
"executionOrder": "v1"
},
"meta": {
"templateId": "skynetlabs-20"
},
"tags": [
{
"name": "skynetlabs-pack"
},
{
"name": "healthcare"
},
{
"name": "clinic-ops"
},
{
"name": "whatsapp"
}
]
}
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.
googleSheetsOAuth2ApihttpHeaderAuthtwilioApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
20 - Clinic Missed Call WA Recovery. Uses googleSheets, httpRequest, twilio. Webhook trigger; 8 nodes.
Source: https://github.com/waseemnasir2k26/skynet-automation-pack/blob/main/n8n/20-clinic-missed-call-wa-recovery.json — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
Are you tired of manually entering open house visitor information into your CRM? Losing hot leads because you didn't follow up fast enough? This powerful n8n workflow automatically syncs every SignSna
16 - Abandoned Cart WA Voice Note. Uses httpRequest, awsS3, twilio, googleSheets. Webhook trigger; 9 nodes.
This template is ideal for solo store owners, eCommerce marketers, automation beginners, or anyone using Shopify and Gmail who wants to recover lost revenue without coding.
[SANTOBET] FLUXO TODO - BACKUP. Uses googleSheets, httpRequest, googleSheetsTrigger. Webhook trigger; 57 nodes.
FLUXO DISPARO DATA E HORA. Uses itemLists, googleSheets, httpRequest. Webhook trigger; 48 nodes.