This workflow follows the Form Trigger → Gmail 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 →
{
"name": "HVACFlow - Smart HVAC Service Management System copy",
"nodes": [
{
"parameters": {
"content": "MODULE 1 - LEAD CAPTURE\n\nWebhook receives new lead form data (name, phone, email, address, service required, message).\nA Code node generates a unique Lead ID, then the lead is saved to MongoDB and the customer gets an email + SMS confirmation.",
"height": 300,
"width": 380,
"color": 6
},
"name": "Note: MODULE 1 - LEAD CAPTURE\n",
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-3424,
48
],
"id": "45f29f89-2b9a-4682-bba6-531ad188f177"
},
{
"parameters": {
"jsCode": "const body = $input.first().json.body || $input.first().json;\nconst leadId = 'LEAD-' + Date.now().toString(36).toUpperCase() + '-' + Math.floor(Math.random()*900+100);\nreturn [{\n json: {\n leadId,\n name: body.name,\n phone: body.phone,\n email: body.Email,\n address: body.address,\n serviceRequired: body.serviceRequired,\n message: body.message,\n status: 'new',\n createdAt: new Date().toISOString()\n }\n}];"
},
"name": "Code - Generate Lead ID",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-3280,
464
],
"id": "2dc76330-36bf-48e2-beb8-a06f4b188590"
},
{
"parameters": {
"operation": "insert",
"collection": "leads",
"fields": "leadId,name,phone,email,address,serviceRequired,message,status,createdAt",
"options": {}
},
"name": "MongoDB - Save Lead",
"type": "n8n-nodes-base.mongoDb",
"typeVersion": 1.1,
"position": [
-3072,
640
],
"id": "3f69db2b-171e-41f7-9c78-3517ef8beefa",
"credentials": {
"mongoDb": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"sendTo": "={{$json.email}}",
"subject": "=We received your HVAC service request - {{$json.leadId}}",
"message": "=Hi {{$json.name}},\n\nThank you for contacting HVACFlow. We've received your request for: {{$json.serviceRequired}}.\n\nYour reference ID is {{$json.leadId}}. A team member will review your request shortly and confirm your appointment.\n\nHVACFlow Team",
"options": {}
},
"name": "Gmail - Lead Confirmation Email",
"type": "n8n-nodes-base.gmail",
"typeVersion": 2.1,
"position": [
-2912,
336
],
"id": "3ea9bb24-4e65-4412-ab45-4aed1aec547e",
"credentials": {
"gmailOAuth2": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"from": "+18312822077",
"to": "={{$json.phone}}",
"message": "=Hi {{$json.name}}, HVACFlow received your request ({{$json.leadId}}). We'll confirm your appointment shortly!",
"options": {}
},
"name": "Twilio - Lead Confirmation SMS",
"type": "n8n-nodes-base.twilio",
"typeVersion": 1,
"position": [
-2768,
480
],
"id": "8c2b723a-6f0a-4a2d-9c88-b94955750022",
"credentials": {
"twilioApi": {
"name": "<your credential>"
}
},
"onError": "continueRegularOutput"
},
{
"parameters": {
"content": "MODULE 2 - AI LEAD CLASSIFICATION\n\nOpenAI reads the customer's message and returns a JSON summary, service type (Installation/Repair/Maintenance) and urgency (Low/Medium/High/Emergency). Results are parsed and saved back to the lead in MongoDB, then routed by urgency.",
"height": 300,
"width": 380,
"color": 6
},
"name": "Note: MODULE 2 - AI LEAD CLASS",
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-2576,
-64
],
"id": "1a2c8942-5db4-4c77-bf45-16b4a0d5a1c9"
},
{
"parameters": {
"jsCode": "const lead = $('Code - Generate Lead ID').first().json;\n\nlet aiRaw = $input.first().json.candidates[0].content.parts[0].text;\n\n// Remove markdown code fences if Gemini returns them\naiRaw = aiRaw\n .replace(/```json/g, '')\n .replace(/```/g, '')\n .trim();\n\nlet ai;\n\ntry {\n ai = JSON.parse(aiRaw);\n} catch (e) {\n ai = {\n summary: aiRaw,\n serviceType: 'Repair',\n urgency: 'Medium'\n };\n}\n\nreturn [\n {\n json: {\n ...lead,\n aiSummary: ai.summary,\n serviceType: ai.serviceType,\n urgency: ai.urgency\n }\n }\n];"
},
"name": "Code - Parse AI Classification",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-2368,
432
],
"id": "d19c9a66-8c4b-4320-9f77-8901a400d988"
},
{
"parameters": {
"operation": "update",
"collection": "leads",
"updateKey": "leadId",
"fields": "aiSummary,serviceType,urgency,status",
"options": {}
},
"name": "MongoDB - Update Lead AI Data",
"type": "n8n-nodes-base.mongoDb",
"typeVersion": 1.1,
"position": [
-2128,
432
],
"id": "2da86320-f62c-425b-b36d-bfbe2e1ab9d2",
"credentials": {
"mongoDb": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"mode": "expression",
"output": "={{$json.urgency === 'Emergency' ? 0 : 1}}"
},
"name": "Switch - Route by Urgency",
"type": "n8n-nodes-base.switch",
"typeVersion": 3.2,
"position": [
-1936,
672
],
"id": "991cbed6-d829-4b49-a675-06995a74f9fe",
"notes": "Output 0 = Emergency (jump straight to booking). Output 1 = Standard (normal queue)."
},
{
"parameters": {
"content": "MODULE 3 - APPOINTMENT BOOKING\n\nAn appointment record is created, available technicians are queried from MongoDB, the first free technician is assigned, and a Google Calendar event is booked. Both the Emergency and Standard paths from the Switch feed into this same booking flow.",
"height": 340,
"width": 384,
"color": 6
},
"name": "Note: MODULE 3 - APPOINTMENT B",
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-1380,
64
],
"id": "f529460f-9114-4814-a832-f2cacc84749c"
},
{
"parameters": {
"operation": "insert",
"collection": "appointments",
"fields": "leadId,name,phone,email,address,serviceType,urgency,status,createdAt",
"options": {}
},
"name": "MongoDB - Create Appointment",
"type": "n8n-nodes-base.mongoDb",
"typeVersion": 1.1,
"position": [
-1568,
608
],
"id": "507a4d87-f4b9-4fc0-9ee8-959b4e41b706",
"credentials": {
"mongoDb": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"collection": "technicians",
"options": {},
"query": "={{ JSON.stringify({ status: 'available' }) }}"
},
"name": "MongoDB - Find Available Technicians",
"type": "n8n-nodes-base.mongoDb",
"typeVersion": 1.1,
"position": [
-1360,
448
],
"id": "2fac7e77-582c-4048-a371-7f6d6ccb036e",
"credentials": {
"mongoDb": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"jsCode": "const appt = $('MongoDB - Create Appointment').first().json;\nconst techs = $input.all().map(i => i.json);\nconst tech = techs[0] || null;\nreturn [{\n json: {\n ...appt,\n technicianId: tech ? tech.technicianId : null,\n technicianName: tech ? tech.name : null,\n technicianPhone: tech ? tech.phone : null,\n technicianEmail: tech ? tech.email : null,\n technicianFound: !!tech\n }\n}];"
},
"name": "Code - Assign Technician",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-1152,
784
],
"id": "921d0e29-a405-4fa1-a750-e5b07e138a62"
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 2
},
"conditions": [
{
"leftValue": "={{$json.technicianFound}}",
"rightValue": true,
"operator": {
"type": "boolean",
"operation": "true"
},
"id": "139a53a4-55b3-406f-addc-e3a046925754"
}
],
"combinator": "and"
},
"options": {}
},
"name": "IF - Technician Available",
"type": "n8n-nodes-base.if",
"typeVersion": 2.2,
"position": [
-928,
768
],
"id": "abcf5023-5616-4ec6-a600-ba9719c84ca0"
},
{
"parameters": {
"calendar": "primary",
"start": "={{$now.plus({days:1}).toISO()}}",
"end": "={{$now.plus({days:1, hours:2}).toISO()}}",
"additionalFields": {
"description": "=Address: {{$json.address}}\\nUrgency: {{$json.urgency}}\\nTechnician: {{$json.technicianName}}",
"summary": "=HVAC {{$json.serviceType}} - {{$json.name}}"
}
},
"name": "Google Calendar - Book Appointment",
"type": "n8n-nodes-base.googleCalendar",
"typeVersion": 1.3,
"position": [
-656,
512
],
"id": "3c5e5573-33f9-491f-bfcf-0c2ed793fd74",
"credentials": {
"googleCalendarOAuth2Api": {
"name": "<your credential>"
}
},
"notes": "Demo uses tomorrow as a placeholder slot. Replace with real slot logic from technicians.schedule for a production version."
},
{
"parameters": {
"operation": "update",
"collection": "appointments",
"updateKey": "=leadId",
"fields": "technicianId,technicianName,status,calendarEventId",
"options": {}
},
"name": "MongoDB - Update Appointment",
"type": "n8n-nodes-base.mongoDb",
"typeVersion": 1.1,
"position": [
-256,
480
],
"id": "5c8147ea-2ef4-4fe6-a225-a286fdade0d4",
"alwaysOutputData": false,
"credentials": {
"mongoDb": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"jsCode": "return [{ json: { ...$json, status: 'awaiting_technician' } }];"
},
"name": "Code - No Technician Available",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-640,
768
],
"id": "5557622c-e933-46ed-a3f2-fbc343f4ec53"
},
{
"parameters": {
"content": "MODULE 4 - TECHNICIAN NOTIFICATION\n\nHTTP Request geocodes the address into a Google Maps link, then the technician is emailed and texted the job details: customer, address, service type, map link, and appointment time.",
"height": 320,
"width": 380,
"color": 6
},
"name": "Note: MODULE 4 - TECHNICIAN NO",
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-368,
-48
],
"id": "6cf548b5-f9c4-4c74-81ab-93aedb56ad49"
},
{
"parameters": {
"jsCode": "const appt = $('Code - Assign Technician').first().json;\nreturn [{\n json: {\n ...appt,\n mapsLink: 'https://www.google.com/maps/search/?api=1&query=' + encodeURIComponent(appt.address)\n }\n}];"
},
"name": "Code - Build Maps Link",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
0,
272
],
"id": "4e98b5c5-2557-4070-881a-a7699b8ff9f1"
},
{
"parameters": {
"sendTo": "={{$json.technicianEmail}}",
"subject": "=New job assigned - {{$json.serviceType}} ({{$json.urgency}})",
"message": "=You have a new job.\n\nCustomer: {{$json.name}}\nAddress: {{$json.address}}\nMap: {{$json.mapsLink}}\nService: {{$json.serviceType}}\nUrgency: {{$json.urgency}}\nAppointment time: {{$json.start}}",
"options": {}
},
"name": "Gmail - Notify Technician",
"type": "n8n-nodes-base.gmail",
"typeVersion": 2.1,
"position": [
272,
160
],
"id": "9445fe0e-3c52-4a29-baa0-4f43bfa53661",
"credentials": {
"gmailOAuth2": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"from": "+18312822077",
"to": "={{$json.technicianPhone}}",
"message": "=New {{$json.urgency}} job: {{$json.serviceType}} at {{$json.address}}. Map: {{$json.mapsLink}}",
"options": {}
},
"name": "Twilio - Notify Technician SMS",
"type": "n8n-nodes-base.twilio",
"typeVersion": 1,
"position": [
272,
336
],
"id": "09c4fa94-642a-4171-ab84-36815dc18f93",
"credentials": {
"twilioApi": {
"name": "<your credential>"
}
},
"onError": "continueRegularOutput"
},
{
"parameters": {
"content": "MODULE 5 - WORK ORDER CREATION\n\nGenerates a Work Order ID and saves a full record (customer info, technician info, service type, appointment details, status = Assigned) into MongoDB.",
"height": 240,
"width": 380,
"color": 6
},
"name": "Note: MODULE 5 - WORK ORDER CR",
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-480,
944
],
"id": "871f2e58-a909-447a-b590-8dc5a985e283"
},
{
"parameters": {
"jsCode": "const appt = $('Code - Build Maps Link').first().json;\nconst workOrderId = 'WO-' + Date.now().toString(36).toUpperCase();\nreturn [{\n json: {\n workOrderId,\n leadId: appt.leadId,\n customerName: appt.name,\n customerPhone: appt.phone,\n customerEmail: appt.email,\n address: appt.address,\n technicianId: appt.technicianId,\n technicianName: appt.technicianName,\n serviceType: appt.serviceType,\n urgency: appt.urgency,\n appointmentTime: appt.start,\n status: 'Assigned',\n createdAt: new Date().toISOString()\n }\n}];"
},
"name": "Code - Generate Work Order",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
16,
576
],
"id": "840884d4-de5e-411e-a1f7-01dde248c690"
},
{
"parameters": {
"operation": "insert",
"collection": "work_orders",
"fields": "workOrderId,leadId,customerName,customerPhone,customerEmail,address,technicianId,technicianName,serviceType,urgency,appointmentTime,status,createdAt",
"options": {}
},
"name": "MongoDB - Create Work Order",
"type": "n8n-nodes-base.mongoDb",
"typeVersion": 1.1,
"position": [
256,
560
],
"id": "977ed2f9-85fd-4b53-8c89-8d376ba5e068",
"credentials": {
"mongoDb": {
"name": "<your credential>"
}
},
"notes": "Status field cycles through Assigned -> In Progress -> Completed as the technician updates the job (update this record from a separate technician-facing form/workflow)."
},
{
"parameters": {
"content": "MODULE 6 - CUSTOMER UPDATES\n\nThe customer is emailed and texted confirming their appointment and technician assignment. A Merge node combines both notification results before logging them to MongoDB.",
"height": 300,
"width": 380,
"color": 6
},
"name": "Note: MODULE 6 - CUSTOMER UPDA",
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
480,
816
],
"id": "ffe0b054-5e59-4f39-a617-6a80ad28c4a3"
},
{
"parameters": {
"sendTo": "={{$json.customerEmail}}",
"subject": "=Your HVAC appointment is confirmed - {{$json.workOrderId}}",
"message": "=Hi {{$json.customerName}},\n\nYour {{$json.serviceType}} appointment is confirmed.\nTechnician: {{$json.technicianName}}\nDate/time: {{$json.appointmentTime}}\n\nWork order: {{$json.workOrderId}}\n\nHVACFlow Team",
"options": {}
},
"name": "Gmail - Customer Appointment Confirmed",
"type": "n8n-nodes-base.gmail",
"typeVersion": 2.1,
"position": [
560,
176
],
"id": "5a9e7efe-89e8-4346-b2fc-5490e8909f69",
"credentials": {
"gmailOAuth2": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"from": "+18312822077",
"to": "={{$json.customerPhone}}",
"message": "=Hi {{$json.customerName}}, your HVACFlow appointment is confirmed with {{$json.technicianName}} on {{$json.appointmentTime}}.",
"options": {}
},
"name": "Twilio - Customer SMS Confirmation",
"type": "n8n-nodes-base.twilio",
"typeVersion": 1,
"position": [
592,
544
],
"id": "320209c0-fef8-42a7-93a0-7bd943c4c7ad",
"credentials": {
"twilioApi": {
"name": "<your credential>"
}
},
"onError": "continueRegularOutput"
},
{
"parameters": {},
"name": "Merge - Notification Results",
"type": "n8n-nodes-base.merge",
"typeVersion": 3.1,
"position": [
848,
320
],
"id": "c0b84dd9-60c9-4e4d-a197-057325e9b32a"
},
{
"parameters": {
"operation": "insert",
"collection": "notifications",
"fields": "workOrderId,leadId,type,sentAt",
"options": {}
},
"name": "MongoDB - Log Notifications",
"type": "n8n-nodes-base.mongoDb",
"typeVersion": 1.1,
"position": [
1008,
192
],
"id": "05fdeeaa-2005-491d-89c7-4ebf64069121",
"credentials": {
"mongoDb": {
"name": "<your credential>"
}
},
"notes": "Logs that email + SMS notifications were sent, for auditing/debugging."
},
{
"parameters": {
"content": "MODULE 7 - DAILY ANALYTICS REPORT\n\nRuns every day at 8 AM. Counts today's leads, appointments booked, jobs completed, and emergency requests from MongoDB, then emails a summary report to the business owner.",
"height": 300,
"width": 380,
"color": 6
},
"name": "Note: MODULE 7 - DAILY ANALYTI",
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-2960,
832
],
"id": "dcc509a8-394e-4556-af3d-f11c6cdcab04"
},
{
"parameters": {
"rule": {
"interval": [
{
"field": "cronExpression",
"expression": "0 8 * * *"
}
]
}
},
"name": "Schedule Trigger - Daily 8AM",
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1.2,
"position": [
-3344,
1152
],
"id": "e1c8c5d3-811a-4df7-aa47-b95c8af86cd3"
},
{
"parameters": {
"operation": "aggregate",
"collection": "leads",
"query": "={{ JSON.stringify([{ $match: { createdAt: { $gte: $today } } }, { $count: 'total' }]) }}"
},
"name": "MongoDB - Count Leads Today",
"type": "n8n-nodes-base.mongoDb",
"typeVersion": 1.1,
"position": [
-3120,
1040
],
"id": "48ef2df5-35a0-47ff-b0cc-bbdc3baf1f1a",
"credentials": {
"mongoDb": {
"name": "<your credential>"
}
},
"notes": "$today should be set via an upstream Set node, or replace with your preferred date-range query."
},
{
"parameters": {
"operation": "aggregate",
"collection": "appointments",
"query": "={{ JSON.stringify([{ $match: { createdAt: { $gte: $today } } }, { $count: 'total' }]) }}"
},
"name": "MongoDB - Count Appointments Today",
"type": "n8n-nodes-base.mongoDb",
"typeVersion": 1.1,
"position": [
-3120,
1152
],
"id": "f309fe9b-e232-4859-9655-a5f6e7643a5f",
"credentials": {
"mongoDb": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"operation": "aggregate",
"collection": "work_orders",
"query": "={{ JSON.stringify([{ $match: { status: 'Completed', createdAt: { $gte: $today } } }, { $count: 'total' }]) }}"
},
"name": "MongoDB - Count Completed Jobs",
"type": "n8n-nodes-base.mongoDb",
"typeVersion": 1.1,
"position": [
-3120,
1248
],
"id": "184aefa0-1619-4ab3-9a7e-74e10b418e50",
"credentials": {
"mongoDb": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"operation": "aggregate",
"collection": "leads",
"query": "={{ JSON.stringify([{ $match: { urgency: 'Emergency', createdAt: { $gte: $today } } }, { $count: 'total' }]) }}"
},
"name": "MongoDB - Count Emergency Requests",
"type": "n8n-nodes-base.mongoDb",
"typeVersion": 1.1,
"position": [
-3120,
1344
],
"id": "ffdb94fc-e327-44a4-9341-15aba6530918",
"credentials": {
"mongoDb": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"mode": "combine",
"combineBy": "combineByPosition",
"options": {
"includeUnpaired": true
}
},
"name": "Merge - Combine Report Stats",
"type": "n8n-nodes-base.merge",
"typeVersion": 3.1,
"position": [
-2896,
1200
],
"id": "d558a46d-981f-4f44-840e-d570033c3c41"
},
{
"parameters": {
"jsCode": "const items = $input.all().map(i => i.json);\nconst get = (i) => (items[i] && items[i].total) ? items[i].total : 0;\nreturn [{\n json: {\n leadsToday: get(0),\n appointmentsToday: get(1),\n completedToday: get(2),\n emergenciesToday: get(3),\n reportDate: new Date().toDateString()\n }\n}];"
},
"name": "Code - Format Daily Report",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-2688,
1200
],
"id": "6a7fe5eb-2efc-4bd4-a0b3-15813ad613cd"
},
{
"parameters": {
"sendTo": "muhammadaryangohar@gmail.com",
"subject": "=HVACFlow daily report - {{$json.reportDate}}",
"message": "=Daily summary for {{$json.reportDate}}:\n\nTotal leads: {{$json.leadsToday}}\nAppointments booked: {{$json.appointmentsToday}}\nJobs completed: {{$json.completedToday}}\nEmergency requests: {{$json.emergenciesToday}}\n\n- HVACFlow automated report",
"options": {}
},
"name": "Gmail - Send Daily Report",
"type": "n8n-nodes-base.gmail",
"typeVersion": 2.1,
"position": [
-2464,
1200
],
"id": "00d226ff-8cf5-4094-8409-2139d98ccf52",
"credentials": {
"gmailOAuth2": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"method": "POST",
"url": "=https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent?key={{$env.GEMINI_API_KEY}}",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Content-Type",
"value": "application/json"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={{ JSON.stringify({ contents: [ { parts: [ { text: \"You are an HVAC dispatch assistant. Read the customer message and reply ONLY with strict JSON: {\\\"summary\\\": string, \\\"serviceType\\\": \\\"Installation|Repair|Maintenance\\\", \\\"urgency\\\": \\\"Low|Medium|High|Emergency\\\"}\\n\\nCustomer message: \" + $json.message } ] } ] }) }}",
"options": {}
},
"name": "Gemini API - Classify Lead",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
-2576,
656
],
"id": "693d1246-0e12-4052-8bda-e1a7c4c8d453",
"notes": "Replace the Authorization header value with your real OpenAI API key or attach an HTTP Header Auth credential."
},
{
"parameters": {
"formTitle": "HVAC Service Request Portal",
"formDescription": "Please fill out this form to request HVAC repair, installation, or maintenance services. Our team will contact you shortly.",
"formFields": {
"values": [
{
"fieldLabel": "Full Name",
"fieldName": "name",
"placeholder": "Enter your full name",
"requiredField": true
},
{
"fieldLabel": "Phone Number",
"fieldName": "phone",
"placeholder": "+923001234567",
"requiredField": true
},
{
"fieldLabel": "Email Address",
"fieldType": "email",
"fieldName": "Email",
"placeholder": "yourname@example.com",
"requiredField": true
},
{
"fieldLabel": "Service Address",
"fieldName": "address",
"placeholder": "House #, Street, City",
"requiredField": true
},
{
"fieldLabel": "serviceRequired",
"fieldType": "dropdown",
"fieldName": "serviceRequired",
"fieldOptions": {
"values": [
{
"option": "Repair"
},
{
"option": "Installation"
},
{
"option": "Miantenance"
}
]
},
"requiredField": true
},
{
"fieldLabel": "Describe the Problem",
"fieldType": "textarea",
"fieldName": "message",
"placeholder": "Example: My AC is not cooling properly."
}
]
},
"options": {}
},
"type": "n8n-nodes-base.formTrigger",
"typeVersion": 2.6,
"position": [
-3488,
464
],
"id": "e31b4c49-4e74-46ce-ada4-90275d9573a9",
"name": "On form submission"
},
{
"parameters": {
"jsCode": "const appt = $('Code - Assign Technician').first().json;\nconst cal = $input.first().json;\nreturn [{\n json: {\n ...appt,\n calendarEventId: cal.id,\n status: 'confirmed'\n }\n}];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-464,
496
],
"id": "11c640ff-4fcb-4eae-82ff-505b82ed534b",
"name": "Code in JavaScript"
},
{
"parameters": {
"jsCode": "const lead = $('Code - Parse AI Classification').first().json;\nreturn [{\n json: {\n ...lead,\n status: 'appointment_pending',\n createdAt: new Date().toISOString()\n }\n}];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-1728,
384
],
"id": "d6baf4f5-e882-4b0a-b040-a1f63e1f8c60",
"name": "Code in JavaScript1"
}
],
"connections": {
"Code - Generate Lead ID": {
"main": [
[
{
"node": "MongoDB - Save Lead",
"type": "main",
"index": 0
}
]
]
},
"MongoDB - Save Lead": {
"main": [
[
{
"node": "Gmail - Lead Confirmation Email",
"type": "main",
"index": 0
},
{
"node": "Twilio - Lead Confirmation SMS",
"type": "main",
"index": 0
},
{
"node": "Gemini API - Classify Lead",
"type": "main",
"index": 0
}
]
]
},
"Code - Parse AI Classification": {
"main": [
[
{
"node": "MongoDB - Update Lead AI Data",
"type": "main",
"index": 0
}
]
]
},
"MongoDB - Update Lead AI Data": {
"main": [
[
{
"node": "Switch - Route by Urgency",
"type": "main",
"index": 0
}
]
]
},
"Switch - Route by Urgency": {
"main": [
[
{
"node": "MongoDB - Create Appointment",
"type": "main",
"index": 0
}
],
[
{
"node": "Code in JavaScript1",
"type": "main",
"index": 0
}
]
]
},
"MongoDB - Create Appointment": {
"main": [
[
{
"node": "MongoDB - Find Available Technicians",
"type": "main",
"index": 0
}
]
]
},
"MongoDB - Find Available Technicians": {
"main": [
[
{
"node": "Code - Assign Technician",
"type": "main",
"index": 0
}
]
]
},
"Code - Assign Technician": {
"main": [
[
{
"node": "IF - Technician Available",
"type": "main",
"index": 0
}
]
]
},
"IF - Technician Available": {
"main": [
[
{
"node": "Google Calendar - Book Appointment",
"type": "main",
"index": 0
}
],
[
{
"node": "Code - No Technician Available",
"type": "main",
"index": 0
}
]
]
},
"Google Calendar - Book Appointment": {
"main": [
[
{
"node": "Code in JavaScript",
"type": "main",
"index": 0
}
]
]
},
"MongoDB - Update Appointment": {
"main": [
[
{
"node": "Code - Build Maps Link",
"type": "main",
"index": 0
}
]
]
},
"Code - Build Maps Link": {
"main": [
[
{
"node": "Gmail - Notify Technician",
"type": "main",
"index": 0
},
{
"node": "Twilio - Notify Technician SMS",
"type": "main",
"index": 0
},
{
"node": "Code - Generate Work Order",
"type": "main",
"index": 0
}
]
]
},
"Code - Generate Work Order": {
"main": [
[
{
"node": "MongoDB - Create Work Order",
"type": "main",
"index": 0
}
]
]
},
"MongoDB - Create Work Order": {
"main": [
[
{
"node": "Gmail - Customer Appointment Confirmed",
"type": "main",
"index": 0
},
{
"node": "Twilio - Customer SMS Confirmation",
"type": "main",
"index": 0
}
]
]
},
"Gmail - Customer Appointment Confirmed": {
"main": [
[
{
"node": "Merge - Notification Results",
"type": "main",
"index": 0
}
]
]
},
"Twilio - Customer SMS Confirmation": {
"main": [
[
{
"node": "Merge - Notification Results",
"type": "main",
"index": 1
}
]
]
},
"Merge - Notification Results": {
"main": [
[
{
"node": "MongoDB - Log Notifications",
"type": "main",
"index": 0
}
]
]
},
"Schedule Trigger - Daily 8AM": {
"main": [
[
{
"node": "MongoDB - Count Leads Today",
"type": "main",
"index": 0
},
{
"node": "MongoDB - Count Appointments Today",
"type": "main",
"index": 0
},
{
"node": "MongoDB - Count Completed Jobs",
"type": "main",
"index": 0
},
{
"node": "MongoDB - Count Emergency Requests",
"type": "main",
"index": 0
}
]
]
},
"MongoDB - Count Leads Today": {
"main": [
[
{
"node": "Merge - Combine Report Stats",
"type": "main",
"index": 0
}
]
]
},
"MongoDB - Count Appointments Today": {
"main": [
[
{
"node": "Merge - Combine Report Stats",
"type": "main",
"index": 1
}
]
]
},
"Merge - Combine Report Stats": {
"main": [
[
{
"node": "Code - Format Daily Report",
"type": "main",
"index": 0
}
]
]
},
"Code - Format Daily Report": {
"main": [
[
{
"node": "Gmail - Send Daily Report",
"type": "main",
"index": 0
}
]
]
},
"Gemini API - Classify Lead": {
"main": [
[
{
"node": "Code - Parse AI Classification",
"type": "main",
"index": 0
}
]
]
},
"On form submission": {
"main": [
[
{
"node": "Code - Generate Lead ID",
"type": "main",
"index": 0
}
]
]
},
"Code in JavaScript": {
"main": [
[
{
"node": "MongoDB - Update Appointment",
"type": "main",
"index": 0
}
]
]
},
"Code in JavaScript1": {
"main": [
[
{
"node": "MongoDB - Create Appointment",
"type": "main",
"index": 0
}
]
]
}
},
"active": false,
"settings": {
"executionOrder": "v1",
"binaryMode": "separate",
"availableInMCP": false
},
"versionId": "b85596b0-ebb9-4c90-aed4-23c74bbeffea",
"meta": {
"templateCredsSetupCompleted": true
},
"nodeGroups": [],
"id": "utgQHRAhxEAqWzKW",
"tags": []
}
Credentials you'll need
Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.
gmailOAuth2googleCalendarOAuth2ApimongoDbtwilioApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
HVACFlow - Smart HVAC Service Management System copy. Uses mongoDb, gmail, twilio, googleCalendar. Scheduled trigger; 42 nodes.
Source: https://github.com/muhammadaryangohar-dev/hvacflow-smart-hvac-automation/blob/main/workflows/hvacflow.json — 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.
Relatórios aos Laboratórios. Uses httpRequest, gmail, formTrigger. Scheduled trigger; 54 nodes.
Relatórios aos Laboratórios. Uses httpRequest, gmail, formTrigger. Scheduled trigger; 48 nodes.
Splitout Googlecalendar. Uses httpRequest, scheduleTrigger, googleCalendar, splitOut. Scheduled trigger; 19 nodes.
It’s very important to come prepared to Sales calls. This often means a lot of manual research about the person you’re calling with. This workflow delivers the latest social media activity (LinkedIn +
Httprequest Workflow. Uses httpRequest, googleCalendar, clearbit, gmail. Scheduled trigger; 19 nodes.