{
  "name": "AI Qualified Booking",
  "tags": [
    {
      "name": "NTF-Playbook"
    }
  ],
  "settings": {
    "executionOrder": "v1"
  },
  "nodes": [
    {
      "id": "sticky-readme",
      "name": "README",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -60,
        -520
      ],
      "parameters": {
        "content": "## AI Qualified Booking\n\n**Trigger:** Webhook, intake form submission\n\n**Flow:**\n1. Prospect submits intake form (Tally/Typeform/Google Forms)\n2. Claude scores against ICP criteria: Qualified / Borderline / Not a Fit\n3. Qualified, gets Calendly link automatically via email\n4. Borderline, routed to manual review for follow-up question\n5. Not a Fit, receives polite decline email with alternative resources\n6. All leads logged to Google Sheets\n\n**Setup:**\n- Set CALENDLY_LINK and YOUR_NAME in the Config node\n- Connect Gmail credential for sending emails\n- Edit Claude ICP criteria inside the Qualify Against ICP node\n- Connect Google Sheets credential and set the spreadsheet ID\n- The webhook URL becomes your form's submission endpoint",
        "height": 380,
        "width": 560,
        "color": 6
      }
    },
    {
      "id": "webhook-trigger",
      "name": "Intake Form Webhook",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [
        0,
        0
      ],
      "parameters": {
        "httpMethod": "POST",
        "path": "booking-intake",
        "responseMode": "responseNode",
        "options": {}
      }
    },
    {
      "id": "config",
      "name": "Config",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        220,
        0
      ],
      "parameters": {
        "mode": "manual",
        "assignments": {
          "assignments": [
            {
              "id": "calendly_link",
              "name": "calendly_link",
              "value": "YOUR_CALENDLY_LINK",
              "type": "string"
            },
            {
              "id": "your_name",
              "name": "your_name",
              "value": "YOUR_NAME",
              "type": "string"
            },
            {
              "id": "name",
              "name": "name",
              "value": "={{ $json.body.name || '' }}",
              "type": "string"
            },
            {
              "id": "email",
              "name": "email",
              "value": "={{ $json.body.email || '' }}",
              "type": "string"
            },
            {
              "id": "company",
              "name": "company",
              "value": "={{ $json.body.company || '' }}",
              "type": "string"
            },
            {
              "id": "role",
              "name": "role",
              "value": "={{ $json.body.role || '' }}",
              "type": "string"
            },
            {
              "id": "challenge",
              "name": "challenge",
              "value": "={{ $json.body.challenge || $json.body.message || '' }}",
              "type": "string"
            },
            {
              "id": "budget",
              "name": "budget",
              "value": "={{ $json.body.budget || '' }}",
              "type": "string"
            },
            {
              "id": "timeline",
              "name": "timeline",
              "value": "={{ $json.body.timeline || '' }}",
              "type": "string"
            }
          ]
        }
      }
    },
    {
      "id": "claude-llm",
      "name": "Claude Qualification Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatAnthropic",
      "typeVersion": 1.3,
      "position": [
        440,
        0
      ],
      "parameters": {
        "model": "claude-sonnet-4-5",
        "options": {
          "maxTokens": 600
        }
      },
      "credentials": {
        "anthropicApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "id": "qualify-chain",
      "name": "Qualify Against ICP",
      "type": "@n8n/n8n-nodes-langchain.chainLlm",
      "typeVersion": 1.4,
      "position": [
        440,
        0
      ],
      "parameters": {
        "promptType": "define",
        "text": "=You are a sales qualification assistant. Score this prospect against the ICP criteria below.\n\nReturn JSON with:\n- score: \"Qualified\" | \"Borderline\" | \"Not a Fit\"\n- reasoning: one sentence explaining the score\n- confidence: 0-100 integer\n\nICP CRITERIA (edit these):\n- Ideal: founder or senior ops/marketing role, company 10-200 people, has a specific automation or efficiency problem, timeline within 90 days\n- Borderline: right role but vague problem, or right problem but no timeline\n- Not a Fit: agencies looking for white-label services, students, purely technical developers building their own tools, no budget indicated\n\nProspect:\nName: {{ $json.name }}\nEmail: {{ $json.email }}\nCompany: {{ $json.company }}\nRole: {{ $json.role }}\nChallenge: {{ $json.challenge }}\nBudget: {{ $json.budget }}\nTimeline: {{ $json.timeline }}\n\nReturn only valid JSON. No markdown fencing."
      }
    },
    {
      "id": "parse-score",
      "name": "Parse Score",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        660,
        0
      ],
      "parameters": {
        "jsCode": "const raw = $input.first().json.text || '{}';\nlet parsed = {};\ntry {\n  parsed = JSON.parse(raw.replace(/```json|```/g, '').trim());\n} catch(e) {\n  parsed = { score: 'Borderline', reasoning: 'Parse error', confidence: 50 };\n}\nconst config = $('Config').first().json;\nreturn [{ json: { ...config, ...parsed, submitted_at: new Date().toISOString() } }];"
      }
    },
    {
      "id": "route-by-score",
      "name": "Route by Score",
      "type": "n8n-nodes-base.switch",
      "typeVersion": 3.2,
      "position": [
        880,
        0
      ],
      "parameters": {
        "mode": "rules",
        "rules": {
          "values": [
            {
              "conditions": {
                "conditions": [
                  {
                    "leftValue": "={{ $json.score }}",
                    "rightValue": "Qualified",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    }
                  }
                ]
              },
              "renameOutput": true,
              "outputKey": "qualified"
            },
            {
              "conditions": {
                "conditions": [
                  {
                    "leftValue": "={{ $json.score }}",
                    "rightValue": "Borderline",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    }
                  }
                ]
              },
              "renameOutput": true,
              "outputKey": "borderline"
            },
            {
              "conditions": {
                "conditions": [
                  {
                    "leftValue": "={{ $json.score }}",
                    "rightValue": "Not a Fit",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    }
                  }
                ]
              },
              "renameOutput": true,
              "outputKey": "not_a_fit"
            }
          ]
        }
      }
    },
    {
      "id": "email-qualified",
      "name": "Email Send Calendar Link",
      "type": "n8n-nodes-base.gmail",
      "typeVersion": 2.1,
      "position": [
        1100,
        -240
      ],
      "parameters": {
        "operation": "send",
        "sendTo": "={{ $json.email }}",
        "subject": "=Let's talk, book a time that works for you",
        "message": "=Hi {{ $json.name }},\n\nThanks for reaching out. Based on what you shared, I think there's a strong fit and I'd love to learn more.\n\nBook a time that works for you: {{ $json.calendly_link }}\n\nLooking forward to it.\n\n{{ $json.your_name }}",
        "options": {}
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      }
    },
    {
      "id": "email-borderline",
      "name": "Email Review Notification",
      "type": "n8n-nodes-base.gmail",
      "typeVersion": 2.1,
      "position": [
        1100,
        0
      ],
      "parameters": {
        "operation": "send",
        "sendTo": "={{ $json.email }}",
        "subject": "=Thanks for reaching out, a quick question",
        "message": "=Hi {{ $json.name }},\n\nThanks for getting in touch. I'd love to understand your situation better before we schedule time.\n\nCould you share a bit more about [YOUR SPECIFIC QUESTION]? Just a few sentences is enough.\n\nI'll follow up once I've had a chance to review.\n\n{{ $json.your_name }}",
        "options": {}
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      }
    },
    {
      "id": "email-not-a-fit",
      "name": "Email Polite Decline",
      "type": "n8n-nodes-base.gmail",
      "typeVersion": 2.1,
      "position": [
        1100,
        240
      ],
      "parameters": {
        "operation": "send",
        "sendTo": "={{ $json.email }}",
        "subject": "=Thanks for reaching out",
        "message": "=Hi {{ $json.name }},\n\nThank you for reaching out and for taking the time to share your situation.\n\nAfter reviewing your intake, I don't think I'm the right fit for what you need right now, but I don't want to leave you without options.\n\nYou might find value in: [ALTERNATIVE RESOURCE OR REFERRAL].\n\nWishing you the best.\n\n{{ $json.your_name }}",
        "options": {}
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      }
    },
    {
      "id": "log-all",
      "name": "Log All to Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.5,
      "position": [
        1320,
        0
      ],
      "parameters": {
        "operation": "append",
        "documentId": {
          "__rl": true,
          "value": "YOUR_SPREADSHEET_ID",
          "mode": "id"
        },
        "sheetName": {
          "__rl": true,
          "value": "Intake",
          "mode": "name"
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "Submitted At": "={{ $json.submitted_at }}",
            "Name": "={{ $json.name }}",
            "Email": "={{ $json.email }}",
            "Company": "={{ $json.company }}",
            "Role": "={{ $json.role }}",
            "Score": "={{ $json.score }}",
            "Confidence": "={{ $json.confidence }}",
            "Reasoning": "={{ $json.reasoning }}"
          }
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      }
    },
    {
      "id": "webhook-response",
      "name": "Webhook Response",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.1,
      "position": [
        1320,
        -240
      ],
      "parameters": {
        "respondWith": "json",
        "responseBody": "={{ JSON.stringify({ received: true }) }}"
      }
    }
  ],
  "connections": {
    "Intake Form Webhook": {
      "main": [
        [
          {
            "node": "Config",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Config": {
      "main": [
        [
          {
            "node": "Qualify Against ICP",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Claude Qualification Model": {
      "ai_languageModel": [
        [
          {
            "node": "Qualify Against ICP",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Qualify Against ICP": {
      "main": [
        [
          {
            "node": "Parse Score",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Score": {
      "main": [
        [
          {
            "node": "Route by Score",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Route by Score": {
      "main": [
        [
          {
            "node": "Email Send Calendar Link",
            "type": "main",
            "index": 0
          },
          {
            "node": "Webhook Response",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Email Review Notification",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Email Polite Decline",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Email Send Calendar Link": {
      "main": [
        [
          {
            "node": "Log All to Sheets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Email Review Notification": {
      "main": [
        [
          {
            "node": "Log All to Sheets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Email Polite Decline": {
      "main": [
        [
          {
            "node": "Log All to Sheets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}