{
  "nodes": [
    {
      "id": "acabbd66-4d43-42ca-9d07-a463e7d5685a",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        6336,
        7360
      ],
      "parameters": {
        "color": 3,
        "width": 564,
        "height": 480,
        "content": "### How it works\nThis workflow automates outbound lead qualification calls using **Vapi AI**. \n\n1. **Trigger:** Every 1 minute, it fetches leads from Airtable marked as 'TBC'.\n2. **Action:** It sends lead data to Vapi to initiate a voice call.\n3. **Feedback:** A Webhook receives the 'end-of-call-report' from Vapi.\n4. **Logic:** The workflow categorizes the result (Answered, Voicemail, or Failed) and updates Airtable.\n5. **Retry:** If a voicemail is detected, it schedules follow-up calls (Attempt #2 after 1 min, Attempt #3 after 24 hours).\n\n### Setup steps\n1. **Airtable:** Create a base with fields: `First Name`, `Mobile`, `Status`, `Attempt`, and `Summary`.\n2. **Vapi:** Add your `Assistant ID` and `Phone Number ID` in the HTTP Request nodes.\n3. **Credentials:** Set up Header Auth in n8n for Vapi (Name: `Authorization`, Value: `Bearer YOUR_VAPI_KEY`)."
      },
      "typeVersion": 1
    },
    {
      "id": "495ebfca-789c-476e-ac5c-379366a047c2",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        6992,
        7568
      ],
      "parameters": {
        "color": 7,
        "width": 1360,
        "height": 250,
        "content": "## SECTION 1: OUTBOUND SCHEDULER"
      },
      "typeVersion": 1
    },
    {
      "id": "92689ad6-5671-4d08-8158-c061cfd4bfe1",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        6352,
        7904
      ],
      "parameters": {
        "color": 7,
        "width": 2492,
        "height": 786,
        "content": "## SECTION 2: RESULTS CALLBACK & RETRY LOGIC"
      },
      "typeVersion": 1
    },
    {
      "id": "1d7207f2-a591-4695-afe0-7614a1a8b17d",
      "name": "Schedule Every Minute",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        7072,
        7632
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "minutes",
              "minutesInterval": 1
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "0b1241f0-a87d-42c0-8b48-f0c932b73e0c",
      "name": "Fetch TBC Leads",
      "type": "n8n-nodes-base.airtable",
      "position": [
        7344,
        7632
      ],
      "parameters": {
        "base": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_BASE_ID"
        },
        "limit": 10,
        "table": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_TABLE_ID"
        },
        "options": {},
        "operation": "search",
        "returnAll": false,
        "filterByFormula": "({Status} ='TBC')"
      },
      "typeVersion": 2.1
    },
    {
      "id": "4eb8e9cc-23f5-478b-869a-e87b1d212e6d",
      "name": "Prepare Call Metadata",
      "type": "n8n-nodes-base.set",
      "position": [
        7600,
        7632
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "fdc97028-eb65-45f0-9b3f-d86d7cf0e5cb",
              "name": "ID",
              "type": "string",
              "value": "={{ $json.id }}"
            },
            {
              "id": "340dd9b3-9799-4997-8d2b-d445282b2ee6",
              "name": "First Name",
              "type": "string",
              "value": "={{ $json[\"First Name\"] }}"
            },
            {
              "id": "d453c719-f462-449c-81eb-a55c4a29db5c",
              "name": "Mobile",
              "type": "string",
              "value": "={{ $json.Mobile }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "e5361d54-7f98-41c4-89d7-bd2916d61886",
      "name": "POST: Trigger Vapi Call",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        7840,
        7632
      ],
      "parameters": {
        "url": "https://api.vapi.ai/call",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"assistantId\": \"YOUR_ASSISTANT_ID\",\n  \"customer\": {\n    \"name\": \"{{ $json['First Name'] }}\",\n    \"number\": \"{{ $json.Mobile }}\"\n  },\n  \"phoneNumberId\": \"YOUR_PHONE_ID\"\n}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "Bearer YOUR_TOKEN_HERE"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "06b5d428-146c-47ce-a7ae-1e7a8f764e1c",
      "name": "Update Lead: In Progress",
      "type": "n8n-nodes-base.airtable",
      "position": [
        8112,
        7632
      ],
      "parameters": {
        "base": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_BASE_ID"
        },
        "table": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_TABLE_ID"
        },
        "columns": {
          "value": {
            "id": "={{ $('Prepare Call Metadata').item.json.ID }}",
            "Status": "In progress"
          },
          "mappingMode": "defineBelow"
        },
        "options": {},
        "operation": "update"
      },
      "typeVersion": 2.1
    },
    {
      "id": "7c11ac6f-0ab4-4000-8d8a-4361230ffb09",
      "name": "Vapi Callback Webhook",
      "type": "n8n-nodes-base.webhook",
      "position": [
        6448,
        8192
      ],
      "parameters": {
        "path": "vapi-callback",
        "options": {},
        "httpMethod": "POST"
      },
      "typeVersion": 2
    },
    {
      "id": "e961b67d-0f5d-4848-b58c-db998772adf9",
      "name": "Log Raw Call Data",
      "type": "n8n-nodes-base.airtable",
      "position": [
        6848,
        8064
      ],
      "parameters": {
        "base": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_BASE_ID"
        },
        "table": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_TABLE_ID"
        },
        "columns": {
          "value": {
            "id": "={{ $json.body.message.call.id }}",
            "recording": "={{ $json.body.message.recordingUrl }}",
            "transcript": "={{ $json.body.message.transcript }}"
          },
          "mappingMode": "defineBelow"
        },
        "options": {},
        "operation": "create"
      },
      "typeVersion": 2.1
    },
    {
      "id": "307b5aeb-0184-4a7b-889b-3e0ba43ee9dd",
      "name": "Update: Call Connected",
      "type": "n8n-nodes-base.airtable",
      "position": [
        7488,
        8048
      ],
      "parameters": {
        "base": {
          "value": "YOUR_BASE_ID"
        },
        "table": {
          "value": "YOUR_TABLE_ID"
        },
        "columns": {
          "value": {
            "id": "={{ $json.id }}",
            "Status": "Called",
            "Attempt": "#Success",
            "Summary": "={{ $('Is End Report?').item.json.body.message.analysis.summary }}"
          }
        },
        "options": {},
        "operation": "update"
      },
      "typeVersion": 2.1
    },
    {
      "id": "b4de198b-1345-49a0-98a0-fb8477fc29d7",
      "name": "Update: Call Failed",
      "type": "n8n-nodes-base.airtable",
      "position": [
        7664,
        8448
      ],
      "parameters": {
        "base": {
          "value": "YOUR_BASE_ID"
        },
        "table": {
          "value": "YOUR_TABLE_ID"
        },
        "columns": {
          "value": {
            "id": "={{ $json.id }}",
            "Status": "Failed",
            "Summary": "={{ $('Is End Report?').item.json.body.message.analysis.summary }}"
          }
        },
        "options": {},
        "operation": "update"
      },
      "typeVersion": 2.1
    },
    {
      "id": "dc4b6b1b-d4c2-4601-a8dc-a34019f14f79",
      "name": "Update: Lead Unreachable",
      "type": "n8n-nodes-base.airtable",
      "position": [
        8192,
        8368
      ],
      "parameters": {
        "base": {
          "value": "YOUR_BASE_ID"
        },
        "table": {
          "value": "YOUR_TABLE_ID"
        },
        "columns": {
          "value": {
            "id": "={{ $json.id }}",
            "Status": "Voicemail",
            "Attempt": "Unreachable"
          }
        },
        "options": {},
        "operation": "update"
      },
      "typeVersion": 2.1
    },
    {
      "id": "f8e543fc-f2a7-41ba-9c0f-9a1271c0a098",
      "name": "Log: Voicemail Attempt 3",
      "type": "n8n-nodes-base.airtable",
      "position": [
        8592,
        8160
      ],
      "parameters": {
        "base": {
          "value": "YOUR_BASE_ID"
        },
        "table": {
          "value": "YOUR_TABLE_ID"
        },
        "columns": {
          "value": {
            "id": "={{ $json.id }}",
            "Status": "Voicemail",
            "Attempt": "#3"
          }
        },
        "options": {},
        "operation": "update"
      },
      "typeVersion": 2.1
    },
    {
      "id": "8db5bef3-c0f6-4a81-83d8-4eda73631e07",
      "name": "Log: Voicemail Attempt 2",
      "type": "n8n-nodes-base.airtable",
      "position": [
        8592,
        7936
      ],
      "parameters": {
        "base": {
          "value": "YOUR_BASE_ID"
        },
        "table": {
          "value": "YOUR_TABLE_ID"
        },
        "columns": {
          "value": {
            "id": "={{ $json.id }}",
            "Status": "Voicemail",
            "Attempt": "#2"
          }
        },
        "options": {},
        "operation": "update"
      },
      "typeVersion": 2.1
    },
    {
      "id": "7ac2c94b-8fa2-4b8d-81fd-d2a77a7f9f2f",
      "name": "Filter: Was Answered?",
      "type": "n8n-nodes-base.if",
      "position": [
        7072,
        8064
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "conditions": [
            {
              "operator": {
                "type": "string",
                "operation": "notEquals"
              },
              "leftValue": "={{ $json.fields['ended reason'] }}",
              "rightValue": "customer-did-not-answer"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "76edddbb-bc4a-4dae-bb1a-c42573757bbf",
      "name": "Check: Is Voicemail?",
      "type": "n8n-nodes-base.if",
      "position": [
        7200,
        8240
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "conditions": [
            {
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $('Is End Report?').item.json.body.message.endedReason }}",
              "rightValue": "voicemail"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "137a3824-872a-4ada-a5af-c5cfc5d23b44",
      "name": "If First Call",
      "type": "n8n-nodes-base.if",
      "position": [
        7600,
        8240
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "conditions": [
            {
              "operator": {
                "type": "string",
                "operation": "notExists"
              },
              "leftValue": "={{ $json.Attempt }}"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "a2bef2bb-38ba-4cca-a9ee-e67129b0546b",
      "name": "If Second Call",
      "type": "n8n-nodes-base.if",
      "position": [
        7776,
        8240
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "conditions": [
            {
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.Attempt }}",
              "rightValue": "#1"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "dbe8a201-dbaf-416f-b81f-52b647434e30",
      "name": "If Third Call",
      "type": "n8n-nodes-base.if",
      "position": [
        8000,
        8240
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "conditions": [
            {
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.Attempt }}",
              "rightValue": "#2"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "4394485c-5df2-4f10-90da-874400604e09",
      "name": "Retry: Call #2",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        8368,
        7936
      ],
      "parameters": {
        "url": "https://api.vapi.ai/call",
        "method": "POST",
        "options": {},
        "jsonBody": "{\n \"assistantId\": \"YOUR_ID\",\n \"customer\": {\"name\": \"{{ $json.fields['First Name'] }}\", \"number\": \"{{ $json.fields.Mobile }}\"}\n}",
        "sendBody": true,
        "specifyBody": "json"
      },
      "typeVersion": 4.2
    },
    {
      "id": "d7f6f489-6555-4dd1-930b-cf2ca8a1fc0e",
      "name": "Retry: Call #3",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        8368,
        8160
      ],
      "parameters": {
        "url": "https://api.vapi.ai/call",
        "method": "POST",
        "options": {},
        "jsonBody": "{\n \"assistantId\": \"YOUR_ID\",\n \"customer\": {\"name\": \"{{ $json['First Name'] }}\", \"number\": \"{{ $json.Mobile }}\"}\n}",
        "sendBody": true,
        "specifyBody": "json"
      },
      "typeVersion": 4.2
    },
    {
      "id": "a6eb0235-0d7c-4f20-9e13-aa2877fbec29",
      "name": "Get Lead ID #1",
      "type": "n8n-nodes-base.airtable",
      "position": [
        7296,
        8048
      ],
      "parameters": {
        "base": {
          "value": "YOUR_BASE_ID"
        },
        "table": {
          "value": "YOUR_TABLE_ID"
        },
        "options": {},
        "operation": "search",
        "filterByFormula": "=({Mobile} = '{{ $(\"Is End Report?\").item.json.body.message.call.customer.number }}')"
      },
      "typeVersion": 2.1
    },
    {
      "id": "eb23f1f5-fc2d-4501-b2f3-9fd4066e4c73",
      "name": "Get Lead ID #2",
      "type": "n8n-nodes-base.airtable",
      "position": [
        7408,
        8240
      ],
      "parameters": {
        "base": {
          "value": "YOUR_BASE_ID"
        },
        "table": {
          "value": "YOUR_TABLE_ID"
        },
        "options": {},
        "operation": "search",
        "filterByFormula": "=({Mobile} = '{{ $(\"Is End Report?\").item.json.body.message.call.customer.number }}')"
      },
      "typeVersion": 2.1
    },
    {
      "id": "0a4e8d31-45df-4a93-9482-2f8234e37a5d",
      "name": "Get Lead ID #3",
      "type": "n8n-nodes-base.airtable",
      "position": [
        7488,
        8448
      ],
      "parameters": {
        "base": {
          "value": "YOUR_BASE_ID"
        },
        "table": {
          "value": "YOUR_TABLE_ID"
        },
        "options": {},
        "operation": "search",
        "filterByFormula": "=({Mobile} = '{{ $(\"Is End Report?\").item.json.body.message.call.customer.number }}')"
      },
      "typeVersion": 2.1
    },
    {
      "id": "644722b0-0955-433a-8c26-30bae23095ab",
      "name": "Is End Report?",
      "type": "n8n-nodes-base.if",
      "position": [
        6640,
        8192
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "conditions": [
            {
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.body.message.type }}",
              "rightValue": "end-of-call-report"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "dddb49bf-a5a5-4a4d-8aa8-f65693fd8f1e",
      "name": "Log: Voicemail Attempt 1",
      "type": "n8n-nodes-base.airtable",
      "position": [
        8000,
        7936
      ],
      "parameters": {
        "base": {
          "value": "YOUR_BASE_ID"
        },
        "table": {
          "value": "YOUR_TABLE_ID"
        },
        "columns": {
          "value": {
            "id": "={{ $json.id }}",
            "Status": "Voicemail",
            "Attempt": "#1"
          }
        },
        "options": {},
        "operation": "update"
      },
      "typeVersion": 2.1
    },
    {
      "id": "8698439a-afed-48bc-b247-b8f47d25d7ca",
      "name": "Wait: 1 Minute",
      "type": "n8n-nodes-base.wait",
      "position": [
        8192,
        7936
      ],
      "parameters": {
        "unit": "minutes",
        "amount": 1
      },
      "typeVersion": 1.1
    },
    {
      "id": "77cac942-d8c5-49bd-953d-9d841c441f8f",
      "name": "Wait: Next Day 4pm",
      "type": "n8n-nodes-base.wait",
      "position": [
        8192,
        8160
      ],
      "parameters": {
        "resume": "specificTime",
        "dateTime": "={{ $now.plus(1, \"day\").setZone(\"Australia/Sydney\").set({ hour: 16, minute: 0 }).toISO() }}"
      },
      "typeVersion": 1.1
    }
  ],
  "connections": {
    "If First Call": {
      "main": [
        [
          {
            "node": "Log: Voicemail Attempt 1",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "If Second Call",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If Third Call": {
      "main": [
        [
          {
            "node": "Wait: Next Day 4pm",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Update: Lead Unreachable",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Lead ID #1": {
      "main": [
        [
          {
            "node": "Update: Call Connected",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Lead ID #2": {
      "main": [
        [
          {
            "node": "If First Call",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Lead ID #3": {
      "main": [
        [
          {
            "node": "Update: Call Failed",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If Second Call": {
      "main": [
        [
          {
            "node": "Log: Voicemail Attempt 1",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "If Third Call",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Is End Report?": {
      "main": [
        [
          {
            "node": "Log Raw Call Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Retry: Call #2": {
      "main": [
        [
          {
            "node": "Log: Voicemail Attempt 2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Retry: Call #3": {
      "main": [
        [
          {
            "node": "Log: Voicemail Attempt 3",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait: 1 Minute": {
      "main": [
        [
          {
            "node": "Retry: Call #2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch TBC Leads": {
      "main": [
        [
          {
            "node": "Prepare Call Metadata",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Log Raw Call Data": {
      "main": [
        [
          {
            "node": "Filter: Was Answered?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait: Next Day 4pm": {
      "main": [
        [
          {
            "node": "Retry: Call #3",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check: Is Voicemail?": {
      "main": [
        [
          {
            "node": "Get Lead ID #2",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Get Lead ID #3",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter: Was Answered?": {
      "main": [
        [
          {
            "node": "Get Lead ID #1",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Check: Is Voicemail?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Call Metadata": {
      "main": [
        [
          {
            "node": "POST: Trigger Vapi Call",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Schedule Every Minute": {
      "main": [
        [
          {
            "node": "Fetch TBC Leads",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Vapi Callback Webhook": {
      "main": [
        [
          {
            "node": "Is End Report?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "POST: Trigger Vapi Call": {
      "main": [
        [
          {
            "node": "Update Lead: In Progress",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Log: Voicemail Attempt 1": {
      "main": [
        [
          {
            "node": "Wait: 1 Minute",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}