{
  "name": "Instant web-form reply (Insurance Agents)",
  "nodes": [
    {
      "id": "857a2b50-26d4-550f-8b27-6914040eeab3",
      "name": "New lead from your form",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [
        0,
        0
      ],
      "parameters": {
        "httpMethod": "POST",
        "path": "new-lead",
        "responseMode": "responseNode",
        "options": {}
      },
      "webhookId": "779bbdb8-6d55-55d7-9e2a-747a7b624709"
    },
    {
      "id": "c32cab39-d7b2-52d5-99a9-5537f196d525",
      "name": "Incoming text",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [
        0,
        300
      ],
      "parameters": {
        "httpMethod": "POST",
        "path": "new-lead-sms",
        "responseMode": "responseNode",
        "options": {}
      },
      "webhookId": "b7c5b221-3a39-5bfe-ba09-76ca514ccd8a"
    },
    {
      "id": "1e37c7c7-d9be-51d2-9ddb-56b94eae39df",
      "name": "Config (edit me)",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        220,
        140
      ],
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "1e4952c8-83f4-58b3-8140-6099f327956e",
              "name": "business_name",
              "value": "YOUR BUSINESS NAME",
              "type": "string"
            },
            {
              "id": "60d0dbca-1de9-5959-8a85-7d71209516b2",
              "name": "booking_link",
              "value": "https://YOUR-BOOKING-LINK",
              "type": "string"
            },
            {
              "id": "47f1efd9-079a-54ad-8260-32f5d9c5d7e2",
              "name": "hours",
              "value": "Mon-Fri 8am-6pm",
              "type": "string"
            },
            {
              "id": "72425189-094d-5a09-9b36-89697ab7313c",
              "name": "owner_email",
              "value": "you@example.com",
              "type": "string"
            },
            {
              "id": "0a507618-3efb-5df1-9bd2-606a95a449d0",
              "name": "owner_cell",
              "value": "+15555550100",
              "type": "string"
            },
            {
              "id": "5d16b27c-1e63-574f-a589-6fdd0b28db7d",
              "name": "twilio_number",
              "value": "+15555550199",
              "type": "string"
            },
            {
              "id": "f9aa566f-366a-53cf-a187-4be8e76b8ad7",
              "name": "twilio_auth_token",
              "value": "PASTE_YOUR_TWILIO_AUTH_TOKEN",
              "type": "string"
            },
            {
              "id": "13134d1d-8215-595b-974d-4e418547057b",
              "name": "twilio_sms_webhook_url",
              "value": "https://YOUR-N8N-URL/webhook/new-lead-sms",
              "type": "string"
            }
          ]
        },
        "includeOtherFields": true,
        "options": {}
      }
    },
    {
      "id": "2cbb4645-9c1c-5e97-ba8e-66c8d7ae740f",
      "name": "Form or text?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        440,
        140
      ],
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": false,
            "leftValue": "",
            "typeValidation": "loose"
          },
          "conditions": [
            {
              "id": "f4eb7a9b-fead-521f-bc38-44778a8b24a8",
              "leftValue": "={{ $json.body.MessageSid }}",
              "rightValue": "",
              "operator": {
                "type": "string",
                "operation": "empty",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      }
    },
    {
      "id": "76ca22cc-c857-52d1-88cb-e64238328e75",
      "name": "Map form fields",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        660,
        0
      ],
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "46c0fae7-9a77-5deb-8383-b47cf8b78f07",
              "name": "lead_name",
              "value": "={{ $json.body.name || $json.body.first_name || 'there' }}",
              "type": "string"
            },
            {
              "id": "1a30ba7a-8c29-5d88-aa01-86a95f33455c",
              "name": "lead_phone",
              "value": "={{ String($json.body.phone || '').replace(/[^0-9]/g, '').replace(/^1?(\\d{10})$/, '+1$1') }}",
              "type": "string"
            },
            {
              "id": "cd890c18-7de8-5d10-9b66-e339a6fdb157",
              "name": "lead_email",
              "value": "={{ $json.body.email || '' }}",
              "type": "string"
            },
            {
              "id": "aa347fdf-9545-5832-b5e9-5e916362e9ab",
              "name": "lead_message",
              "value": "={{ $json.body.message || $json.body.details || '' }}",
              "type": "string"
            },
            {
              "id": "cc806048-f307-5400-bc9e-66c0d37d5bbf",
              "name": "honeypot",
              "value": "={{ $json.body.website || '' }}",
              "type": "string"
            }
          ]
        },
        "includeOtherFields": true,
        "options": {}
      }
    },
    {
      "id": "2c594af1-5931-58ae-8e53-e8ab3458fb2c",
      "name": "Tell the form it worked",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.1,
      "position": [
        880,
        0
      ],
      "parameters": {
        "respondWith": "text",
        "responseBody": "{\"ok\": true}",
        "options": {
          "responseHeaders": {
            "entries": [
              {
                "name": "Content-Type",
                "value": "application/json"
              }
            ]
          }
        }
      }
    },
    {
      "id": "20ea9a66-e3ec-551b-8ee7-7234e40bf803",
      "name": "Spam check",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        1100,
        0
      ],
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": false,
            "leftValue": "",
            "typeValidation": "loose"
          },
          "conditions": [
            {
              "id": "e5ba6c7d-93ae-5a71-a595-a289bf462eae",
              "leftValue": "={{ $json.honeypot }}",
              "rightValue": "",
              "operator": {
                "type": "string",
                "operation": "empty",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      }
    },
    {
      "id": "0ffe8be1-1adb-5f89-bab0-0f104b6c83cd",
      "name": "AI writes reply",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "typeVersion": 1.8,
      "position": [
        1320,
        0
      ],
      "parameters": {
        "modelId": {
          "__rl": true,
          "value": "gpt-5-mini",
          "mode": "id"
        },
        "messages": {
          "values": [
            {
              "content": "You are the friendly front-desk assistant at a small independent insurance agency. You are not a licensed agent. Write one short, warm SMS reply (under 300 characters) to a person asking about insurance. Thank them, say a licensed agent will call them back, and offer the booking link. You may ask what type of coverage they'd like a quote on and a good time to call. Never quote, estimate or compare premiums or rates. Never explain, interpret, compare or recommend coverage, policies or carriers. Never say coverage is bound, active, changed or cancelled, and never promise a price or savings. Ask them not to text Social Security, driver's license, policy or bank numbers. If they mention an accident, injury, fire or other emergency, tell them to call 911 if anyone is hurt or in danger and to call the office. Sign off with the agency name.",
              "role": "system"
            },
            {
              "content": "=Business: {{ $('Config (edit me)').first().json.business_name }}\nHours: {{ $('Config (edit me)').first().json.hours }}\nBooking link: {{ $('Config (edit me)').first().json.booking_link }}\nLead name: {{ $('Map form fields').first().json.lead_name }}\nWhat they wrote: {{ $('Map form fields').first().json.lead_message }}"
            }
          ]
        },
        "options": {}
      },
      "credentials": {
        "openAiApi": {
          "id": "REPLACE_OPENAI_CREDENTIAL",
          "name": "OpenAI account (placeholder)"
        }
      }
    },
    {
      "id": "59c5d139-f1b6-5fc4-957e-04a3f9fb3ef9",
      "name": "Has a valid mobile number?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        1540,
        -160
      ],
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "loose"
          },
          "conditions": [
            {
              "id": "6a2d2131-e890-5ad3-b6bc-ab8e721626ee",
              "leftValue": "={{ $('Map form fields').first().json.lead_phone }}",
              "rightValue": "^\\+1\\d{10}$",
              "operator": {
                "type": "string",
                "operation": "regex"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      }
    },
    {
      "id": "94b14b07-6604-5528-b147-6f290200fc62",
      "name": "Text the lead",
      "type": "n8n-nodes-base.twilio",
      "typeVersion": 1,
      "position": [
        1760,
        -160
      ],
      "parameters": {
        "from": "={{ $('Config (edit me)').first().json.twilio_number }}",
        "to": "={{ $('Map form fields').first().json.lead_phone }}",
        "message": "={{ $('AI writes reply').first().json.message.content }}",
        "options": {}
      },
      "credentials": {
        "twilioApi": {
          "id": "REPLACE_TWILIO_CREDENTIAL",
          "name": "Twilio account (placeholder)"
        }
      }
    },
    {
      "id": "b3ce2e40-01d4-53d6-aa89-3f0ec0287036",
      "name": "Has an email?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        1540,
        40
      ],
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": false,
            "leftValue": "",
            "typeValidation": "loose"
          },
          "conditions": [
            {
              "id": "6a8e32d0-632b-599b-9d5c-52089972ec13",
              "leftValue": "={{ $('Map form fields').first().json.lead_email }}",
              "rightValue": "",
              "operator": {
                "type": "string",
                "operation": "notEmpty",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      }
    },
    {
      "id": "3216ed2f-ea1e-5b22-8aee-93f43ce30edc",
      "name": "Email the lead",
      "type": "n8n-nodes-base.gmail",
      "typeVersion": 2.1,
      "position": [
        1760,
        40
      ],
      "parameters": {
        "sendTo": "={{ $('Map form fields').first().json.lead_email }}",
        "subject": "=Thanks for reaching out to {{ $('Config (edit me)').first().json.business_name }}",
        "emailType": "text",
        "message": "={{ $('AI writes reply').first().json.message.content }}",
        "options": {}
      },
      "credentials": {
        "gmailOAuth2": {
          "id": "REPLACE_GMAIL_CREDENTIAL",
          "name": "Gmail account (placeholder)"
        }
      }
    },
    {
      "id": "27d56bcd-c072-5b34-9323-e8c0b0ce9990",
      "name": "Email the owner",
      "type": "n8n-nodes-base.gmail",
      "typeVersion": 2.1,
      "position": [
        1540,
        240
      ],
      "parameters": {
        "sendTo": "={{ $('Config (edit me)').first().json.owner_email }}",
        "subject": "=New lead: {{ $('Map form fields').first().json.lead_name }}",
        "emailType": "text",
        "message": "=Name: {{ $('Map form fields').first().json.lead_name }}\nPhone: {{ $('Map form fields').first().json.lead_phone }}\nEmail: {{ $('Map form fields').first().json.lead_email }}\nMessage: {{ $('Map form fields').first().json.lead_message }}\n\nWe already replied with: {{ $('AI writes reply').first().json.message.content }}",
        "options": {}
      },
      "credentials": {
        "gmailOAuth2": {
          "id": "REPLACE_GMAIL_CREDENTIAL",
          "name": "Gmail account (placeholder)"
        }
      }
    },
    {
      "id": "dd7b79fc-4828-5ec8-aba5-21e387c1a775",
      "name": "Check Twilio signature",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        660,
        460
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "// Is this request really from Twilio? Checks the X-Twilio-Signature header.\n// Twilio signs: the exact webhook URL + every POST field, sorted by name, as name+value,\n// using HMAC-SHA1 keyed with your auth token, base64-encoded.\n// n8n Cloud allows require('crypto'). Self-hosted: set NODE_FUNCTION_ALLOW_BUILTIN=crypto\n// (on the task runner too, if you use one).\nconst crypto = require('crypto');\nconst cfg = $('Config (edit me)').first().json;\nconst req = $json;\nconst params = req.body || {};\nconst url = String(cfg.twilio_sms_webhook_url || '').trim();\nconst data = url + Object.keys(params).sort().map(k => k + params[k]).join('');\nconst expected = crypto.createHmac('sha1', String(cfg.twilio_auth_token || '')).update(data, 'utf8').digest('base64');\nconst received = String((req.headers || {})['x-twilio-signature'] || '');\nconst a = Buffer.from(expected);\nconst b = Buffer.from(received);\nconst ok = url !== '' && received !== '' && a.length === b.length && crypto.timingSafeEqual(a, b);\nreturn { json: { ...req, signature_ok: ok } };"
      }
    },
    {
      "id": "aaf3c09e-bfb5-5afd-a1c4-a1e7c0dbf7e4",
      "name": "Signature valid?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        880,
        460
      ],
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "loose"
          },
          "conditions": [
            {
              "id": "b3175902-de7f-5f98-a762-172b685e9d81",
              "leftValue": "={{ $json.signature_ok }}",
              "rightValue": "",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      }
    },
    {
      "id": "fa8237e3-fe85-59a5-ad56-3397996fc851",
      "name": "Reject: not from Twilio (403)",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.1,
      "position": [
        1100,
        640
      ],
      "parameters": {
        "respondWith": "text",
        "responseBody": "Forbidden",
        "options": {
          "responseHeaders": {
            "entries": [
              {
                "name": "Content-Type",
                "value": "text/plain"
              }
            ]
          },
          "responseCode": 403
        }
      }
    },
    {
      "id": "73637253-af6e-59b9-83da-26832b1bea0f",
      "name": "Acknowledge Twilio (text)",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.1,
      "position": [
        1320,
        460
      ],
      "parameters": {
        "respondWith": "text",
        "responseBody": "<Response></Response>",
        "options": {
          "responseHeaders": {
            "entries": [
              {
                "name": "Content-Type",
                "value": "text/xml"
              }
            ]
          }
        }
      }
    },
    {
      "id": "311ebef9-949a-50d6-912c-4ddbf05a4218",
      "name": "Says URGENT?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        1540,
        460
      ],
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": false,
            "leftValue": "",
            "typeValidation": "loose"
          },
          "conditions": [
            {
              "id": "678b1629-d33c-5af2-ae5e-97087496b52f",
              "leftValue": "={{ $('Incoming text').first().json.body.Body }}",
              "rightValue": "urgent",
              "operator": {
                "type": "string",
                "operation": "contains"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      }
    },
    {
      "id": "e8d8be9a-a109-506d-a8aa-80fde6e7fbe3",
      "name": "Text the owner (URGENT)",
      "type": "n8n-nodes-base.twilio",
      "typeVersion": 1,
      "position": [
        1760,
        280
      ],
      "parameters": {
        "from": "={{ $('Config (edit me)').first().json.twilio_number }}",
        "to": "={{ $('Config (edit me)').first().json.owner_cell }}",
        "message": "=URGENT text to {{ $('Config (edit me)').first().json.business_name }} from {{ $('Incoming text').first().json.body.From }}: \"{{ $('Incoming text').first().json.body.Body }}\" Call or text them back now.",
        "options": {}
      },
      "credentials": {
        "twilioApi": {
          "id": "REPLACE_TWILIO_CREDENTIAL",
          "name": "Twilio account (placeholder)"
        }
      }
    },
    {
      "id": "5717eb82-8735-577f-8a3f-4d51024acd18",
      "name": "Text the customer (URGENT ack)",
      "type": "n8n-nodes-base.twilio",
      "typeVersion": 1,
      "position": [
        1980,
        280
      ],
      "parameters": {
        "from": "={{ $('Config (edit me)').first().json.twilio_number }}",
        "to": "={{ $('Incoming text').first().json.body.From }}",
        "message": "=Got it, we've texted the agent's cell and someone will call you shortly. Coverage can't be started or changed by text. If anyone is hurt or in danger, call 911. - {{ $('Config (edit me)').first().json.business_name }}",
        "options": {}
      },
      "credentials": {
        "twilioApi": {
          "id": "REPLACE_TWILIO_CREDENTIAL",
          "name": "Twilio account (placeholder)"
        }
      }
    },
    {
      "id": "98364dfb-53a5-5464-a684-534a0173709c",
      "name": "Email the owner (URGENT, optional)",
      "type": "n8n-nodes-base.gmail",
      "typeVersion": 2.1,
      "position": [
        2200,
        280
      ],
      "parameters": {
        "sendTo": "={{ $('Config (edit me)').first().json.owner_email }}",
        "subject": "=URGENT: text from {{ $('Incoming text').first().json.body.From }}",
        "emailType": "text",
        "message": "=They wrote: {{ $('Incoming text').first().json.body.Body }}\n\nYour cell was texted and they were told you'll get back to them right away.",
        "options": {}
      },
      "credentials": {
        "gmailOAuth2": {
          "id": "REPLACE_GMAIL_CREDENTIAL",
          "name": "Gmail account (placeholder)"
        }
      },
      "onError": "continueRegularOutput"
    },
    {
      "id": "3d072826-b6d3-52df-9842-69bf2abaeae4",
      "name": "Forward the reply to you",
      "type": "n8n-nodes-base.gmail",
      "typeVersion": 2.1,
      "position": [
        1760,
        640
      ],
      "parameters": {
        "sendTo": "={{ $('Config (edit me)').first().json.owner_email }}",
        "subject": "=Reply from {{ $('Incoming text').first().json.body.From }} (replied to your instant reply)",
        "emailType": "text",
        "message": "=They wrote: {{ $('Incoming text').first().json.body.Body }}\n\nReply to them from your phone or the Twilio console.",
        "options": {}
      },
      "credentials": {
        "gmailOAuth2": {
          "id": "REPLACE_GMAIL_CREDENTIAL",
          "name": "Gmail account (placeholder)"
        }
      }
    },
    {
      "id": "cfe9d465-e4ec-5497-969e-9a4b7725ce6c",
      "name": "Setup steps",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -560,
        -200
      ],
      "parameters": {
        "content": "## Setup (about 1 hour)\n1. Fill in **Config (edit me)**, including your Twilio **auth token** and the incoming-text webhook URL.\n2. Connect your own **Twilio**, **OpenAI** and **Gmail** credentials on the red nodes.\n3. Point your website form (or any form tool or CRM that can send a webhook) to POST to `https://YOUR-N8N-URL/webhook/new-lead` with fields `name`, `phone`, `email`, `message`. Different field names? Change them in **Map form fields**. Add a hidden, empty field called `website`: bots fill it in, people don't.\n4. In Twilio > Phone Numbers > your number > Messaging: 'A message comes in' > Webhook, HTTP POST, `https://YOUR-N8N-URL/webhook/new-lead-sms`. Paste the exact same URL into **twilio_sms_webhook_url** in Config. A number has one 'message comes in' webhook, so if you run several of these workflows on one number, point it at only one of them.\n5. Register your Twilio number for A2P 10DLC, and in Twilio's SMS Geo Permissions allow only the countries you serve.\n6. Send yourself a test lead, then activate.\n\n**Security:** the Check Twilio signature node rejects (403) anything not signed with your Twilio auth token. Self-hosted n8n: set `NODE_FUNCTION_ALLOW_BUILTIN=crypto`. Don't share this workflow once your token is in it.",
        "height": 660,
        "width": 520
      }
    }
  ],
  "connections": {
    "New lead from your form": {
      "main": [
        [
          {
            "node": "Config (edit me)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Incoming text": {
      "main": [
        [
          {
            "node": "Config (edit me)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Config (edit me)": {
      "main": [
        [
          {
            "node": "Form or text?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Form or text?": {
      "main": [
        [
          {
            "node": "Map form fields",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Check Twilio signature",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Map form fields": {
      "main": [
        [
          {
            "node": "Tell the form it worked",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Tell the form it worked": {
      "main": [
        [
          {
            "node": "Spam check",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Spam check": {
      "main": [
        [
          {
            "node": "AI writes reply",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI writes reply": {
      "main": [
        [
          {
            "node": "Has a valid mobile number?",
            "type": "main",
            "index": 0
          },
          {
            "node": "Has an email?",
            "type": "main",
            "index": 0
          },
          {
            "node": "Email the owner",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Has a valid mobile number?": {
      "main": [
        [
          {
            "node": "Text the lead",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Has an email?": {
      "main": [
        [
          {
            "node": "Email the lead",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Twilio signature": {
      "main": [
        [
          {
            "node": "Signature valid?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Signature valid?": {
      "main": [
        [
          {
            "node": "Acknowledge Twilio (text)",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Reject: not from Twilio (403)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Acknowledge Twilio (text)": {
      "main": [
        [
          {
            "node": "Says URGENT?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Says URGENT?": {
      "main": [
        [
          {
            "node": "Text the owner (URGENT)",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Forward the reply to you",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Text the owner (URGENT)": {
      "main": [
        [
          {
            "node": "Text the customer (URGENT ack)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Text the customer (URGENT ack)": {
      "main": [
        [
          {
            "node": "Email the owner (URGENT, optional)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "pinData": {},
  "meta": {
    "templateCredsSetupCompleted": false,
    "generatedBy": "Speed-to-Lead Playbooks"
  },
  "tags": []
}