This workflow corresponds to n8n.io template #14804 — we link there as the canonical source.
This workflow follows the Google Sheets → Googlesheetstrigger 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": "dce15696-5aeb-459c-a56d-c65cb4b7fe76",
"name": "Main Sticky",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2320,
16
],
"parameters": {
"color": 2,
"width": 500,
"height": 600,
"content": "## Automate HeyGen Video Generation from Google Sheets\nEffortlessly convert text scripts in Google Sheets into AI-generated videos using HeyGen.\n\n\n### How it works\n1. Monitor Google Sheets for new row updates.\n2. Sanitize script text to prevent JSON errors.\n3. Send text to HeyGen API for processing.\n4. Poll for video completion status.\n5. Update Google Sheets with the final video URL.\n\n\n### Setup\n1. Connect your Google Sheets account.\n2. Provide your HeyGen API Key in the HTTP Request node.\n3. Configure Document ID and Sheet Name in Google nodes.\n4. Adjust the avatar and voice IDs as needed.\n\n\n### Customization\nConsolidate user-specific values (API Keys, IDs) in a Set node at the workflow start for easy configuration."
},
"typeVersion": 1
},
{
"id": "bc6f1693-f349-435e-915a-35f402d47a72",
"name": "Google Sheets Trigger",
"type": "n8n-nodes-base.googleSheetsTrigger",
"position": [
-1696,
160
],
"parameters": {
"event": "rowUpdate",
"options": {},
"pollTimes": {
"item": [
{
"mode": "everyMinute"
}
]
},
"sheetName": {
"__rl": true,
"mode": "list",
"value": "YOUR_RESOURCE_ID_HERE"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "YOUR_RESOURCE_ID_HERE"
}
},
"typeVersion": 1
},
{
"id": "2dc1d0e8-1ab6-4879-90ad-3a6979b929b5",
"name": "Has Script?",
"type": "n8n-nodes-base.if",
"position": [
-1472,
160
],
"parameters": {
"conditions": {
"string": [
{
"value1": "={{ $json.Script }}",
"operation": "isNotEmpty"
},
{
"value1": "={{ $json.Status }}",
"value2": "Completed",
"operation": "notEqual"
}
]
}
},
"typeVersion": 1
},
{
"id": "c046b6a7-18ce-4d14-ad89-6e1b44e46b54",
"name": "Process One at a Time",
"type": "n8n-nodes-base.splitInBatches",
"position": [
-1264,
144
],
"parameters": {
"options": {}
},
"typeVersion": 3
},
{
"id": "a4fe5b87-f7c3-42e6-940b-87fbfb1295d1",
"name": "Sanitize Script",
"type": "n8n-nodes-base.code",
"position": [
-1024,
160
],
"parameters": {
"jsCode": "// Sanitize the Script field to make it safe for JSON injection\n// Removes newlines, carriage returns, tabs, and escapes quotes\nconst item = $input.item.json;\n\nconst rawScript = item.Script || '';\n\nconst cleanScript = rawScript\n .replace(/\\r\\n/g, ' ') // Windows line endings\n .replace(/\\n/g, ' ') // Unix line endings\n .replace(/\\r/g, ' ') // Old Mac line endings\n .replace(/\\t/g, ' ') // Tabs\n .replace(/\\\\/g, '\\\\\\\\') // Escape backslashes first\n .replace(/\"/g, '\\\\\"') // Escape double quotes\n .replace(/\\s+/g, ' ') // Collapse multiple spaces\n .trim();\n\nreturn [{\n json: {\n ...item,\n CleanScript: cleanScript\n }\n}];"
},
"typeVersion": 2
},
{
"id": "eeabc558-954a-4f55-bfa3-a3793a9a1e7f",
"name": "Generate Video",
"type": "n8n-nodes-base.httpRequest",
"position": [
-736,
160
],
"parameters": {
"url": "YOUR_API_ENDPOINT_HERE",
"method": "POST",
"options": {},
"jsonBody": "={\n \"video_inputs\": [\n {\n \"character\": {\n \"type\": \"avatar\",\n \"avatar_id\": \"4185302635fa4de29a99ad8ca17475bc\"\n },\n \"voice\": {\n \"type\": \"text\",\n \"input_text\": \"{{ $json.CleanScript }}\",\n \"voice_id\": \"d7f0f1713ccd458790d6cffb41ad27e2\"\n }\n }\n ],\n \"dimension\": {\n \"width\": 720,\n \"height\": 1280\n }\n}",
"sendBody": true,
"sendHeaders": true,
"specifyBody": "json",
"headerParameters": {
"parameters": [
{
"name": "X-Api-Key",
"value": "sk_V2_hgu_khdB00SgqzE_dDenmzsc8IVkvjmZh4pkrngPLd6Alx72"
},
{
"name": "Content-Type",
"value": "application/json"
}
]
}
},
"typeVersion": 4.3
},
{
"id": "825db574-df10-42e7-9c5e-b92c9ffb53e3",
"name": "If",
"type": "n8n-nodes-base.if",
"position": [
-512,
160
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 3,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "51d6ebcf-1b85-4752-a61f-a343c5d0e08c",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "=",
"rightValue": ""
}
]
}
},
"typeVersion": 2.3
},
{
"id": "3a1d1e70-1ecb-444e-a8f9-7d06661901e1",
"name": "Wait",
"type": "n8n-nodes-base.wait",
"position": [
-288,
144
],
"parameters": {
"amount": 60
},
"typeVersion": 1.1
},
{
"id": "bfef54cd-103f-4e31-b62e-40ac6438db8e",
"name": "Video Status",
"type": "n8n-nodes-base.httpRequest",
"position": [
-64,
144
],
"parameters": {
"url": "YOUR_API_ENDPOINT_HERE",
"options": {},
"sendQuery": true,
"sendHeaders": true,
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"queryParameters": {
"parameters": [
{
"name": "video_id",
"value": "={{ $('Generate Video').item.json.data.video_id }}"
}
]
},
"headerParameters": {
"parameters": [
{
"name": "accept",
"value": "application/json"
}
]
}
},
"typeVersion": 4.3
},
{
"id": "945b5fee-2151-48f9-a16e-dc2fe46f3a9e",
"name": "Is Complete?1",
"type": "n8n-nodes-base.if",
"position": [
240,
144
],
"parameters": {
"conditions": {
"string": [
{
"value1": "={{ $json.data.status }}",
"value2": "completed"
}
]
}
},
"typeVersion": 1
},
{
"id": "b02f439c-71cf-4718-a04e-795cbdc25592",
"name": "Update Sheet with Video1",
"type": "n8n-nodes-base.googleSheets",
"position": [
480,
128
],
"parameters": {
"columns": {
"value": {
"Row_ID": "={{ $('Process One at a Time').item.json.Row_ID }}",
"Status": "Completed",
"Video_URL": "={{ $json.data.video_url }}",
"row_number": 0,
"Completed_At": "={{ $now.toISO() }}"
},
"schema": [
{
"id": "Row_ID",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Row_ID",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Script",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Script",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Status",
"type": "string",
"display": true,
"required": false,
"displayName": "Status",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Video_URL",
"type": "string",
"display": true,
"required": false,
"displayName": "Video_URL",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Completed_At",
"type": "string",
"display": true,
"required": false,
"displayName": "Completed_At",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "row_number",
"type": "number",
"display": true,
"removed": false,
"readOnly": true,
"required": false,
"displayName": "row_number",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [
"Row_ID"
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "update",
"sheetName": {
"__rl": true,
"mode": "list",
"value": "YOUR_RESOURCE_ID_HERE"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "YOUR_RESOURCE_ID_HERE"
}
},
"typeVersion": 4.5
},
{
"id": "11b872c3-8ae5-465b-905a-9baccafa3c26",
"name": "Wait Before Retry1",
"type": "n8n-nodes-base.wait",
"position": [
480,
320
],
"parameters": {
"amount": 60
},
"typeVersion": 1.1
},
{
"id": "ac9ac3b8-3833-4b0d-a1b4-6c3b4f02f394",
"name": "Section 1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1760,
16
],
"parameters": {
"color": 7,
"width": 892,
"height": 312,
"content": "## 1. Trigger & Data Processing\nWatches Google Sheets for pending scripts and cleans the text."
},
"typeVersion": 1
},
{
"id": "04080163-8397-4d96-8818-99d90eb157ba",
"name": "Section 2",
"type": "n8n-nodes-base.stickyNote",
"position": [
-800,
16
],
"parameters": {
"color": 7,
"width": 892,
"height": 312,
"content": "## 2. API Communication\nHandles HeyGen requests and polls for video generation status."
},
"typeVersion": 1
},
{
"id": "89fc0f7f-d86d-477f-8745-e14cec4de985",
"name": "Section 3",
"type": "n8n-nodes-base.stickyNote",
"position": [
176,
16
],
"parameters": {
"color": 7,
"width": 488,
"height": 520,
"content": "## 3. Sheet Update\nWrites the generated video URL back to the spreadsheet."
},
"typeVersion": 1
}
],
"connections": {
"If": {
"main": [
[
{
"node": "Wait",
"type": "main",
"index": 0
}
]
]
},
"Wait": {
"main": [
[
{
"node": "Video Status",
"type": "main",
"index": 0
}
]
]
},
"Has Script?": {
"main": [
[
{
"node": "Process One at a Time",
"type": "main",
"index": 0
}
]
]
},
"Video Status": {
"main": [
[
{
"node": "Is Complete?1",
"type": "main",
"index": 0
}
]
]
},
"Is Complete?1": {
"main": [
[
{
"node": "Update Sheet with Video1",
"type": "main",
"index": 0
}
],
[
{
"node": "Wait Before Retry1",
"type": "main",
"index": 0
}
]
]
},
"Generate Video": {
"main": [
[
{
"node": "If",
"type": "main",
"index": 0
}
]
]
},
"Sanitize Script": {
"main": [
[
{
"node": "Generate Video",
"type": "main",
"index": 0
}
]
]
},
"Wait Before Retry1": {
"main": [
[
{
"node": "Video Status",
"type": "main",
"index": 0
}
]
]
},
"Google Sheets Trigger": {
"main": [
[
{
"node": "Has Script?",
"type": "main",
"index": 0
}
]
]
},
"Process One at a Time": {
"main": [
[],
[
{
"node": "Sanitize Script",
"type": "main",
"index": 0
}
]
]
},
"Update Sheet with Video1": {
"main": [
[
{
"node": "Process One at a Time",
"type": "main",
"index": 0
}
]
]
}
}
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Automate HeyGen Video Generation from Google Sheets Effortlessly convert text scripts in Google Sheets into AI-generated videos using HeyGen.
Source: https://n8n.io/workflows/14804/ — 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 powerful no-code workflow automates plagiarism detection using Plagiarism Checker AI Powered. Users submit text through Google Sheets. The system checks for duplication using the API, sends a det
This n8n workflow automates outbound phone calls to new leads using VAPI, with built-in timezone detection to ensure you're only calling during business hours.
Julia. Uses googleSheetsTrigger, googleSheets, httpRequest. Event-driven trigger; 16 nodes.
This n8n template automatically enriches IP addresses with geolocation data and performs HTTP port scanning when new IPs are added to a Google Sheets document. Perfect for network monitoring, security
This n8n template demonstrates how to automatically validate email addresses from your Google Sheets using a reliable email verification API. Perfect for cleaning contact lists, validating leads, and