SAMPLE BUILD
n8n workflow: missed-call or form lead to Sheet + SMS-ready webhook
An n8n workflow you import from file: a webhook receives a missed-call or form lead, normalizes the fields, appends it to your Leads sheet, and (if there is a phone number) posts a text-back payload to the SMS tool of your choice.
How it flows
What it does
- Webhook node (POST /webhook/hwa-sample-lead) accepts form fields (name, phone, email, service, message) or a missed-call payload with from (caller number).
- "Normalize lead" maps either shape into one set of fields and stamps the time.
- "Append to Leads sheet" adds the row to the same 13-column Leads tab as the Lead Tracker sample.
- If a phone number is present, "Send to SMS-ready webhook" POSTs {to, name, message} to a URL you choose (your SMS provider, a Twilio Function, or another automation). The URL ships as an example.com placeholder: replace it with your own endpoint before going live.
Download
n8n workflow (.json)Install guide (PDF)
Install in short
- In n8n, open Workflows > Create workflow, then the three-dot menu > Import from File and choose hwa-n8n-missed-call-lead.workflow.json. (You can also paste the JSON straight onto the canvas.)
- Open Append to Leads sheet: create a Google Sheets credential, paste your spreadsheet URL in Document, keep Sheet = Leads, and check the column mapping.
- Open Send to SMS-ready webhook: replace https://example.com/replace-with-your-sms-webhook with your SMS tool's endpoint and adjust the JSON body to the fields it expects. Replace [Company] in the message.
- If your phone system sends different field names for missed calls, edit Normalize lead (e.g. caller number in "from").
- Click the webhook node > Listen for test event, send the test command below to the Test URL, and check each node's output.
- Save, then toggle the workflow Active. Use the Production URL in your phone system or form.
Test it
- Test command (replace the URL):
curl -X POST "YOUR_N8N_TEST_URL" -H "Content-Type: application/json" -d '{"from":"+15550100","caller_name":"Test Caller"}' - Expected: one Leads row with Source "Missed call" and Notes "Missed call"; the SMS node runs because a phone number is present.
Good to know
- Texting: only text people who contacted you, include opt-out wording, and honor STOP. US business texting from software needs A2P 10DLC registration through your provider.
- Built for n8n 1.x (Webhook v2, Edit Fields v3.4, Google Sheets v4.5, IF v2, HTTP Request v4.2).
Preview: hwa-n8n-missed-call-lead.workflow.json
{
"name": "HWA Sample - Missed-call or form lead to Sheet + SMS-ready webhook",
"nodes": [
{
"id": "e18bc360-1b3e-58ec-848e-44e1d6c91711",
"name": "Lead webhook",
"type": "n8n-nodes-base.webhook",
"typeVersion": 2,
"position": [
0,
0
],
"webhookId": "f25880be-5ba5-55a5-8bf7-9fafbb9255e1",
"parameters": {
"httpMethod": "POST",
"path": "hwa-sample-lead",
"responseMode": "onReceived",
"options": {}
}
},
{
"id": "ecc405ba-62c6-5f69-9658-9fbd56d8b7af",
"name": "Normalize lead",
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
220,
0
],
"parameters": {
"assignments": {
"assignments": [
{
"id": "3dc6ea5e-e01d-52f4-963c-4a29b93f30c9",
"name": "name",
"value": "={{ $json.body.name || $json.body.caller_name || 'Unknown caller' }}",
"type": "string"
},
{
"id": "df113f7b-c77c-5425-add0-0a66605ececa",
"name": "phone",
"value": "={{ ($json.body.phone || $json.body.from || '').toString().trim() }}",
"type": "string"
},
{
"id": "5bda2767-3164-5796-b5b5-5371f5a402cb",
"name": "email",
"value": "={{ $json.body.email || '' }}",
"type": "string"
},
{
"id": "5bf2c1bd-4142-54a8-828f-6241be722c6d",
"name": "service",
"value": "={{ $json.body.service || '' }}",
"type": "string"
},
{
"id": "896f39f5-36ce-5dec-ac26-948596a083ba",
"name": "message",
"value": "={{ $json.body.message || ($json.body.from ? 'Missed call' : '') }}",
"type": "string"
},
{
"id": "983a782c-889e-5444-92a1-d683293b94f3",
"name": "source",
"value": "={{ $json.body.source || ($json.body.from ? 'Missed call' : 'Web form') }}",
"type": "string"
},
{
"id": "c7733941-699a-5bfe-bf21-13fe1e6a64d6",
"name": "received_at",
"value": "={{ $now.toFormat('yyyy-MM-dd HH:mm') }}",
"type": "string"
}
]
},
"options": {}
}
},
{
"id": "d7f462a5-745a-516e-885c-606a51dd5e9f",
"name": "Append to Leads sheet",
"type": "n8n-nodes-base.googleSheets",
"typeVersion": 4.5,
"position": [
440,
0
],
"parameters": {
"operation": "append",
"documentId": {
"__rl": true,
"value": "",
"mode": "url"
},
"sheetName": {
"__rl": true,
"value": "Leads",
"mode": "name"
},
"columns": {
"mappingMode": "defineBelow",
"value": {
"Created": "={{ $json.received_at }}",
"Name": "={{ $json.name }}",
"Phone": "={{ $json.phone }}",
"Email": "={{ $json.email }}",
"Source": "={{ $json.source }}",
"Service": "={{ $json.service }}",
"Status": "New",
"Next Step": "Text back + call back",
"Last Updated": "={{ $json.received_at }}",
"Notes": "={{ $json.message }}"
},
"matchingColumns": [],
"schema": [
{
"id": "Lead ID",
"displayName": "Lead ID",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsed": true
},
{
"id": "Created",
"displayName": "Created",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsed": true
},
{
"id": "Name",
"displayName": "Name",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsed": true
},
{
"id": "Phone",
"displayName": "Phone",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsed": true
},
{
"id": "Email",
"displayName": "Email",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsed": true
},
{
"id": "Source",
"displayName": "Source",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsed": true
},
{
"id": "Service",
"displayName": "Service",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsed": true
},
{
"id": "Status",
"displayName": "Status",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsed": true
},
{
"id": "Next Step",
"displayName": "Next Step",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsed": true
},
{
"id": "Last Contact",
"displayName": "Last Contact",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsed": true
},
{
"id": "Last Updated",
"displayName": "Last Updated",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsed": true
},
{
"id": "Stale?",
"displayName": "Stale?",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsed": true
},
{
"id": "Notes",
"displayName": "Notes",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsed": true
}
]
},
"options": {}
}
},
{
"id": "2caab085-2210-560e-901b-13dbb6534647",
"name": "Has phone number?",
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [
660,
0
],
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "loose"
},
"conditions": [
{
"id": "fcd4417c-e586-5cdd-84fb-702d4a9f134f",
"leftValue": "={{ $('Normalize lead').item.json.phone }}",
"rightValue": "",
"operator": {
"type": "string",
"operation": "notEmpty",
"singleValue": true
}
}
],
"combinator": "and"
},
"options": {}
}
},
{
"id": "e4b5ed78-3c5a-5e21-a3ab-d95e2cf85a05",
"name": "Send to SMS-ready webhook",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
880,
-100
],
"parameters": {
"method": "POST",
"url": "https://example.com/replace-with-your-sms-webhook",
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={{ JSON.stringify({ to: $('Normalize lead').item.json.phone, name: $('Normalize lead').item.json.name, message: 'Hi, sorry we missed you. This is [Company]. What can we help with? Reply here and we will call you back shortly. Reply STOP to opt out.' }) }}",
"options": {}
}
}
],
"connections": {
"Lead webhook": {
"main": [
[
{
"node": "Normalize lead",
"type": "main",
"index": 0
}
]
]
},
"Normalize lead": {
"main": [
[
{
"node": "Append to Leads sheet",
"type": "main",
"index": 0
}
]
]
},
"Append to Leads sheet": {
"main": [
[
{
"node": "Has phone number?",
"type": "main",
"index": 0
}
]
]
},
"Has phone number?": {
"main": [
[
{
"node": "Send to SMS-ready webhook",
"type": "main",
"index": 0
}
],
[]
]
}
},
"settings": {
"executionOrder": "v1"
},
"pinData": {},
"meta": {
"templateCredsSetupCompleted": false
},
"active": false
}This is a free sample to copy and adapt, not a managed service; no support or warranty. Test with sample data first.
Built with AI assistance, reviewed before delivery.