This workflow corresponds to n8n.io template #16195 — we link there as the canonical source.
This workflow follows the Gmail → Google Sheets recipe pattern — see all workflows that pair these two integrations.
The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"id": "sC1sxzI9jgH7PjqS",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "Calendly-to-CRM Sales Prep Automation",
"tags": [
{
"id": "4Of2LE0HSt4qmmUG",
"name": "Ansh",
"createdAt": "2026-04-20T10:32:01.726Z",
"updatedAt": "2026-04-20T10:32:01.726Z"
}
],
"nodes": [
{
"id": "99c2d8eb-ce6c-471b-a1c5-3bdf86ef7f6c",
"name": "Sticky Note - Overview1",
"type": "n8n-nodes-base.stickyNote",
"position": [
880,
1088
],
"parameters": {
"width": 508,
"height": 608,
"content": "## Calendly-to-CRM Sales Prep Automation\nThis workflow fires every time a prospect books a sales meeting via Calendly. It automatically validates the booking, guards against duplicates, pulls the prospect's CRM history, open deals, and company details, generates AI-powered talking points, then sends the sales rep a complete ready-to-use briefing \u2014 so they walk in fully prepared without lifting a finger.\n\n### How it works\n\n\t\u2022\tIt validates and catches new meeting bookings from Calendly.\n\t\u2022\tIt checks if a prep pack was already sent to avoid duplicates.\n\t\u2022\tIt looks up the prospect in HubSpot and fetches their open deals.\n\t\u2022\tIt enriches the prospect's company data from an external source.\n\t\u2022\tIt uses AI to generate smart, personalised talking points.\n\t\u2022\tIt sends a full briefing to the sales rep via Slack.\n\t\u2022\tIt updates the calendar invite and logs everything to Google Sheets.\n\t\u2022\tIt catches any errors and alerts the team automatically.\n\n### Setup Steps\n\n\t1.\tConnect Calendly webhook and add your signing secret for validation.\n\t2.\tConnect HubSpot with your API token.\n\t3.\tAdd your Clearbit API key for company enrichment.\n\t4.\tAdd your OpenAI API key for AI talking points.\n\t5.\tConnect Slack, Google Sheets, and Gmail with credentials.\n\t6.\tSet your duplicate-check Google Sheet ID and Slack channel ID.\n\t7.\tTurn on the workflow."
},
"typeVersion": 1
},
{
"id": "4d453501-527b-43e0-97bf-c397dc1c18f5",
"name": "Sticky Note - Step 1",
"type": "n8n-nodes-base.stickyNote",
"position": [
1408,
1088
],
"parameters": {
"color": 7,
"width": 640,
"height": 608,
"content": "## Step 1: Catch & Validate the Booking\nThis step receives the meeting notification from Calendly and checks that it is genuine. It verifies the security signature so no fake or test events can trigger the workflow by mistake."
},
"typeVersion": 1
},
{
"id": "01ab6e71-fde3-4ffe-8d2d-7f864c1cece5",
"name": "Sticky Note - Step 2",
"type": "n8n-nodes-base.stickyNote",
"position": [
2512,
1088
],
"parameters": {
"color": 7,
"width": 1120,
"height": 608,
"content": "## Step 3: Look Up the Prospect\nThis step searches your CRM, fetches open deals, and enriches the prospect's company data from an external source. It builds a complete picture of who is coming to the meeting before the prep pack is built."
},
"typeVersion": 1
},
{
"id": "791e6533-dbc8-4459-9404-7406ea9cd335",
"name": "Sticky Note - Step 3",
"type": "n8n-nodes-base.stickyNote",
"position": [
4160,
1088
],
"parameters": {
"color": 7,
"width": 912,
"height": 608,
"content": "## Step 5: Build & Send the Prep Pack\nThis step takes all the data collected and uses AI to write smart talking points. It then sends the full briefing to the sales rep on Slack, updates the calendar invite, and logs the record to Google Sheets."
},
"typeVersion": 1
},
{
"id": "fbef0e91-eba5-4863-a925-3205caa4e774",
"name": "Sticky Note - Step 4 Duplicate Guard",
"type": "n8n-nodes-base.stickyNote",
"position": [
2064,
1088
],
"parameters": {
"color": 7,
"width": 432,
"height": 612,
"content": "## Step 2: Duplicate Guard\nBefore doing any work, this step checks whether a prep pack was already sent for this exact meeting. If it was, the workflow stops early so the sales rep never receives two identical messages."
},
"typeVersion": 1
},
{
"id": "c75ee464-75a6-415f-998e-9d5660b476f7",
"name": "Sticky Note - Step 5 AI Talking Points",
"type": "n8n-nodes-base.stickyNote",
"position": [
3648,
1088
],
"parameters": {
"color": 7,
"width": 496,
"height": 612,
"content": "## Step 4: AI Talking Points\nThis step sends all the prospect data to an AI model and asks it to write three sharp, personalised conversation starters for the sales rep. This saves research time and helps the rep open the meeting with confidence."
},
"typeVersion": 1
},
{
"id": "e8fd2cdf-8a89-42a3-8d36-2300e21a738c",
"name": "Calendly Webhook",
"type": "n8n-nodes-base.webhook",
"position": [
1456,
1408
],
"parameters": {
"path": "calendly-meeting-booked",
"options": {},
"httpMethod": "POST"
},
"typeVersion": 2
},
{
"id": "58d49611-39b2-4c44-95a9-5dd6327fab19",
"name": "Validate Webhook Signature",
"type": "n8n-nodes-base.code",
"position": [
1680,
1408
],
"parameters": {
"jsCode": "// Validate Calendly webhook signature\n// Calendly signs payloads with HMAC-SHA256 using your webhook signing key\nconst crypto = require('crypto');\n\nconst signingKey = 'REPLACE_WITH_CALENDLY_SIGNING_KEY';\nconst rawBody = JSON.stringify($input.item.json.body || $input.item.json);\nconst receivedSignature = $input.item.json.headers?.['calendly-webhook-signature'] || '';\n\n// Calendly signature format: \"t=<timestamp>,v1=<signature>\"\nconst parts = receivedSignature.split(',');\nconst timestampPart = parts.find(p => p.startsWith('t='));\nconst signaturePart = parts.find(p => p.startsWith('v1='));\n\nif (!timestampPart || !signaturePart) {\n // If no signature header (e.g. in testing), allow through with a warning\n return [{ json: { ...($input.item.json), signatureValid: false, signatureSkipped: true } }];\n}\n\nconst timestamp = timestampPart.replace('t=', '');\nconst receivedSig = signaturePart.replace('v1=', '');\nconst expectedSig = crypto\n .createHmac('sha256', signingKey)\n .update(`${timestamp}.${rawBody}`)\n .digest('hex');\n\nconst isValid = crypto.timingSafeEqual(\n Buffer.from(expectedSig, 'hex'),\n Buffer.from(receivedSig, 'hex')\n);\n\nif (!isValid) {\n throw new Error('Invalid Calendly webhook signature \u2014 request rejected.');\n}\n\nreturn [{ json: { ...($input.item.json), signatureValid: true } }];"
},
"typeVersion": 2
},
{
"id": "83b05891-df1f-4078-bc2e-f64e5ffbfed4",
"name": "Extract Meeting Details",
"type": "n8n-nodes-base.set",
"position": [
1904,
1408
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "f1",
"name": "prospectEmail",
"type": "string",
"value": "={{ $json.payload?.invitee?.email ?? $json.body?.payload?.invitee?.email }}"
},
{
"id": "f2",
"name": "prospectName",
"type": "string",
"value": "={{ $json.payload?.invitee?.name ?? $json.body?.payload?.invitee?.name }}"
},
{
"id": "f3",
"name": "meetingTime",
"type": "string",
"value": "={{ $json.payload?.event?.start_time ?? $json.body?.payload?.event?.start_time }}"
},
{
"id": "f4",
"name": "meetingName",
"type": "string",
"value": "={{ $json.payload?.event_type?.name ?? $json.body?.payload?.event_type?.name }}"
},
{
"id": "f5",
"name": "salesRepEmail",
"type": "string",
"value": "={{ ($json.payload?.event?.assigned_to ?? $json.body?.payload?.event?.assigned_to ?? [])[0] }}"
},
{
"id": "f6",
"name": "meetingUuid",
"type": "string",
"value": "={{ $json.payload?.event?.uuid ?? $json.body?.payload?.event?.uuid ?? $json.payload?.uri ?? 'no-uuid' }}"
},
{
"id": "f7",
"name": "eventUri",
"type": "string",
"value": "={{ $json.payload?.event?.uri ?? $json.body?.payload?.event?.uri }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "797da2bc-c988-4eb6-8689-c9a8b2bddfc0",
"name": "Check Duplicate in Sheet",
"type": "n8n-nodes-base.googleSheets",
"position": [
2128,
1408
],
"parameters": {
"operation": "lookup",
"documentId": {
"__rl": true,
"mode": "id",
"value": "REPLACE_WITH_DUPLICATE_CHECK_SHEET_ID"
}
},
"typeVersion": 4.5
},
{
"id": "cdd30fdc-1231-4153-90aa-8997e9e0f359",
"name": "Already Sent?",
"type": "n8n-nodes-base.if",
"position": [
2352,
1408
],
"parameters": {
"options": {},
"conditions": {
"options": {
"leftValue": "",
"caseSensitive": false,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "dup1",
"operator": {
"type": "string",
"operation": "empty"
},
"leftValue": "={{ $json.MeetingUUID }}",
"rightValue": ""
}
]
}
},
"typeVersion": 2.2
},
{
"id": "013f6d97-efa7-4ae6-b719-3a875d0354a1",
"name": "HubSpot - Get Contact",
"type": "n8n-nodes-base.hubspot",
"position": [
2576,
1408
],
"parameters": {
"contactId": "={{ $('Extract Meeting Details').item.json.prospectEmail }}",
"operation": "get",
"additionalFields": {}
},
"typeVersion": 2
},
{
"id": "7b21c2bc-7c9f-41fa-9f3b-c646b7f42bd9",
"name": "HubSpot - Get Open Deals",
"type": "n8n-nodes-base.hubspot",
"position": [
2800,
1408
],
"parameters": {
"limit": 5,
"filters": {},
"resource": "deal",
"operation": "getAll"
},
"typeVersion": 2
},
{
"id": "6d7abc56-362b-47b9-85fd-95d458ef4820",
"name": "Clearbit - Enrich Company",
"type": "n8n-nodes-base.httpRequest",
"position": [
3024,
1408
],
"parameters": {
"url": "=https://person.clearbit.com/v2/combined/find?email={{ $('Extract Meeting Details').item.json.prospectEmail }}",
"options": {
"timeout": 8000
},
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth"
},
"typeVersion": 4.2
},
{
"id": "4e55e3a3-0512-484a-af1d-80c2becc66f7",
"name": "Contact in CRM?",
"type": "n8n-nodes-base.if",
"position": [
3248,
1408
],
"parameters": {
"options": {},
"conditions": {
"options": {
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "cond1",
"operator": {
"type": "string",
"operation": "notEmpty"
},
"leftValue": "={{ $('HubSpot - Get Contact').item.json.id }}",
"rightValue": ""
}
]
}
},
"typeVersion": 2.2
},
{
"id": "6178a313-1d60-475b-91a5-c06f662d41bd",
"name": "Prepare Full Context",
"type": "n8n-nodes-base.code",
"position": [
3472,
1312
],
"parameters": {
"jsCode": "// Gather all upstream data\nconst meeting = $('Extract Meeting Details').item.json;\nconst contact = $('HubSpot - Get Contact').item.json;\nconst dealsRaw = $('HubSpot - Get Open Deals').all();\nconst enrichment = $('Clearbit - Enrich Company').item.json;\n\nconst props = contact.properties || {};\nconst company = enrichment?.company || {};\nconst person = enrichment?.person || {};\n\n// Format deals summary\nconst deals = dealsRaw\n .map(d => d.json?.properties)\n .filter(Boolean)\n .map(d => `\u2022 ${d.dealname || 'Unnamed deal'} \u2014 Stage: ${d.dealstage || 'N/A'} | Amount: $${d.amount || '0'} | Close: ${d.closedate ? new Date(d.closedate).toLocaleDateString() : 'N/A'} | Win prob: ${d.hs_deal_stage_probability ? Math.round(d.hs_deal_stage_probability * 100) + '%' : 'N/A'}`)\n .join('\\n');\n\nconst contextForAI = `\nProspect: ${meeting.prospectName} (${meeting.prospectEmail})\nJob Title: ${props.jobtitle || person.employment?.title || 'Unknown'}\nCompany: ${props.company || company.name || 'Unknown'}\nIndustry: ${company.category?.industry || 'Unknown'}\nCompany Size: ${company.metrics?.employees || 'Unknown'} employees\nEstimated Revenue: ${company.metrics?.estimatedAnnualRevenue || 'Unknown'}\nLifecycle Stage: ${props.lifecyclestage || 'Unknown'}\nLead Status: ${props.hs_lead_status || 'Unknown'}\nOpen Deals:\\n${deals || 'None found'}\nEmails Opened: ${props.hs_email_open_count || '0'}\nLast Reply: ${props.hs_sales_email_last_replied ? new Date(parseInt(props.hs_sales_email_last_replied)).toLocaleDateString() : 'Never'}\nMeeting Type: ${meeting.meetingName}\n`;\n\nreturn [{ json: { contextForAI, meeting, props, company, person, deals, contactFound: true } }];"
},
"typeVersion": 2
},
{
"id": "12ac805b-3e00-47bc-9248-fa851fd72588",
"name": "Prepare Basic Context",
"type": "n8n-nodes-base.code",
"position": [
3472,
1504
],
"parameters": {
"jsCode": "const meeting = $('Extract Meeting Details').item.json;\nconst enrichment = $('Clearbit - Enrich Company').item.json;\nconst company = enrichment?.company || {};\n\nconst contextForAI = `\nProspect: ${meeting.prospectName} (${meeting.prospectEmail})\nCompany: ${company.name || 'Unknown'}\nIndustry: ${company.category?.industry || 'Unknown'}\nCompany Size: ${company.metrics?.employees || 'Unknown'} employees\nMeeting Type: ${meeting.meetingName}\nNote: This prospect is NOT in the CRM \u2014 treat as a brand new contact.\n`;\n\nreturn [{ json: { contextForAI, meeting, company, props: {}, person: {}, deals: 'None \u2014 new prospect', contactFound: false } }];"
},
"typeVersion": 2
},
{
"id": "666b43b8-5472-4857-a0e8-48a96182f0d8",
"name": "OpenAI - Generate Talking Points",
"type": "n8n-nodes-base.httpRequest",
"position": [
3840,
1408
],
"parameters": {
"url": "https://api.openai.com/v1/chat/completions",
"method": "POST",
"options": {
"timeout": 15000
},
"sendBody": true,
"authentication": "genericCredentialType",
"bodyParameters": {
"parameters": [
{
"name": "model",
"value": "gpt-4o"
},
{
"name": "max_tokens",
"value": "600"
},
{
"name": "messages",
"value": "=[{\"role\":\"system\",\"content\":\"You are a sales coach helping a rep prepare for a meeting. Generate exactly 3 sharp, specific, personalised talking points or questions based on the prospect data provided. Each talking point should be 1-2 sentences. Format as a numbered list. Be concrete \u2014 reference their industry, company size, or deal stage where relevant. No generic advice.\"},{\"role\":\"user\",\"content\":{{ JSON.stringify($json.contextForAI) }}}]"
}
]
},
"genericAuthType": "httpHeaderAuth"
},
"typeVersion": 4.2
},
{
"id": "55c78c42-a0b6-4561-a1cd-cb6afe155f34",
"name": "Build Final Prep Pack",
"type": "n8n-nodes-base.code",
"position": [
4208,
1408
],
"parameters": {
"jsCode": "const context = $('OpenAI - Generate Talking Points').item.json.choices?.[0]?.message?.content || '1. Research the prospect further before the call.\\n2. Focus on discovery questions.\\n3. Understand their current workflow before pitching.';\n\nconst data = $input.item.json;\nconst meeting = data.meeting;\nconst props = data.props || {};\nconst company = data.company || {};\nconst person = data.person || {};\nconst deals = data.deals || 'None';\nconst contactFound = data.contactFound;\n\nconst meetingDate = new Date(meeting.meetingTime).toLocaleString('en-US', {\n weekday: 'long', year: 'numeric', month: 'long', day: 'numeric',\n hour: '2-digit', minute: '2-digit', timeZoneName: 'short'\n});\n\nconst crmSection = contactFound\n ? `\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n*\ud83d\udc64 CRM Profile*\n\u2022 Title: ${props.jobtitle || person.employment?.title || 'N/A'}\n\u2022 Phone: ${props.phone || 'N/A'}\n\u2022 Lifecycle Stage: ${props.lifecyclestage || 'N/A'}\n\u2022 Lead Status: ${props.hs_lead_status || 'N/A'}\n\u2022 Emails Opened: ${props.hs_email_open_count || '0'}\n\u2022 Last Reply: ${props.hs_sales_email_last_replied ? new Date(parseInt(props.hs_sales_email_last_replied)).toLocaleDateString() : 'Never'}\n\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n*\ud83d\udcbc Open Deals*\n${typeof deals === 'string' ? deals : deals || 'None found'}`\n : `\u26a0\ufe0f *New prospect \u2014 not in CRM yet. Add them after the call.*`;\n\nconst prepPack = `*\ud83d\udccb Pre-Meeting Prep Pack*\n*Meeting:* ${meeting.meetingName}\n*When:* ${meetingDate}\n*Prospect:* ${meeting.prospectName} (${meeting.prospectEmail})\n\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n*\ud83c\udfe2 Company Overview*\n\u2022 Company: ${props.company || company.name || 'Unknown'}\n\u2022 Industry: ${company.category?.industry || 'N/A'}\n\u2022 Employees: ${company.metrics?.employees || 'N/A'}\n\u2022 Revenue: ${company.metrics?.estimatedAnnualRevenue || 'N/A'}\n\u2022 Location: ${[company.geo?.city, company.geo?.country].filter(Boolean).join(', ') || 'N/A'}\n\n${crmSection}\n\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n*\ud83e\udd16 AI Talking Points*\n${context}\n\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n_Prep pack auto-generated by n8n \u2022 ${new Date().toLocaleString()}_`;\n\nreturn [{ json: { prepPack, prospectName: meeting.prospectName, prospectEmail: meeting.prospectEmail, meetingTime: meeting.meetingTime, meetingName: meeting.meetingName, meetingUuid: meeting.meetingUuid, salesRepEmail: meeting.salesRepEmail, eventUri: meeting.eventUri, contactFound, talkingPoints: context } }];"
},
"typeVersion": 2
},
{
"id": "a9201a5c-9f52-4e00-8d58-3c28153eba12",
"name": "Slack - Send Prep Pack",
"type": "n8n-nodes-base.slack",
"position": [
4432,
1408
],
"parameters": {
"text": "={{ $json.prepPack }}",
"select": "channel",
"channelId": {
"__rl": true,
"mode": "id",
"value": "REPLACE_WITH_SLACK_CHANNEL_ID"
},
"otherOptions": {}
},
"typeVersion": 2.3
},
{
"id": "49d87a38-3f78-4b06-80be-a9b808745e31",
"name": "Gmail - Email Prep to Rep",
"type": "n8n-nodes-base.gmail",
"position": [
4656,
1408
],
"parameters": {
"sendTo": "={{ $json.salesRepEmail }}",
"message": "={{ $json.prepPack.replace(/\\*/g, '').replace(/\u2501/g, '---') }}",
"options": {},
"subject": "=\ud83d\udccb Prep Pack: {{ $json.prospectName }} \u2014 {{ $json.meetingName }}",
"emailType": "text"
},
"typeVersion": 2.1
},
{
"id": "cf61ab85-b2c3-44ef-9556-a83998e8b6e8",
"name": "Log to Google Sheets",
"type": "n8n-nodes-base.googleSheets",
"position": [
4880,
1408
],
"parameters": {
"columns": {
"value": {
"Date": "={{ $now.format('yyyy-MM-dd') }}",
"Status": "Sent",
"Meeting": "={{ $json.meetingName }}",
"PrepSentAt": "={{ $now.toISO() }}",
"MeetingTime": "={{ $json.meetingTime }}",
"MeetingUUID": "={{ $json.meetingUuid }}",
"ProspectName": "={{ $json.prospectName }}",
"ProspectEmail": "={{ $json.prospectEmail }}",
"SalesRepEmail": "={{ $json.salesRepEmail }}",
"CRMContactFound": "={{ $json.contactFound }}"
},
"mappingMode": "defineBelow"
},
"options": {},
"operation": "append",
"sheetName": {
"__rl": true,
"mode": "name",
"value": "SentLog"
},
"documentId": {
"__rl": true,
"mode": "id",
"value": "REPLACE_WITH_GOOGLE_SHEET_ID"
}
},
"typeVersion": 4.5
}
],
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "24fb3f34-099b-4d3d-82fa-9aa2168d28a8",
"connections": {
"Already Sent?": {
"main": [
[
{
"node": "HubSpot - Get Contact",
"type": "main",
"index": 0
}
]
]
},
"Contact in CRM?": {
"main": [
[
{
"node": "Prepare Full Context",
"type": "main",
"index": 0
}
],
[
{
"node": "Prepare Basic Context",
"type": "main",
"index": 0
}
]
]
},
"Calendly Webhook": {
"main": [
[
{
"node": "Validate Webhook Signature",
"type": "main",
"index": 0
}
]
]
},
"Prepare Full Context": {
"main": [
[
{
"node": "OpenAI - Generate Talking Points",
"type": "main",
"index": 0
}
]
]
},
"Build Final Prep Pack": {
"main": [
[
{
"node": "Slack - Send Prep Pack",
"type": "main",
"index": 0
}
]
]
},
"HubSpot - Get Contact": {
"main": [
[
{
"node": "HubSpot - Get Open Deals",
"type": "main",
"index": 0
}
]
]
},
"Prepare Basic Context": {
"main": [
[
{
"node": "OpenAI - Generate Talking Points",
"type": "main",
"index": 0
}
]
]
},
"Slack - Send Prep Pack": {
"main": [
[
{
"node": "Gmail - Email Prep to Rep",
"type": "main",
"index": 0
}
]
]
},
"Extract Meeting Details": {
"main": [
[
{
"node": "Check Duplicate in Sheet",
"type": "main",
"index": 0
}
]
]
},
"Check Duplicate in Sheet": {
"main": [
[
{
"node": "Already Sent?",
"type": "main",
"index": 0
}
]
]
},
"HubSpot - Get Open Deals": {
"main": [
[
{
"node": "Clearbit - Enrich Company",
"type": "main",
"index": 0
}
]
]
},
"Clearbit - Enrich Company": {
"main": [
[
{
"node": "Contact in CRM?",
"type": "main",
"index": 0
}
]
]
},
"Gmail - Email Prep to Rep": {
"main": [
[
{
"node": "Log to Google Sheets",
"type": "main",
"index": 0
}
]
]
},
"Validate Webhook Signature": {
"main": [
[
{
"node": "Extract Meeting Details",
"type": "main",
"index": 0
}
]
]
},
"OpenAI - Generate Talking Points": {
"main": [
[
{
"node": "Build Final Prep Pack",
"type": "main",
"index": 0
}
]
]
}
}
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This workflow receives new Calendly meeting bookings, checks Google Sheets to prevent duplicate briefings, pulls contact and deal context from HubSpot, enriches company data with Clearbit, generates three talking points with OpenAI, then sends a prep pack to the sales rep via…
Source: https://n8n.io/workflows/16195/ — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
This workflow triggers on HubSpot dealstage changes, pulls full deal, contact, and owner details, uses OpenAI to generate a concise Slack-ready update with next steps, notifies the right Slack channel
This workflow automates the initial screening process for new job applications, freeing up your recruitment team to focus on qualified candidates. It receives applications from a webhook, uses OpenAI
This system meticulously guides each lead through a fully automated journey, from initial contact to a personalized follow-up and CRM integration.
Analyze website SEO issues and generate optimization actions with AI
Email Drafter. Uses gmail, slack, openAi, httpRequest. Webhook trigger; 15 nodes.