{
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "nodes": [
    {
      "id": "3b342194-a69b-4610-b847-37a9959a2a2c",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2704,
        -512
      ],
      "parameters": {
        "color": 6,
        "width": 540,
        "height": 466,
        "content": "## \u2744\ufe0f Frozen ASMR Video Creator\n\nCreate \"frozen\" product videos automatically and post them to social media. No coding required.\n\n### How it works\n1. **Sheet:** Finds a new product image in your Google Sheet.\n2. **Ice Effect:** Uses Gemini AI to freeze the image.\n3. **Video:** Uses Veo3 to animate the image into a 10s ASMR video.\n4. **Captions:** GPT-4o writes the text for you.\n5. **Publish:** Posts to YouTube, TikTok, Instagram, and Pinterest.\n\n### Setup steps\n1. **Get Keys:** You need API keys for Gemini, Kie.ai, ImgBB, OpenAI, and upload-post.com.\n2. **Prepare Sheet:** Make a Google Sheet with columns: `topic`, `image_url`, `status`.\n3. **Connect:** Double-click the YouTube and Telegram nodes to connect your accounts.\n4. **Config:** Press `Ctrl+F`, search for \"YOUR_\", and paste your real API keys."
      },
      "typeVersion": 1
    },
    {
      "id": "a12b39b7-5a1c-4b60-82ab-6ae2785d16e0",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2704,
        -16
      ],
      "parameters": {
        "color": 7,
        "width": 856,
        "height": 220,
        "content": "## 1. Get Data\nChecks your Google Sheet for new rows. If the row is clean, it starts the process."
      },
      "typeVersion": 1
    },
    {
      "id": "6b349dad-e207-466e-98ce-d3dd20821a0f",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1824,
        -16
      ],
      "parameters": {
        "color": 7,
        "width": 616,
        "height": 220,
        "content": "## 2. Freeze Image\nSends the photo to Gemini AI to add a realistic ice and frost effect."
      },
      "typeVersion": 1
    },
    {
      "id": "03d015f2-0e2e-4f62-a760-139feef0af3f",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2704,
        224
      ],
      "parameters": {
        "color": 7,
        "width": 1500,
        "height": 256,
        "content": "## 3. Make Video\nSends the frozen image to Veo3. It waits automatically until the video is fully rendered and ready to download."
      },
      "typeVersion": 1
    },
    {
      "id": "dde5afce-a0aa-4deb-9676-b7854cfa8090",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1184,
        -208
      ],
      "parameters": {
        "color": 7,
        "width": 1784,
        "height": 684,
        "content": "## 4. Write & Post\nGPT-4o writes descriptions for each app. Then, the workflow uploads the video to all 4 platforms at once."
      },
      "typeVersion": 1
    },
    {
      "id": "e238b484-244f-4a29-8466-d70d5d0f66f7",
      "name": "Generate Video (Veo3)",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -1984,
        304
      ],
      "parameters": {
        "url": "https://api.kie.ai/api/v1/veo/generate",
        "method": "POST",
        "options": {
          "timeout": 60000
        },
        "jsonBody": "={\n  \"prompt\": \"{{ $json.video_prompt }}\",\n  \"model\": \"veo3_fast\",\n  \"aspectRatio\": \"9:16\",\n  \"imageUrls\": [\"{{ $json.image_url }}\"]\n}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "Bearer YOUR_TOKEN_HERE"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "4ef930ef-bfb4-4869-b339-24a8d519ca6d",
      "name": "Wait 30s",
      "type": "n8n-nodes-base.wait",
      "position": [
        -1760,
        304
      ],
      "parameters": {
        "amount": 30
      },
      "typeVersion": 1.1
    },
    {
      "id": "5d12b5e2-7a16-47ba-841a-a59d8745f45a",
      "name": "Check Video Status",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -1552,
        304
      ],
      "parameters": {
        "url": "https://api.kie.ai/api/v1/veo/record-info",
        "options": {},
        "sendQuery": true,
        "sendHeaders": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "taskId",
              "value": "={{ $('Generate Video (Veo3)').item.json.data.taskId }}"
            }
          ]
        },
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "Bearer YOUR_TOKEN_HERE"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "7d679fbe-8533-400e-8933-f3c5663c24ea",
      "name": "Ready?",
      "type": "n8n-nodes-base.if",
      "position": [
        -1360,
        304
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "4732f0de-79aa-4406-86bb-7861e6753986",
              "operator": {
                "type": "number",
                "operation": "equals"
              },
              "leftValue": "={{ $json.data.successFlag }}",
              "rightValue": 1
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "f39d5b1f-469e-4466-b702-365ef2252d33",
      "name": "Extract Image",
      "type": "n8n-nodes-base.code",
      "position": [
        -2656,
        304
      ],
      "parameters": {
        "jsCode": "const response = $json;\n\nlet base64Image;\n\nif (response.candidates && response.candidates[0]?.content?.parts) {\n  const parts = response.candidates[0].content.parts;\n  for (const part of parts) {\n    if (part.inlineData?.data) {\n      base64Image = part.inlineData.data;\n      break;\n    }\n  }\n}\n\nif (!base64Image && response.predictions && response.predictions[0]) {\n  base64Image = response.predictions[0].bytesBase64Encoded;\n}\n\nif (!base64Image) {\n  throw new Error('No image found in response: ' + JSON.stringify(Object.keys(response)));\n}\n\nreturn [{\n  json: {\n    image_base64: base64Image,\n    topic: $('Validate Input2').item.json.topic,\n    scent_name: $('Validate Input2').item.json.scent_name,\n    brand_name: $('Validate Input2').item.json.brand_name\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "268a24d3-a604-4864-8deb-3eed59244798",
      "name": "Upload to ImgBB",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -2432,
        304
      ],
      "parameters": {
        "url": "https://api.imgbb.com/1/upload?key=YOUR_TOKEN_HERE",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "contentType": "form-urlencoded",
        "bodyParameters": {
          "parameters": [
            {
              "name": "image",
              "value": "={{ $json.image_base64 }}"
            }
          ]
        }
      },
      "typeVersion": 4.3
    },
    {
      "id": "bc309102-4d9a-4f93-9829-eaf3988bce25",
      "name": "Build Video Prompt",
      "type": "n8n-nodes-base.code",
      "position": [
        -2208,
        304
      ],
      "parameters": {
        "jsCode": "const imageUrl = $json.data.display_url;\nconst scent = String($('Validate Input2').item.json.scent_name || '').trim();\nconst brand = String($('Validate Input2').item.json.brand_name || '').trim();\n\nconst videoPrompt = [\n  \"Vertical 9:16 premium ASMR video. Duration 10-12s. Hyper-realistic macro.\",\n  \"\",\n  \"ABSOLUTE RESTRICTIONS:\",\n  \"No text, no letters, no words, no numbers.\",\n  \"No captions, no subtitles, no watermarks, no logos added by the model.\",\n  \"No sharp objects. No blades. No knives. No cutting tools.\",\n  \"Tool must remain the SAME SHAPE in every frame.\",\n  \"\",\n  \"TOOL DEFINITION (IMPORTANT):\",\n  \"A blunt, rounded metal scraper with a wide oval tip.\",\n  \"Matte steel finish. No sharp edge. No pointed geometry.\",\n  \"The tool NEVER changes form, angle, or sharpness.\",\n  \"\",\n  \"STYLE TARGET:\",\n  \"Luxury frozen packshot, but physically aggressive ice texture.\",\n  \"Dark bluish-grey studio background. Cold stone matte floor.\",\n  \"Dense sugar frost. Thick brittle rime ice. Frost looks fragile and crack-prone.\",\n  \"\",\n  \"HOOK (0.0-1.2s):\",\n  \"Frozen perfume bottle is already resting on the icy stone surface.\",\n  \"Absolute stillness. No movement.\",\n  \"Extreme macro on brittle frost texture.\",\n  \"Silence for tension.\",\n  \"\",\n  \"TENSION SPIKE (1.2-2.2s):\",\n  \"Blunt metal scraper taps the frost ONCE.\",\n  \"Hard, dry snap.\",\n  \"Micro fractures spider-web through the frost layer only.\",\n  \"Tiny ice grains fall and bounce.\",\n  \"\",\n  \"CRUNCH PAYOFF (2.2-8.5s):\",\n  \"Scraper presses down with visible resistance.\",\n  \"Frost does NOT glide smoothly \u2014 it fractures, snaps, and breaks.\",\n  \"Each pass produces sharp, brittle ice crack sounds.\",\n  \"Chunks break off unevenly.\",\n  \"Glass underneath is revealed in jagged edges, not smooth lines.\",\n  \"\",\n  \"FINAL BEAT (8.5-10.5s):\",\n  \"Last brittle frost chunk snaps free with a loud crack.\",\n  \"Bottle remains fully intact.\",\n  \"Loose ice fragments scatter and slide on stone.\",\n  \"\",\n  \"CAMERA & LIGHT:\",\n  \"Ultra macro lens. Shallow depth of field.\",\n  \"Hard highlights on ice crystals.\",\n  \"Cold, sharp reflections. No softness.\",\n  \"\",\n  \"AUDIO ONLY (CRITICAL):\",\n  \"Dry ice snap. Sharp crack. Brittle fracture.\",\n  \"No smooth scraping sounds.\",\n  \"No music. No voice.\"\n].join(\" \");\n\nreturn [{\n  json: {\n    video_prompt: videoPrompt,\n    image_url: imageUrl,\n    topic: $('Validate Input2').item.json.topic,\n    scent_name: scent,\n    brand_name: brand\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "22beb01b-f721-4ed8-80d5-86695ccc9e97",
      "name": "Download Product Image",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -1760,
        80
      ],
      "parameters": {
        "url": "={{ $('Validate Input2').item.json.reference_url }}",
        "options": {
          "response": {
            "response": {
              "responseFormat": "file"
            }
          }
        }
      },
      "typeVersion": 4.3
    },
    {
      "id": "6ee069bd-0a31-4954-9bbb-b2c1ce735a88",
      "name": "Build Image Prompt",
      "type": "n8n-nodes-base.code",
      "position": [
        -1568,
        80
      ],
      "parameters": {
        "jsCode": "const item = $input.first();\n\nconst bin = item?.binary?.data || item?.binary?.file || item?.binary?.image;\n\nif (!bin?.data || bin.data.length < 50) {\n  throw new Error(\"Reference image binary missing or empty\");\n}\n\nconst imageBase64 = String(bin.data).replace(/^data:.*;base64,/, \"\");\nconst mimeType = bin.mimeType || \"image/jpeg\";\n\nconst scent = String($(\"Validate Input2\").item.json.scent_name || \"\").trim();\nconst brand = String($(\"Validate Input2\").item.json.brand_name || \"\").trim();\nconst topic = String($(\"Validate Input2\").item.json.topic || \"\").trim();\n\nconst safe = (s) => String(s || \"\").replace(/\\r?\\n|\\r/g, \" \").replace(/\\s+/g, \" \").trim();\n\nconst brandSafe = safe(brand);\nconst scentSafe = safe(scent);\n\nconst imagePrompt = safe(`\nIDENTITY LOCK:\n- Preserve EXACT bottle silhouette, proportions, cap shape, nozzle placement, edges/corners, and all engravings from the reference.\n- Do NOT redesign the bottle. Do NOT change geometry. Do NOT change the label/engraved layout.\n\nTEXT LOCK:\n- Do NOT redraw, regenerate, or modify any text, logo, or typography.\n- Keep the exact original text from the reference. If frost covers text, let it be partially obscured/blurred \u2014 never altered.\n\nSTYLE TRANSFORM ONLY:\n- Apply realistic frozen treatment on top of the SAME bottle: dense micro-frost crystals across the bottle, thicker rime on edges and cap top, frozen condensation streaks.\n- Background and lighting can change.\n\nSCENE:\n- Dark bluish-grey studio background, cold stone matte surface with scattered ice crystals.\n- Soft diffused key light + subtle rim light, crisp highlights, realistic reflections.\n- Centered front view, no props, vertical 9:16.\n\nProduct: ${brandSafe} ${scentSafe}.\n`);\n\nconst requestBody = {\n  contents: [\n    {\n      parts: [\n        { inline_data: { mime_type: mimeType, data: imageBase64 } },\n        { text: imagePrompt }\n      ]\n    }\n  ],\n  generationConfig: {\n    responseModalities: [\"IMAGE\"],\n    imageConfig: { aspectRatio: \"9:16\" }\n  }\n};\n\nreturn [{ json: { request_body: requestBody, brand_name: brandSafe, scent_name: scentSafe, topic } }];"
      },
      "typeVersion": 2
    },
    {
      "id": "33dd4e8d-f94a-48a9-ba44-966cd3efc214",
      "name": "Gemini (Frozen Image)",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -1360,
        80
      ],
      "parameters": {
        "url": "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash-preview-05-20:generateContent",
        "method": "POST",
        "options": {},
        "jsonBody": "={{ $json.request_body }}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "headerParameters": {
          "parameters": [
            {
              "name": "x-goog-api-key",
              "value": "YOUR_GOOGLE_AI_API_KEY"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        }
      },
      "typeVersion": 4.3
    },
    {
      "id": "2152983f-1a9c-4034-ae22-aee4bc8bc460",
      "name": "Get Sheet Data",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -2432,
        80
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "YOUR_GOOGLE_SHEET_ID"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "d003c958-32ac-4fea-9bf7-70ece4fb7df3",
      "name": "GPT-4o (Captions)",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "position": [
        -1152,
        80
      ],
      "parameters": {
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4o"
        },
        "options": {
          "temperature": 0.9
        },
        "messages": {
          "values": [
            {
              "role": "system",
              "content": "You write hypnotic micro-text for luxury ASMR short videos.\n\nWhat the viewer sees:\nA real luxury perfume bottle frozen solid for days.\nMacro close-ups.\nIce cracking.\nFrost slowly peeling.\nCold glass textures.\nNo talking. No hands. Just the object.\nFeels intimate, quiet, slightly forbidden.\nThe kind of video people replay without noticing.\n\nYour job:\nWrite text that makes people WATCH AGAIN.\n\nStyle rules:\n- Extremely short.\n- Simple language.\n- Observational, not promotional.\n- Slightly mysterious.\n- Sounds like a human noticing something oddly addictive.\n- No hype, no emojis unless absolutely necessary.\n- No calls to action like \"watch till the end\".\n\nHard bans (never use):\nknife, blade, cut, slice, chop, stab, weapon, blood, gore, kill, murder, razor\n\nReturn JSON ONLY. No markdown. No explanations.\n\nExact output format:\n{\n  \"youtube_title\": \"\",\n  \"youtube_description\": \"\",\n  \"tiktok_caption\": \"\",\n  \"instagram_caption\": \"\",\n  \"pinterest_title\": \"\",\n  \"pinterest_description\": \"\"\n}"
            },
            {
              "content": "TOPIC: '{{ $('Build Video Prompt').item.json.topic }}'\n\nVideo: luxury perfume bottle frozen for 72 hours. Frost cracks, ice snaps, crunchy ASMR textures, satisfying close-up.\nDo NOT use any banned words. Make it irresistible but natural.\nReturn JSON only."
            }
          ]
        }
      },
      "typeVersion": 1.4
    },
    {
      "id": "04baf874-3359-4833-8d1a-15baec76aad4",
      "name": "Download Video",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -608,
        80
      ],
      "parameters": {
        "url": "={{ $json.video_url }}",
        "options": {
          "response": {
            "response": {
              "responseFormat": "file"
            }
          }
        }
      },
      "typeVersion": 4.3
    },
    {
      "id": "a8807e21-9e81-45bd-9df6-3693803c3a92",
      "name": "YouTube",
      "type": "n8n-nodes-base.youTube",
      "position": [
        -288,
        16
      ],
      "parameters": {
        "title": "={{ $('Prepare Upload2').item.json.youtube_title }}",
        "options": {
          "description": "={{ $('Prepare Upload2').item.json.youtube_description }}"
        },
        "resource": "video",
        "operation": "upload",
        "categoryId": "24",
        "regionCode": "US"
      },
      "typeVersion": 1
    },
    {
      "id": "61820f63-82d7-45db-a19f-b0d0c38f8c5a",
      "name": "Update Sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        240,
        80
      ],
      "parameters": {
        "columns": {
          "value": {
            "topic": "={{ $('Validate Input2').item.json.topic }}",
            "status": "uploaded",
            "video_id": "={{ $json.uploadId }}",
            "row_number": 0,
            "youtube_url": "=https://youtube.com/shorts/{{ $json.uploadId }}"
          },
          "schema": [
            {
              "id": "topic",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "topic",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "image_url",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "image_url",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "status",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "video_id",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "video_id",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "youtube_url",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "youtube_url",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "row_number",
              "type": "number",
              "display": true,
              "required": false,
              "displayName": "row_number",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "topic"
          ]
        },
        "options": {},
        "operation": "update",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "YOUR_GOOGLE_SHEET_ID"
        }
      },
      "typeVersion": 4
    },
    {
      "id": "9fb8a069-a9c4-4d54-846e-2587b3d3319c",
      "name": "Pinterest",
      "type": "n8n-nodes-base.httpRequest",
      "onError": "continueRegularOutput",
      "position": [
        -288,
        176
      ],
      "parameters": {
        "url": "https://api.upload-post.com/api/upload",
        "method": "POST",
        "options": {
          "timeout": 120000
        },
        "sendBody": true,
        "contentType": "multipart-form-data",
        "sendHeaders": true,
        "bodyParameters": {
          "parameters": [
            {
              "name": "title",
              "value": "={{ $('Prepare Upload2').item.json.pinterest_title }}"
            },
            {
              "name": "description",
              "value": "={{ $('Prepare Upload2').item.json.pinterest_description }}"
            },
            {
              "name": "user",
              "value": "YOUR_PINTEREST_USERNAME"
            },
            {
              "name": "platform[]",
              "value": "pinterest"
            },
            {
              "name": "mediaUrl",
              "value": "={{ $('Prepare Upload2').item.json.video_url }}"
            },
            {
              "name": "boardId",
              "value": "YOUR_PINTEREST_BOARD_ID"
            }
          ]
        },
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "Apikey YOUR_UPLOAD_POST_API_KEY"
            }
          ]
        }
      },
      "typeVersion": 4.3
    },
    {
      "id": "5b92a81d-ea96-4209-9ba6-fb0756a0119d",
      "name": "TikTok",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -288,
        -144
      ],
      "parameters": {
        "url": "https://api.upload-post.com/api/upload",
        "method": "POST",
        "options": {
          "timeout": 120000
        },
        "sendBody": true,
        "contentType": "multipart-form-data",
        "sendHeaders": true,
        "bodyParameters": {
          "parameters": [
            {
              "name": "title",
              "value": "={{ $('Prepare Upload2').item.json.youtube_title }}"
            },
            {
              "name": "description",
              "value": "={{ $('Prepare Upload2').item.json.tiktok_caption }}"
            },
            {
              "name": "caption",
              "value": "={{ $('Prepare Upload2').item.json.tiktok_caption }}"
            },
            {
              "name": "user",
              "value": "YOUR_TIKTOK_USERNAME"
            },
            {
              "name": "platform[]",
              "value": "tiktok"
            },
            {
              "name": "mediaUrl",
              "value": "={{ $('Prepare Upload2').item.json.video_url }}"
            }
          ]
        },
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "Apikey YOUR_UPLOAD_POST_API_KEY"
            }
          ]
        }
      },
      "typeVersion": 4.3
    },
    {
      "id": "719350bd-123b-40a2-adc3-dc2bcc11be99",
      "name": "Instagram",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -288,
        336
      ],
      "parameters": {
        "url": "https://api.upload-post.com/api/upload",
        "method": "POST",
        "options": {
          "timeout": 120000
        },
        "sendBody": true,
        "contentType": "multipart-form-data",
        "sendHeaders": true,
        "bodyParameters": {
          "parameters": [
            {
              "name": "title",
              "value": "={{ $('Prepare Upload2').item.json.youtube_title }}"
            },
            {
              "name": "description",
              "value": "={{ $('Prepare Upload2').item.json.instagram_caption }}"
            },
            {
              "name": "caption",
              "value": "={{ $('Prepare Upload2').item.json.instagram_caption }}"
            },
            {
              "name": "user",
              "value": "YOUR_INSTAGRAM_USERNAME"
            },
            {
              "name": "platform[]",
              "value": "instagram"
            },
            {
              "name": "mediaUrl",
              "value": "={{ $('Prepare Upload2').item.json.video_url }}"
            }
          ]
        },
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "Apikey YOUR_UPLOAD_POST_API_KEY"
            }
          ]
        }
      },
      "typeVersion": 4.3
    },
    {
      "id": "dff1c271-f829-4103-9b8f-92701e64cc84",
      "name": "Wait & Retry2",
      "type": "n8n-nodes-base.wait",
      "position": [
        -1136,
        304
      ],
      "parameters": {
        "amount": 30
      },
      "typeVersion": 1.1
    },
    {
      "id": "1a750101-445b-4d82-8c2c-8d5f0a7d75df",
      "name": "Validate Input2",
      "type": "n8n-nodes-base.code",
      "position": [
        -2208,
        80
      ],
      "parameters": {
        "jsCode": "const items = $input.all();\n\nconst valid = items.find(item => {\n  const topic = (item.json.topic || '').trim();\n  const imageUrl = (item.json.image_url || '').trim();\n  const status = (item.json.status || '').toLowerCase().trim();\n  \n  return topic.length > 0 && \n         imageUrl.length > 0 && \n         !['done', 'processing', 'uploaded', 'error'].includes(status);\n});\n\nif (!valid) {\n  return [];\n}\n\nconst topic = valid.json.topic.trim();\nconst parts = topic.split('\u2014').map(s => s.trim());\n\nreturn [{\n  json: {\n    topic: topic,\n    scent_name: parts[0] || topic,\n    brand_name: parts[1] || '',\n    reference_url: valid.json.image_url.trim(),\n    row_number: valid.json.row_number || 2\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "76bf996c-5513-48dd-a7fa-0ba14b2460b7",
      "name": "Mark Processing2",
      "type": "n8n-nodes-base.googleSheets",
      "onError": "continueRegularOutput",
      "position": [
        -1984,
        80
      ],
      "parameters": {
        "columns": {
          "value": {
            "topic": "={{ $json.topic }}",
            "status": "processing",
            "row_number": 0
          },
          "schema": [
            {
              "id": "topic",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "topic",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "image_url",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "image_url",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "status",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "video_id",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "video_id",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "youtube_url",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "youtube_url",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "row_number",
              "type": "number",
              "display": true,
              "required": false,
              "displayName": "row_number",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "topic"
          ]
        },
        "options": {},
        "operation": "update",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "YOUR_GOOGLE_SHEET_ID"
        }
      },
      "typeVersion": 4
    },
    {
      "id": "73dee076-5600-491e-b65f-180107d2af29",
      "name": "Schedule Trigger2",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -2656,
        80
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "triggerAtHour": 9
            },
            {
              "triggerAtHour": 15
            }
          ]
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "fc1bd994-cfd7-43ec-a4ed-8afa63bd4ab4",
      "name": "Prepare Upload2",
      "type": "n8n-nodes-base.code",
      "position": [
        -816,
        80
      ],
      "parameters": {
        "jsCode": "const response = $input.first().json;\nconst topic = String($('Validate Input2').item.json.topic || '').trim();\nconst videoUrl = $('Check Video Status').item.json.data.response.resultUrls[0];\n\nlet parsed;\ntry {\n  let content = response.message?.content || response.content || '';\n  content = content.replace(/```json\\s*/g, '').replace(/```\\s*/g, '').trim();\n  parsed = JSON.parse(content);\n} catch (e) {\n  parsed = {};\n}\n\nreturn [{\n  json: {\n    topic,\n    video_url: videoUrl,\n    youtube_title: parsed.youtube_title || parsed?.youtube?.title || topic.substring(0, 60),\n    youtube_description: parsed.youtube_description || parsed?.youtube?.description || '',\n    tiktok_caption: parsed.tiktok_caption || parsed?.tiktok?.caption || '',\n    instagram_caption: parsed.instagram_caption || parsed?.instagram?.caption || '',\n    pinterest_title: parsed.pinterest_title || parsed?.pinterest?.title || topic,\n    pinterest_description: parsed.pinterest_description || parsed?.pinterest?.description || ''\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "33ee2bd9-38cd-4cf7-9ef8-0f5de5f90bbe",
      "name": "Telegram2",
      "type": "n8n-nodes-base.telegram",
      "position": [
        400,
        80
      ],
      "parameters": {
        "text": "=\u2713 {{ $('Validate Input2').item.json.topic }}\nhttps://youtube.com/shorts/{{ $json.uploadId }}",
        "chatId": "YOUR_TELEGRAM_CHAT_ID",
        "additionalFields": {}
      },
      "typeVersion": 1
    }
  ],
  "connections": {
    "Ready?": {
      "main": [
        [
          {
            "node": "GPT-4o (Captions)",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Wait & Retry2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "TikTok": {
      "main": [
        [
          {
            "node": "Update Sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "YouTube": {
      "main": [
        [
          {
            "node": "Update Sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait 30s": {
      "main": [
        [
          {
            "node": "Check Video Status",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Instagram": {
      "main": [
        [
          {
            "node": "Update Sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Pinterest": {
      "main": [
        [
          {
            "node": "Update Sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Update Sheet": {
      "main": [
        [
          {
            "node": "Telegram2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract Image": {
      "main": [
        [
          {
            "node": "Upload to ImgBB",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait & Retry2": {
      "main": [
        [
          {
            "node": "Check Video Status",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Download Video": {
      "main": [
        [
          {
            "node": "YouTube",
            "type": "main",
            "index": 0
          },
          {
            "node": "Pinterest",
            "type": "main",
            "index": 0
          },
          {
            "node": "TikTok",
            "type": "main",
            "index": 0
          },
          {
            "node": "Instagram",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Sheet Data": {
      "main": [
        [
          {
            "node": "Validate Input2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Upload2": {
      "main": [
        [
          {
            "node": "Download Video",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Upload to ImgBB": {
      "main": [
        [
          {
            "node": "Build Video Prompt",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Validate Input2": {
      "main": [
        [
          {
            "node": "Mark Processing2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Mark Processing2": {
      "main": [
        [
          {
            "node": "Download Product Image",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "GPT-4o (Captions)": {
      "main": [
        [
          {
            "node": "Prepare Upload2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Schedule Trigger2": {
      "main": [
        [
          {
            "node": "Get Sheet Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Image Prompt": {
      "main": [
        [
          {
            "node": "Gemini (Frozen Image)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Video Prompt": {
      "main": [
        [
          {
            "node": "Generate Video (Veo3)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Video Status": {
      "main": [
        [
          {
            "node": "Ready?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Gemini (Frozen Image)": {
      "main": [
        [
          {
            "node": "Extract Image",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate Video (Veo3)": {
      "main": [
        [
          {
            "node": "Wait 30s",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Download Product Image": {
      "main": [
        [
          {
            "node": "Build Image Prompt",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}