This workflow corresponds to n8n.io template #12637 — we link there as the canonical source.
This workflow follows the Gmail → HTTP Request 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 →
{
"meta": {
"templateCredsSetupCompleted": true
},
"nodes": [
{
"id": "bfcfda11-8dd6-4773-bb90-79abcfcbcbee",
"name": "Respond to Webhook",
"type": "n8n-nodes-base.respondToWebhook",
"position": [
3488,
1488
],
"parameters": {
"options": {},
"respondWith": "json",
"responseBody": "={\n \"plainToken\": \"{{ $json.plainToken }}\",\n \"encryptedToken\": \"{{ $json.encryptedToken }}\"\n}"
},
"typeVersion": 1.4
},
{
"id": "590c4266-351a-4d4b-8c61-8df858241e2e",
"name": "Zoom Webhook",
"type": "n8n-nodes-base.webhook",
"position": [
2592,
1584
],
"parameters": {
"path": "7b08a076-7beb-4eec-959a-3e1b2051db79",
"options": {},
"httpMethod": "POST",
"responseMode": "responseNode"
},
"typeVersion": 2.1
},
{
"id": "ac011896-4a1d-48ee-8c4f-deb10ddec617",
"name": "Form Webhook",
"type": "n8n-nodes-base.webhook",
"position": [
3456,
2112
],
"parameters": {
"path": "0ab18fbb-1c85-42da-ad80-d5e663aa0668",
"options": {},
"httpMethod": "POST"
},
"typeVersion": 2.1
},
{
"id": "0ef7ecf9-665c-4235-80ed-97e5ababb0b6",
"name": "Set From Form",
"type": "n8n-nodes-base.set",
"position": [
3680,
2112
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "5ebcf673-5062-403b-b790-dad8acc48876",
"name": "topic",
"type": "string",
"value": "={{ $json.body[\"Classroom Name\"] }}"
},
{
"id": "20e5bc32-0a17-478f-abee-bdf99b7614aa",
"name": "shareLink",
"type": "string",
"value": "={{ $json.body[\"Zoom Share Link\"] }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "f0004d1d-b996-4dad-bc1d-05b57313ae79",
"name": "Set From Zoom",
"type": "n8n-nodes-base.set",
"position": [
3856,
1760
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "e653fb6a-cf86-4a4f-b64b-7875f7d3f85d",
"name": "topic",
"type": "string",
"value": "={{ $('Webhook Validation?').item.json.body.payload.object.topic }}"
},
{
"id": "9d0e77b4-df9c-436d-b30a-671886cde9c4",
"name": "shareLink",
"type": "string",
"value": "={{ $('Webhook Validation?').item.json.body.payload.object.share_url }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "90eea11d-eb82-47a7-bf66-0ae22608d6e7",
"name": "Merge",
"type": "n8n-nodes-base.merge",
"position": [
4160,
1776
],
"parameters": {},
"typeVersion": 3.2
},
{
"id": "bab3dc91-17c7-4875-8b2b-184c66b17d28",
"name": "Find Active Course by Name",
"type": "n8n-nodes-base.code",
"position": [
5760,
1760
],
"parameters": {
"jsCode": "// Get input string from previous node\nconst input = $('Merge').first().json.topic;\nconst classroomName = typeof input === 'string' ? input.trim() : '';\n\n// Get courses\nconst payload = $('Get All Classrooms').first().json;\nconst courses = payload.courses || [];\n\n// Filter ACTIVE courses only\nconst activeCourses = courses.filter(course =>\n course.courseState === 'ACTIVE'\n);\n\n// Match (case-insensitive, exact)\nconst target = classroomName.toLowerCase();\nconst matchedCourse = activeCourses.find(course =>\n course.name.trim().toLowerCase() === target\n);\n\nif (matchedCourse) {\n return {\n json: {\n status: \"Found\",\n courseId: matchedCourse.id,\n courseName: matchedCourse.name\n }\n };\n}\n\nreturn {\n json: {\n status: \"Not Found\",\n searchedName: classroomName,\n activeCourseCount: activeCourses.length\n }\n};"
},
"typeVersion": 2
},
{
"id": "103ebc31-5e22-48eb-ad93-54786b8ddc6a",
"name": "Find Topic",
"type": "n8n-nodes-base.code",
"position": [
6224,
1760
],
"parameters": {
"jsCode": "const topics = $input.item.json.topic || [];\nconst topicName = $('Set Parameters').first().json.desiredTopic;\nconst targetTopic = topics.find(t => t.name === topicName);\n\nif (targetTopic) {\n return {\n status: \"found\",\n topicId: targetTopic.topicId\n };\n} else {\n return {\n status: \"not found\"\n };\n}"
},
"typeVersion": 2
},
{
"id": "f1ef74e6-ccd6-4921-9318-e8ad89ef3ba6",
"name": "Get All Topics in Class",
"type": "n8n-nodes-base.httpRequest",
"position": [
6000,
1760
],
"parameters": {
"url": "=https://classroom.googleapis.com/v1/courses/{{ $json.courseId }}/topics",
"options": {},
"authentication": "predefinedCredentialType",
"nodeCredentialType": "googleOAuth2Api"
},
"credentials": {
"googleOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.3,
"alwaysOutputData": true
},
{
"id": "2637f809-3dd0-491c-913e-0a69a78beb2d",
"name": "Publish Materials to Topic",
"type": "n8n-nodes-base.httpRequest",
"position": [
6688,
1744
],
"parameters": {
"url": "=https://classroom.googleapis.com/v1/courses/{{ $('Find Active Course by Name').item.json.courseId }}/courseWorkMaterials",
"method": "POST",
"options": {},
"jsonBody": "={\n \"title\": \"{{ $('Generate Material Title').item.json.title }}\",\n \"state\": \"PUBLISHED\",\n \"topicId\": \"{{ $json.topicId }}\",\n \"materials\": [\n {\n \"link\": {\n \"url\": \"{{ $('Zoom Webhook').item.json.body.payload.object.share_url }} \",\n \"title\": \"Zoom Recording\"\n }\n }\n ]\n}",
"sendBody": true,
"specifyBody": "json",
"authentication": "predefinedCredentialType",
"nodeCredentialType": "googleOAuth2Api"
},
"credentials": {
"googleOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.3
},
{
"id": "2a05b165-49fa-4d8e-9c26-0b99a574d92a",
"name": "If2",
"type": "n8n-nodes-base.if",
"position": [
6448,
1760
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "3d9ffa69-f305-4361-b5d6-a633fb9e7796",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.status }}",
"rightValue": "found"
}
]
}
},
"typeVersion": 2.2
},
{
"id": "90ba9e22-b3a0-42d4-bb37-f25d9fd6a6b8",
"name": "Duration Filtering",
"type": "n8n-nodes-base.code",
"position": [
3312,
1776
],
"parameters": {
"jsCode": "const zoomPayload = $('Zoom Webhook').item.json.body.payload.object;\nconst desiredThreshold = $input.first().json.durationThreshold;\n\nif (!zoomPayload || !zoomPayload.recording_files || zoomPayload.recording_files.length === 0) {\n return [{ json: { status: false, reason: \"no_recording_data\" } }];\n}\n\n// Get any recording file with start/end times\nconst recordingFile = zoomPayload.recording_files[0];\n\nif (!recordingFile.recording_start || !recordingFile.recording_end) {\n return [{ json: { status: false, reason: \"missing_timestamps\" } }];\n}\n\n// Calculate duration in minutes\nconst start = new Date(recordingFile.recording_start);\nconst end = new Date(recordingFile.recording_end);\nconst durationMinutes = (end - start) / 1000 / 60;\n\n// Filter out recordings under 30 minutes\nif (durationMinutes < desiredThreshold) {\n return [{ json: { status: false, reason: \"too_short\", durationMinutes } }];\n}\n\nreturn [{ json: { status: true, durationMinutes } }];"
},
"typeVersion": 2
},
{
"id": "a8d6ca5a-568f-48f8-a405-5c6b3ea5e63f",
"name": "Relevant Duration?",
"type": "n8n-nodes-base.if",
"position": [
3536,
1776
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "6f951b70-2126-4517-971a-d90a3f85a86c",
"operator": {
"type": "boolean",
"operation": "true",
"singleValue": true
},
"leftValue": "={{ $json.status }}",
"rightValue": "true"
}
]
}
},
"typeVersion": 2.2
},
{
"id": "610bc66b-d323-4613-8b41-91e1cb5729d9",
"name": "Switch",
"type": "n8n-nodes-base.switch",
"position": [
5200,
1776
],
"parameters": {
"rules": {
"values": [
{
"outputKey": "True",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "20777556-3bfa-4433-be7e-19666e268597",
"operator": {
"type": "boolean",
"operation": "true",
"singleValue": true
},
"leftValue": "={{ $json.output[0].content[0].text.status }}",
"rightValue": ""
}
]
},
"renameOutput": true
},
{
"outputKey": "False",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "6b647757-041b-4513-8bd1-c9abbc3ed8f2",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.output[0].content[0].text.message }}",
"rightValue": "zoom call is class recording but class not found."
}
]
},
"renameOutput": true
}
]
},
"options": {}
},
"typeVersion": 3.3
},
{
"id": "45b12850-9d21-4b75-97bc-c3ca865d3e36",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
4320,
1616
],
"parameters": {
"color": 7,
"width": 1088,
"height": 352,
"content": "## Validate calls by name\nHere we check if call name has a match with a Class "
},
"typeVersion": 1
},
{
"id": "f480d680-e633-48bd-bee1-bc3b1367995d",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
2976,
1344
],
"parameters": {
"color": 7,
"width": 720,
"height": 320,
"content": "## Zoom Webhook Validation\nIt's a Zoom's initial handshake."
},
"typeVersion": 1
},
{
"id": "9cdda68f-0a5f-4a22-bcc4-549e99672742",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
3392,
1984
],
"parameters": {
"color": 7,
"width": 448,
"height": 304,
"content": "## Form Input\nCreate a separate form for manual uploads if something fails (e.g. you specified a Class Topic that doesn't exist or your call does not have a correct Class name)"
},
"typeVersion": 1
},
{
"id": "7db3dbd1-d7ac-4b40-ad37-1df27bb25335",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
3216,
1680
],
"parameters": {
"color": 7,
"width": 528,
"height": 272,
"content": "## Check Call Duration\nSpecify the threshold in the previous node and filter out calls that do not match."
},
"typeVersion": 1
},
{
"id": "3108a43b-ba60-40b9-94ea-4d54076191d9",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
5456,
1616
],
"parameters": {
"color": 7,
"width": 1440,
"height": 336,
"content": "## Find Class & Upload Materials\nHere we get the course ID to upload our materials, search for specified topic and actually upload the call to Google Class"
},
"typeVersion": 1
},
{
"id": "2eb26920-543d-4039-8436-3dcc163cc202",
"name": "Get All Classrooms",
"type": "n8n-nodes-base.httpRequest",
"position": [
4400,
1776
],
"parameters": {
"url": "https://classroom.googleapis.com/v1/courses",
"options": {},
"authentication": "predefinedCredentialType",
"nodeCredentialType": "googleOAuth2Api"
},
"credentials": {
"googleOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.3
},
{
"id": "0bfa7979-ccb2-4b8d-8ec4-3aa9f7707cb9",
"name": "Sticky Note5",
"type": "n8n-nodes-base.stickyNote",
"position": [
1872,
1280
],
"parameters": {
"width": 644,
"height": 990,
"content": "## Auto-publish Zoom recordings to Google Classroom\n\n### About\nThis flow is ideal for online schools that use Zoom to teach classes and Google Classroom for storing materials and homework.\n\nIt listens for Zoom webhooks that come after each recorded call is uploaded to Zoom Cloud (you'll need Zoom paid plan).\nWhen new meeting comes, it filters out calls that last less than 30 mins. \nAfter duration check, it checks if there is a Google Class that matches the call name. Your call must be named exactly as the Google Class you want the call to be uploaded to. \nIf the class is found, it will extract the Class ID. This flow assumes that you have a specific topic used for storing class recordings and materials, so it will look for this topic and upload the material. If topic is not found, you'll get an email.\n\n### Setup\n- [ ] Set duration threshold and topic name in the \"Set Parameters\" node.\n- [ ] Specify desired name pattern to be generated (currently generates recording date). You can keep it as is and adjust later manually.\n- [ ] Register the webhook URL in Zoom and enable recording.completed notifications.\n- [ ] Set the HMAC signing secret in the Crypto node to match Zoom.\n- [ ] Validate the URL in Zoom (make sure to publish the workflow)\n- [ ] Connect Google Classroom (OAuth) and create a connection with the following scopes: \nhttps://www.googleapis.com/auth/classroom.courseworkmaterials\nhttps://www.googleapis.com/auth/classroom.topics.readonly https://www.googleapis.com/auth/classroom.courses.readonly https://www.googleapis.com/auth/classroom.announcements https://www.googleapis.com/auth/classroom.coursework.students\nThese scopes should be enough but if you get \"Not enough scopes\" error, just use Claude or ChatGPT to get the required scope and then edit the credential. Put spaces between scopes.\n- [ ] Connect a Gmail account for alert emails.\n- [ ] Add OpenAI (LangChain) API credentials for the model used to validate names.\n- [ ] (Optional) Configure the form webhook for manual upload entries or testing and add a form link to the Gmail node.\n\n### Improve\nThe last node in the system returns a direct link to the newly created material. You can add a Gmail node to email you that link and easily go and update the material if needed."
},
"typeVersion": 1
},
{
"id": "de335675-bbcb-43f8-89d9-7d74a24273bb",
"name": "Set Data",
"type": "n8n-nodes-base.set",
"position": [
3264,
1488
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "a325eb0e-783e-4f96-a398-9391b3e3377e",
"name": "plainToken",
"type": "string",
"value": "={{ $('Zoom Webhook').item.json.body.payload.plainToken }}"
},
{
"id": "4b8b572a-8740-4ce1-8173-ed909b87ec1f",
"name": "encryptedToken",
"type": "string",
"value": "={{ $json.data }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "90a5a1a8-a776-4234-8dfb-774d41f7f872",
"name": "Encryption",
"type": "n8n-nodes-base.crypto",
"position": [
3040,
1488
],
"parameters": {
"type": "SHA256",
"value": "={{ $json.body.payload.plainToken }}",
"action": "hmac",
"secret": "YOUR_CREDENTIAL_HERE"
},
"typeVersion": 1
},
{
"id": "3ee8e5fc-8664-4c64-8c77-13232cd1d68c",
"name": "Webhook Validation?",
"type": "n8n-nodes-base.if",
"position": [
2816,
1584
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "973ce2d3-4f2c-4951-917e-31156de03b1c",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.body.event }}",
"rightValue": "endpoint.url_validation"
}
]
}
},
"typeVersion": 2.2
},
{
"id": "bef2e036-28b1-4835-bed1-46c66361108b",
"name": "Return Active Classes' Names",
"type": "n8n-nodes-base.code",
"position": [
4624,
1776
],
"parameters": {
"jsCode": "const payload = $input.first().json;\n\nconst activeCourseNames = payload.courses\n .filter(course => course.courseState === \"ACTIVE\")\n .map(course => course.name);\n\nreturn [{ json: { courses: activeCourseNames } }];"
},
"typeVersion": 2
},
{
"id": "1093fdef-e146-4f53-94a4-921ced876aed",
"name": "Check Classes",
"type": "@n8n/n8n-nodes-langchain.openAi",
"position": [
4848,
1776
],
"parameters": {
"modelId": {
"__rl": true,
"mode": "list",
"value": "gpt-4.1-mini",
"cachedResultName": "GPT-4.1-MINI"
},
"options": {
"textFormat": {
"textOptions": {
"type": "json_object"
}
}
},
"simplify": false,
"responses": {
"values": [
{
"role": "system",
"content": "You're a helpuful and intelligent assistant."
},
{
"content": "=You'll get a zoom call name and current active classes.\nYour task description:\nthe correct scenario is when zoom call contains only class name and this class name has an exact match with one of the given active classes.\n\nOutput:\nreturn payload in the following format:\n\n{\"status\":boolean,\"message\":\"\"}\n\nwith one of messages (MUST BE ONLY ONE FROM BELOW) :\n1. \"zoom call is not class recording.\". set false status.\n2. \"zoom call is class recording but class not found.\" set false status.\n3. \"zoom is class recording and class is found.\" set true status."
},
{
"content": "={\n\"zoomName\":\"{{ $('Zoom Webhook').item.json.body.payload.object.topic }}\",\n\"activeClasses\":\"{{ $json.courses }}\"\n}"
}
]
},
"builtInTools": {}
},
"credentials": {
"openAiApi": {
"name": "<your credential>"
}
},
"typeVersion": 2
},
{
"id": "7cda3564-3eb5-4157-a085-5449a9f89a8f",
"name": "Topic Not Found",
"type": "n8n-nodes-base.gmail",
"position": [
6688,
1968
],
"parameters": {
"sendTo": "user@example.com",
"message": "=Topic \"2. Class Materials\" is not found for {{ $('Find Active Course by Name').item.json.courseName }}",
"options": {
"appendAttribution": false
},
"subject": "=Course not found"
},
"credentials": {
"gmailOAuth2": {
"name": "<your credential>"
}
},
"typeVersion": 2.1
},
{
"id": "8a5d7984-0086-4a4c-af8c-da89bb7251e5",
"name": "Issue with Classes",
"type": "n8n-nodes-base.gmail",
"position": [
5520,
1968
],
"parameters": {
"sendTo": "user@example.com",
"message": "={{ $('Check Classes').item.json.output[0].content[0].text.message }}. Upload video manually using this form: {INSERT MANUAL FORM LINK}",
"options": {
"appendAttribution": false
},
"subject": "=Course not found"
},
"credentials": {
"gmailOAuth2": {
"name": "<your credential>"
}
},
"typeVersion": 2.1
},
{
"id": "0a8df2f0-d0ca-48c0-a502-347684a9aafb",
"name": "Generate Material Title",
"type": "n8n-nodes-base.code",
"position": [
5520,
1760
],
"parameters": {
"jsCode": "const startTime = $('Zoom Webhook').item.json.body.payload.object.start_time;\nconst date = new Date(startTime);\n\n// Get date parts without leading zeros\nconst year = date.getFullYear();\nconst month = date.getMonth() + 1; // getMonth() returns 0-11\nconst day = date.getDate();\n\nconst title = `${day}.${month}.${year}`;\n\nreturn [{ json: { title } }];"
},
"typeVersion": 2
},
{
"id": "75ddcc59-9d77-467e-8c79-36e37e2d1e85",
"name": "Set Parameters",
"type": "n8n-nodes-base.set",
"position": [
2992,
1776
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "18ec5add-d2f5-4c69-8809-41c41bfe18ac",
"name": "durationThreshold",
"type": "number",
"value": 30
},
{
"id": "9f320c59-e17f-40f0-83ec-038288bbb76c",
"name": "desiredTopic",
"type": "string",
"value": "2. Class Materials"
}
]
}
},
"typeVersion": 3.4
}
],
"connections": {
"If2": {
"main": [
[
{
"node": "Publish Materials to Topic",
"type": "main",
"index": 0
}
],
[
{
"node": "Topic Not Found",
"type": "main",
"index": 0
}
]
]
},
"Merge": {
"main": [
[
{
"node": "Get All Classrooms",
"type": "main",
"index": 0
}
]
]
},
"Switch": {
"main": [
[
{
"node": "Generate Material Title",
"type": "main",
"index": 0
}
],
[
{
"node": "Issue with Classes",
"type": "main",
"index": 0
}
]
]
},
"Set Data": {
"main": [
[
{
"node": "Respond to Webhook",
"type": "main",
"index": 0
}
]
]
},
"Encryption": {
"main": [
[
{
"node": "Set Data",
"type": "main",
"index": 0
}
]
]
},
"Find Topic": {
"main": [
[
{
"node": "If2",
"type": "main",
"index": 0
}
]
]
},
"Form Webhook": {
"main": [
[
{
"node": "Set From Form",
"type": "main",
"index": 0
}
]
]
},
"Zoom Webhook": {
"main": [
[
{
"node": "Webhook Validation?",
"type": "main",
"index": 0
}
]
]
},
"Check Classes": {
"main": [
[
{
"node": "Switch",
"type": "main",
"index": 0
}
]
]
},
"Set From Form": {
"main": [
[
{
"node": "Merge",
"type": "main",
"index": 1
}
]
]
},
"Set From Zoom": {
"main": [
[
{
"node": "Merge",
"type": "main",
"index": 0
}
]
]
},
"Set Parameters": {
"main": [
[
{
"node": "Duration Filtering",
"type": "main",
"index": 0
}
]
]
},
"Duration Filtering": {
"main": [
[
{
"node": "Relevant Duration?",
"type": "main",
"index": 0
}
]
]
},
"Get All Classrooms": {
"main": [
[
{
"node": "Return Active Classes' Names",
"type": "main",
"index": 0
}
]
]
},
"Relevant Duration?": {
"main": [
[
{
"node": "Set From Zoom",
"type": "main",
"index": 0
}
]
]
},
"Webhook Validation?": {
"main": [
[
{
"node": "Encryption",
"type": "main",
"index": 0
}
],
[
{
"node": "Set Parameters",
"type": "main",
"index": 0
}
]
]
},
"Generate Material Title": {
"main": [
[
{
"node": "Find Active Course by Name",
"type": "main",
"index": 0
}
]
]
},
"Get All Topics in Class": {
"main": [
[
{
"node": "Find Topic",
"type": "main",
"index": 0
}
]
]
},
"Find Active Course by Name": {
"main": [
[
{
"node": "Get All Topics in Class",
"type": "main",
"index": 0
}
]
]
},
"Return Active Classes' Names": {
"main": [
[
{
"node": "Check Classes",
"type": "main",
"index": 0
}
]
]
}
}
}
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.
gmailOAuth2googleOAuth2ApiopenAiApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This flow is ideal for online schools that use Zoom to teach classes and Google Classroom for storing materials and homework.
Source: https://n8n.io/workflows/12637/ — 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.
User Signup & Verification: The workflow starts when a user signs up. It generates a verification code and sends it via SMS using Twilio. Code Validation: The user replies with the code. The workflow
Instantly map all internal URLs, perform AI-powered (ChatGPT) analysis, and deliver results in HTML via webhook, Google Sheets, or email. All from your own n8n instance!
Watch on Youtube▶️
Listens for completed Fireflies transcripts, qualifies whether a proposal is needed using OpenAI, drafts structured proposal content, populates a Google Doc template, converts to PDF, and sends it to
Sales Team V2. Uses supabase, httpRequest, crypto, openAi. Scheduled trigger; 25 nodes.