{
  "name": "Missed Call → WhatsApp Recovery — turn missed calls into conversations",
  "nodes": [
    {
      "parameters": {
        "content": "## Missed Call → WhatsApp Recovery (free)\n\nEvery phone call you miss becomes a WhatsApp conversation within seconds, and gets logged so you can see how many calls you were losing.\n\n**Setup (10 min):**\n1. Point your phone system's *missed call / no-answer* webhook at the Webhook node URL. Works with Twilio (`StatusCallback` with `no-answer`/`busy`), CallRail, JustCall, 3CX, or any system that can POST on a missed call.\n2. Paste your WhatsApp API key in the HTTP Request node (Wati shown; respond.io/AiSensy: swap URL).\n3. Create and approve a WhatsApp template `missed_call_recovery` (example text: \"Sorry we missed your call! How can we help?\").\n4. Connect Google Sheets to see your missed-call volume — most businesses are shocked by this number.\n\n**Expected payload:** `{ \"caller\": \"+15551234567\", \"called_at\": \"...\", \"line\": \"sales\" }`\nTwilio users: map `From` → caller in the Set node.\n\nDealership pack with vehicle-interest capture + day 1/3/7 cadence:\nhttps://stackpick-b8s.pages.dev/templates/\n\nAI answering instead (costs ~$0.11/min, compared here):\nhttps://stackpick-b8s.pages.dev/calculators/ai-voice-agent-cost/",
        "height": 560,
        "width": 420
      },
      "id": "note-setup",
      "name": "Setup notes",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [-720, -160]
    },
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "missed-call",
        "options": {}
      },
      "id": "webhook-missed",
      "name": "Missed call (webhook)",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [-240, 80],
      "webhookId": "missed-call"
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "b1",
              "name": "caller",
              "value": "={{ ($json.body.caller || $json.body.From || '').replace(/[^+\\d]/g, '') }}",
              "type": "string"
            },
            {
              "id": "b2",
              "name": "line",
              "value": "={{ $json.body.line || $json.body.To || 'main' }}",
              "type": "string"
            },
            {
              "id": "b3",
              "name": "missed_at",
              "value": "={{ $json.body.called_at || $now.toISO() }}",
              "type": "string"
            }
          ]
        },
        "options": {}
      },
      "id": "set-normalize",
      "name": "Normalize call event",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [-20, 80]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "typeValidation": "strict",
            "version": 2
          },
          "conditions": [
            {
              "id": "c1",
              "leftValue": "={{ $json.caller }}",
              "rightValue": "",
              "operator": {
                "type": "string",
                "operation": "notEmpty",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "if-valid",
      "name": "Has caller number?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [200, 80]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "=https://live-mt-server.wati.io/YOUR_TENANT_ID/api/v1/sendTemplateMessage?whatsappNumber={{ $json.caller }}",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "Bearer YOUR_WATI_API_KEY"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify({ template_name: 'missed_call_recovery', broadcast_name: 'missed_call_recovery', parameters: [] }) }}",
        "options": {}
      },
      "id": "http-recovery",
      "name": "Send WhatsApp recovery message",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [440, 0]
    },
    {
      "parameters": {
        "operation": "append",
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": ""
        },
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": ""
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "missed_at": "={{ $('Normalize call event').item.json.missed_at }}",
            "caller": "={{ $('Normalize call event').item.json.caller }}",
            "line": "={{ $('Normalize call event').item.json.line }}",
            "recovery_sent": "yes"
          }
        },
        "options": {}
      },
      "id": "sheets-log",
      "name": "Log missed call",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.5,
      "position": [660, 0]
    }
  ],
  "connections": {
    "Missed call (webhook)": {
      "main": [[{ "node": "Normalize call event", "type": "main", "index": 0 }]]
    },
    "Normalize call event": {
      "main": [[{ "node": "Has caller number?", "type": "main", "index": 0 }]]
    },
    "Has caller number?": {
      "main": [
        [{ "node": "Send WhatsApp recovery message", "type": "main", "index": 0 }],
        []
      ]
    },
    "Send WhatsApp recovery message": {
      "main": [[{ "node": "Log missed call", "type": "main", "index": 0 }]]
    }
  },
  "settings": {
    "executionOrder": "v1"
  },
  "pinData": {},
  "meta": {
    "templateCredsSetupCompleted": false
  }
}
