{
  "name": "Generate UGC product videos from Google Sheets with DALL·E, GPT-4 and Sora",
  "nodes": [
    {
      "id": "15ba86f1-e3d3-46cd-a1d7-0005287509d6",
      "name": "Error Trigger",
      "type": "n8n-nodes-base.errorTrigger",
      "position": [
        -2896,
        848
      ]
    },
    {
      "id": "c431d2a6-b0e7-4b21-81ef-b9ec1efe379a",
      "name": "Parse Error Details",
      "type": "n8n-nodes-base.code",
      "position": [
        -2672,
        848
      ]
    },
    {
      "id": "4746134f-3714-45e5-9cca-a5751b070dd8",
      "name": "Row Number Known?",
      "type": "n8n-nodes-base.if",
      "position": [
        -2448,
        848
      ]
    },
    {
      "id": "3b2456ed-3507-48a0-b4c5-b92d5f26e271",
      "name": "Update Sheet — Error",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -2224,
        752
      ]
    },
    {
      "id": "35d1f8da-c092-4eab-aa3d-980767a288ef",
      "name": "Log Error (Unknown Row)",
      "type": "n8n-nodes-base.code",
      "position": [
        -2224,
        944
      ]
    },
    {
      "id": "3f5dc41d-654e-4a6c-afe8-5bff56034a60",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2944,
        624
      ],
      "parameters": {
        "width": 920,
        "height": 536,
        "content": "## ERROR HANDLER WORKFLOW\nThis workflow is triggered when the main UGC pipeline fails.\nIt extracts the error details and row number, then updates\nthe Google Sheet with Status = \"Error\" and the error m"
      }
    },
    {
      "id": "14d935a8-8970-4289-9a6b-79922ea48d7d",
      "name": "Sticky Note — Complete1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -896,
        -80
      ],
      "parameters": {
        "width": 1248,
        "height": 492,
        "content": "## 5. GOOGLE DRIVE UPLOAD & SHEET UPDATE\nFetches the video binary from Sora API.\nUploads MP4 to Google Drive.\nSets file to public (anyone with link).\nBuilds shareable Drive URL.\nWrites Image URL + Vid"
      }
    },
    {
      "id": "91e74ed5-93b8-4060-b6b1-a55d20ed26d3",
      "name": "Sticky Note — Sora Poll Loop1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1840,
        -80
      ],
      "parameters": {
        "width": 916,
        "height": 492,
        "content": "## 4b. SORA POLLING LOOP\nPolls GET /v1/videos/{videoId} every 30s. Check Sora Status merges poll response with\ncarried product data from Extract Sora Job ID.\n\nIF node checks isDone === true:\n  TRUE  -"
      }
    },
    {
      "id": "028d4623-9249-49b1-ab7d-a87d5effba36",
      "name": "Sticky Note — Sora Async Polling1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2464,
        -80
      ],
      "parameters": {
        "width": 592,
        "height": 492,
        "content": "## 4. SORA VIDEO GENERATION (Async + Polling)\nWaits 60s for rate limiting, then POSTs to Sora API. Sora returns a queued job ID (not a video URL).\n\nExtracts the job ID, then enters a polling loop:\n  -"
      }
    },
    {
      "id": "41f09387-5c2b-46be-91e7-905f9d99b17f",
      "name": "Sticky Note — Vision & Script1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -3168,
        32
      ],
      "parameters": {
        "width": 680,
        "height": 376,
        "content": "## 3. VISION ANALYSIS & VIDEO SCRIPT\nGPT-4 Vision analyzes the generated image for mood, colors, composition. This enriches the video script with visual continuity. Script optimized for Sora's prompt "
      }
    },
    {
      "id": "a858e198-91f1-459e-a02c-dafff58d809e",
      "name": "Sticky Note — Image Gen1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -3824,
        32
      ],
      "parameters": {
        "width": 632,
        "height": 376,
        "content": "## 2. IMAGE GENERATION\n\nFor each pending product, a code node builds a detailed DALL·E 3 prompt with UGC aesthetic direction. The prompt is sent to the OpenAI API to generate an HD image, and the retu"
      }
    },
    {
      "id": "f3480891-ef64-4a0e-a223-980b307496e5",
      "name": "Sticky Note — Trigger1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -4704,
        32
      ],
      "parameters": {
        "width": 648,
        "height": 328,
        "content": "## Stage 1 — Trigger & data fetch. \n\nA schedule trigger fires on a set interval. It reads all rows from a Google Sheets \"Products\" tab, then a code node filters down to only rows where Status = \"Pendi"
      }
    },
    {
      "id": "b0db93d6-486b-4c91-8e65-357c07d58a32",
      "name": "Loop Complete1",
      "type": "n8n-nodes-base.noOp",
      "position": [
        512,
        176
      ]
    },
    {
      "id": "4a816411-f497-4d10-90fd-bef7e15792bd",
      "name": "Update Sheet — Done2",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        144,
        176
      ]
    },
    {
      "id": "4b2ef789-11da-4f36-aeda-9c8fb0b03c3f",
      "name": "Build Public Drive URL1",
      "type": "n8n-nodes-base.code",
      "position": [
        -176,
        176
      ]
    },
    {
      "id": "1b8ed01a-0222-4890-a4f5-49a26f8cf35b",
      "name": "Make File Public1",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -400,
        176
      ]
    },
    {
      "id": "e6da9b30-d9bb-47e7-99a4-64899060732a",
      "name": "Upload Video to Google Drive1",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        -624,
        176
      ]
    },
    {
      "id": "53d8ace4-c965-48f2-97fd-755cdef262c1",
      "name": "Fetch Sora Video Content1",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -848,
        176
      ]
    },
    {
      "id": "b541ed0b-1437-4146-a64e-7cee7436a0a8",
      "name": "Video Ready?1",
      "type": "n8n-nodes-base.if",
      "position": [
        -1072,
        176
      ]
    },
    {
      "id": "77c8f941-9d0e-49d9-b54d-a57dcc83d712",
      "name": "Check Sora Status1",
      "type": "n8n-nodes-base.code",
      "position": [
        -1296,
        112
      ]
    },
    {
      "id": "4f0a27cf-59c0-4e20-9ddc-6494695133af",
      "name": "Poll Sora Status1",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -1520,
        112
      ]
    },
    {
      "id": "7e2196bd-3f07-46eb-a2d5-58d9c2429712",
      "name": "Wait 30 Seconds1",
      "type": "n8n-nodes-base.wait",
      "position": [
        -1744,
        176
      ]
    },
    {
      "id": "a264934c-b7d4-4b9f-aa12-c08c8ccd46d8",
      "name": "Extract Sora Job ID1",
      "type": "n8n-nodes-base.code",
      "position": [
        -1968,
        176
      ]
    },
    {
      "id": "5438f0c9-dd1c-4e1d-97c4-37fdb13446c1",
      "name": "Sora Generate Video1",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -2192,
        176
      ]
    },
    {
      "id": "1b949498-28e8-4be0-b6d8-bc7af87fc8a2",
      "name": "Wait for Sora Rate Limit1",
      "type": "n8n-nodes-base.wait",
      "position": [
        -2416,
        176
      ]
    },
    {
      "id": "339acd53-88b0-412b-9d3f-e3df4415d62c",
      "name": "Video Script Builder1",
      "type": "n8n-nodes-base.code",
      "position": [
        -2640,
        176
      ]
    },
    {
      "id": "718f66b9-df1d-4ffa-98c4-d8da3135e29c",
      "name": "Parse Vision Analysis1",
      "type": "n8n-nodes-base.code",
      "position": [
        -2864,
        176
      ]
    },
    {
      "id": "76b6c96b-ec5d-4a19-92f9-4f2616353a45",
      "name": "GPT-4 Vision Analysis1",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -3088,
        176
      ]
    },
    {
      "id": "4a84b896-8b39-45a6-aee5-f42ab91e5269",
      "name": "Extract DALL-E URL1",
      "type": "n8n-nodes-base.code",
      "position": [
        -3312,
        176
      ]
    },
    {
      "id": "168cbb8e-8baa-4e77-8101-4aaa8ba88cfc",
      "name": "DALL-E 3 Generate Image1",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -3536,
        176
      ]
    },
    {
      "id": "d98ee411-296b-40fb-b480-8463f1902ba7",
      "name": "AI Prompt Builder1",
      "type": "n8n-nodes-base.code",
      "position": [
        -3760,
        176
      ]
    },
    {
      "id": "708a0f76-2a80-44dc-aeb1-43f19074864b",
      "name": "Loop Over Items1",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        -3984,
        176
      ]
    },
    {
      "id": "ae1ccc94-f9d6-4144-b940-2fc5ede0b2bd",
      "name": "Filter Pending Rows1",
      "type": "n8n-nodes-base.code",
      "position": [
        -4208,
        176
      ]
    },
    {
      "id": "ee9d2866-355d-4c73-aaf3-bf46c09b365e",
      "name": "Read Product Sheet1",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -4432,
        176
      ]
    },
    {
      "id": "5969cd10-3860-488e-a9b1-8bf89383bd73",
      "name": "Schedule Trigger1",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -4656,
        176
      ]
    },
    {
      "id": "4b0a9306-c78e-4f47-99ce-e11b7650c14b",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -5488,
        -96
      ],
      "parameters": {
        "width": 496,
        "height": 352,
        "content": "## Workflow overview\n\nThis is an n8n automation workflow that turns product listings in a Google Sheet into UGC-style videos, fully hands-off.\n\nIt runs on a schedule, picks up any row marked \"Pending\""
      }
    },
    {
      "id": "5178b44c-46aa-47a8-88f5-a5c9a70ee9ed",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -5488,
        304
      ],
      "parameters": {
        "width": 496,
        "height": 560,
        "content": "## Setup instructions\n\nBefore running this workflow, configure the following:\n\n1. **Google Sheets OAuth** — Connect your Google account so the workflow can read product rows and write back status upda"
      }
    }
  ],
  "connections": {
    "Error Trigger": {
      "main": [
        [
          {
            "node": "Parse Error Details",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Video Ready?1": {
      "main": [
        [
          {
            "node": "Fetch Sora Video Content1",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Wait 30 Seconds1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Over Items1": {
      "main": [
        [
          {
            "node": "Loop Complete1",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "AI Prompt Builder1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait 30 Seconds1": {
      "main": [
        [
          {
            "node": "Poll Sora Status1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Make File Public1": {
      "main": [
        [
          {
            "node": "Build Public Drive URL1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Poll Sora Status1": {
      "main": [
        [
          {
            "node": "Check Sora Status1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Row Number Known?": {
      "main": [
        [
          {
            "node": "Update Sheet — Error",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Log Error (Unknown Row)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Schedule Trigger1": {
      "main": [
        [
          {
            "node": "Read Product Sheet1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Prompt Builder1": {
      "main": [
        [
          {
            "node": "DALL-E 3 Generate Image1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Sora Status1": {
      "main": [
        [
          {
            "node": "Video Ready?1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract DALL-E URL1": {
      "main": [
        [
          {
            "node": "GPT-4 Vision Analysis1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Error Details": {
      "main": [
        [
          {
            "node": "Row Number Known?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Read Product Sheet1": {
      "main": [
        [
          {
            "node": "Filter Pending Rows1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract Sora Job ID1": {
      "main": [
        [
          {
            "node": "Wait 30 Seconds1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter Pending Rows1": {
      "main": [
        [
          {
            "node": "Loop Over Items1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Sora Generate Video1": {
      "main": [
        [
          {
            "node": "Extract Sora Job ID1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Video Script Builder1": {
      "main": [
        [
          {
            "node": "Wait for Sora Rate Limit1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "GPT-4 Vision Analysis1": {
      "main": [
        [
          {
            "node": "Parse Vision Analysis1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Vision Analysis1": {
      "main": [
        [
          {
            "node": "Video Script Builder1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Update Sheet — Done2": {
      "main": [
        [
          {
            "node": "Loop Over Items1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Public Drive URL1": {
      "main": [
        [
          {
            "node": "Update Sheet — Done2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "DALL-E 3 Generate Image1": {
      "main": [
        [
          {
            "node": "Extract DALL-E URL1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Sora Video Content1": {
      "main": [
        [
          {
            "node": "Upload Video to Google Drive1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait for Sora Rate Limit1": {
      "main": [
        [
          {
            "node": "Sora Generate Video1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Upload Video to Google Drive1": {
      "main": [
        [
          {
            "node": "Make File Public1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}