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": "Veo 3.1 \u2014 Finance Tip (Video-Only, GPT-4.1 \u2192 Veo Preview)",
"nodes": [
{
"parameters": {},
"id": "ManualTrigger",
"name": "Manual Trigger",
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [
-560,
0
]
},
{
"parameters": {
"functionCode": "const runId = Date.now().toString(36) + '-' + Math.random().toString(36).slice(2,8);\nreturn [{ json: { runId } }];"
},
"id": "MakeRunId",
"name": "Make runId",
"type": "n8n-nodes-base.function",
"typeVersion": 2,
"position": [
-380,
0
]
},
{
"parameters": {
"keepOnlySet": true,
"values": {
"string": [
{
"name": "topic",
"value": "One quick way to start a $1K emergency fund"
},
{
"name": "durationSeconds",
"value": "20"
},
{
"name": "aspectRatio",
"value": "9:16"
},
{
"name": "negativePrompt",
"value": "nudity, explicit, low quality, glitch, distorted, disfigured"
}
]
}
},
"id": "Config",
"name": "Config",
"type": "n8n-nodes-base.set",
"typeVersion": 2,
"position": [
-200,
0
]
},
{
"parameters": {
"model": "gpt-4.1",
"messages": [
{
"type": "system",
"text": "You write concise 20-second finance scripts (\u224845\u201360 words) for vertical videos. Tone: soft, confident, warm, non-preachy, actionable. No emojis. No tickers, no guarantees, no solicitation. Return only the spoken script\u2014no labels."
},
{
"type": "user",
"text": "Topic: {{$json[\"/previousNode:Config\"].topic}}\nAudience: beginners under money stress\nConstraint: 45\u201360 words max\nPersona: calm, intimate, reassuring feminine voice\nEnd with 1 gentle CTA to follow for daily tips"
}
],
"responseType": "text"
},
"id": "OpenAI_Script",
"name": "Script (OpenAI GPT-4.1)",
"type": "n8n-nodes-chat.openAiAssistant",
"typeVersion": 1,
"position": [
40,
0
]
},
{
"parameters": {
"functionCode": "const text = items[0].json?.text || items[0].json?.data?.[0]?.content || '';\nconst cfg = $json[\"/previousNode:Config\"];\nconst runId = $json[\"/previousNode:Make runId\"].runId;\nconst prompt = `Soft, photorealistic, vertical ${cfg.aspectRatio} video (~${cfg.durationSeconds}s) of an attractive adult woman delivering a calm, intimate personal-finance tip in a soft whisper. Professional, tasteful; avoid sexualization. Subtle head/eye movement, natural micro-expressions. Clean neutral background, shallow depth of field, soft key light.\n\nVOICEOVER (use exactly this text, paced to ${cfg.durationSeconds}s):\\n${text}\n\nCompliance: educational only, no guarantees, no securities recommendations.\nRunId:${runId}`;\nreturn [{ json: { script: text, prompt, aspectRatio: cfg.aspectRatio, durationSeconds: Number(cfg.durationSeconds), negativePrompt: cfg.negativePrompt } }];"
},
"id": "BuildPrompt",
"name": "Build Veo Prompt",
"type": "n8n-nodes-base.function",
"typeVersion": 2,
"position": [
260,
0
]
},
{
"parameters": {
"url": "https://generativelanguage.googleapis.com/v1beta/models/veo-3.1-generate-preview:predictLongRunning",
"method": "POST",
"sendBody": true,
"jsonParameters": true,
"responseFormat": "json",
"authentication": "none",
"headerParametersJson": "={\"x-goog-api-key\": $env.GEMINI_API_KEY, \"Content-Type\": \"application/json\"}",
"bodyParametersJson": "={\n \"instances\": [\n {\n \"prompt\": $json.prompt,\n \"aspectRatio\": $json.aspectRatio,\n \"durationSeconds\": $json.durationSeconds\n }\n ],\n \"parameters\": {\n \"preset\": \"fast\",\n \"negativePrompt\": $json.negativePrompt\n }\n}"
},
"id": "VeoCreate",
"name": "Veo 3.1 \u2014 Create Job (Preview)",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4,
"position": [
520,
0
]
},
{
"parameters": {
"keepOnlySet": true,
"values": {
"string": [
{
"name": "operationName",
"value": "={{$json[\"name\"]}}"
}
]
}
},
"id": "StoreOp",
"name": "Store Operation",
"type": "n8n-nodes-base.set",
"typeVersion": 2,
"position": [
720,
0
]
},
{
"parameters": {
"amount": 8,
"unit": "seconds"
},
"id": "Wait8s",
"name": "Wait 8s",
"type": "n8n-nodes-base.wait",
"typeVersion": 1,
"position": [
720,
160
]
},
{
"parameters": {
"url": "={{\"https://generativelanguage.googleapis.com/v1beta/\" + $json[\"operationName\"]}}",
"method": "GET",
"responseFormat": "json",
"authentication": "none",
"headerParametersJson": "={\"x-goog-api-key\": $env.GEMINI_API_KEY}"
},
"id": "PollOp",
"name": "Poll Operation",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4,
"position": [
920,
60
]
},
{
"parameters": {
"conditions": {
"collection": [
{
"type": "boolean",
"value1": "={{$json.done === true}}"
}
]
}
},
"id": "IfDone",
"name": "Done?",
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [
1120,
60
]
},
{
"parameters": {
"amount": 5,
"unit": "seconds"
},
"id": "WaitLoop",
"name": "Wait (loop)",
"type": "n8n-nodes-base.wait",
"typeVersion": 1,
"position": [
1120,
-80
]
},
{
"parameters": {
"functionCode": "return items;"
},
"id": "LoopBack",
"name": "Loop",
"type": "n8n-nodes-base.function",
"typeVersion": 2,
"position": [
1300,
-80
]
},
{
"parameters": {
"functionCode": "const op = items[0].json;\nconst url = op?.response?.generateVideoResponse?.generatedSamples?.[0]?.video?.uri;\nif (!url) throw new Error('Operation complete but no video URL found.');\nreturn [{ json: { videoUrl: url } }];"
},
"id": "ExtractUrl",
"name": "Extract Video URL",
"type": "n8n-nodes-base.function",
"typeVersion": 2,
"position": [
1320,
60
]
},
{
"parameters": {
"message": "\u2705 Veo render complete: {{$json[\"/previousNode:Extract Video URL\"].videoUrl}}",
"raiseMessage": true
},
"id": "Success",
"name": "Success",
"type": "n8n-nodes-base.noOp",
"typeVersion": 1,
"position": [
1520,
60
]
}
],
"connections": {
"Manual Trigger": {
"main": [
[
{
"node": "Make runId",
"type": "main",
"index": 0
}
]
]
},
"Make runId": {
"main": [
[
{
"node": "Config",
"type": "main",
"index": 0
}
]
]
},
"Config": {
"main": [
[
{
"node": "Script (OpenAI GPT-4.1)",
"type": "main",
"index": 0
}
]
]
},
"Script (OpenAI GPT-4.1)": {
"main": [
[
{
"node": "Build Veo Prompt",
"type": "main",
"index": 0
}
]
]
},
"Build Veo Prompt": {
"main": [
[
{
"node": "Veo 3.1 \u2014 Create Job (Preview)",
"type": "main",
"index": 0
}
]
]
},
"Veo 3.1 \u2014 Create Job (Preview)": {
"main": [
[
{
"node": "Store Operation",
"type": "main",
"index": 0
}
]
]
},
"Store Operation": {
"main": [
[
{
"node": "Poll Operation",
"type": "main",
"index": 0
}
],
[
{
"node": "Wait 8s",
"type": "main",
"index": 0
}
]
]
},
"Wait 8s": {
"main": [
[
{
"node": "Poll Operation",
"type": "main",
"index": 0
}
]
]
},
"Poll Operation": {
"main": [
[
{
"node": "Done?",
"type": "main",
"index": 0
}
]
]
},
"Done?": {
"main": [
[
{
"node": "Extract Video URL",
"type": "main",
"index": 0
}
],
[
{
"node": "Wait (loop)",
"type": "main",
"index": 0
}
]
]
},
"Wait (loop)": {
"main": [
[
{
"node": "Loop",
"type": "main",
"index": 0
}
]
]
},
"Loop": {
"main": [
[
{
"node": "Poll Operation",
"type": "main",
"index": 0
}
]
]
},
"Extract Video URL": {
"main": [
[
{
"node": "Success",
"type": "main",
"index": 0
}
]
]
}
},
"settings": {
"executionOrder": "v1"
},
"meta": {
"version": "1.114.x",
"notes": "Phase 1: video-only. Uses n8n built-in OpenAI credential (select in node UI). AI Studio key in env as GEMINI_API_KEY."
}
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Veo 3.1 — Finance Tip (Video-Only, GPT-4.1 → Veo Preview). Uses n8n-nodes-chat, httpRequest. Event-driven trigger; 14 nodes.
Source: https://gist.github.com/allanzilber-boop/43b7d99ed8116f0d4c0ef27c24d702a7 — 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 automates SEO analysis by comparing your website with a competitor’s site. It reads input URLs from Google Sheets, scrapes structured SEO data from both sites, and expands into important
Spot Workplace Discrimination Patterns with AI. Uses manualTrigger, lmChatOpenAi, httpRequest, html. Event-driven trigger; 38 nodes.
Spot Workplace Discrimination Patterns with AI. Uses manualTrigger, lmChatOpenAi, httpRequest, html. Event-driven trigger; 38 nodes.
This template can be used to find the content gaps in your competitors' discourse: identifying the topics they are not yet connecting and giving you an opportunity to fill in this gap with your conten
OpenAI-model-examples. Uses manualTrigger, openAi, httpRequest, stickyNote. Event-driven trigger; 27 nodes.