{
  "id": "OxdUBxc7llHmoDZx",
  "name": "My workflow 3",
  "tags": [],
  "nodes": [
    {
      "id": "4a993817-3909-4d2b-b7ef-f2b9f34dea76",
      "name": "Sticky - Webhook Contract & Security",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -336,
        48
      ],
      "parameters": {
        "content": "Inbound trigger for external start. Validate secret; parse JSON; return 200 immediately."
      },
      "typeVersion": 1
    },
    {
      "id": "ddb50403-dc30-4068-9c40-0022f222b748",
      "name": "WebHook",
      "type": "n8n-nodes-base.webhook",
      "position": [
        -96,
        96
      ],
      "parameters": {
        "path": "52048302-06bd-4eae-9b004c5ed17d",
        "options": {},
        "httpMethod": "POST"
      },
      "typeVersion": 2.1
    },
    {
      "id": "2322ee6b-3f5a-46d4-95b2-3ac405711621",
      "name": "Sticky - Normalize Text for TTS",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        32,
        16
      ],
      "parameters": {
        "height": 224,
        "content": "Sanitize the video script to ensure HeyGen can use that correctly."
      },
      "typeVersion": 1
    },
    {
      "id": "58891633-6f20-4d91-99f9-6f72cfd0336b",
      "name": "Code",
      "type": "n8n-nodes-base.code",
      "position": [
        128,
        96
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "const item = $input.item;\nreturn { json: { content: item.json.body.content.replaceAll(\"\\n\", \"\").replaceAll(\"\\r\", \"\"), title:item.json.body.title } };"
      },
      "typeVersion": 2
    },
    {
      "id": "2cc0fe4b-a229-4937-a8b7-d6ed766aee6b",
      "name": "Sticky - Parameter Staging (Secrets & IDs)",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        304,
        -16
      ],
      "parameters": {
        "height": 320,
        "content": "Init vars (script, voice_id, avatar_id, aspect, sub=false); set defaults."
      },
      "typeVersion": 1
    },
    {
      "id": "86024350-5e49-43a6-a98f-f3cc0ad63abf",
      "name": "Setup Heygen Parameters",
      "type": "n8n-nodes-base.set",
      "disabled": true,
      "position": [
        384,
        96
      ],
      "parameters": {
        "fields": {
          "values": [
            {
              "name": "x-api-key"
            },
            {
              "name": "voice_id"
            },
            {
              "name": "avatar_id"
            },
            {
              "name": "title",
              "stringValue": "={{ $json.title }}"
            },
            {
              "name": "content",
              "stringValue": "={{ $json.content }}"
            }
          ]
        },
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "f1fa5816-f371-4a91-8eed-fca27399b46f",
      "name": "Sticky - Create HeyGen Job (v2)",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        560,
        -16
      ],
      "parameters": {
        "width": 208,
        "height": 288,
        "content": "Submit video generation request to HeyGen using API: POST /v2/video/generate with params."
      },
      "typeVersion": 1
    },
    {
      "id": "970c4d5f-0ba5-4b3e-9b0b-d6edb8821f9b",
      "name": "Create Avatar Video (HeyGen)",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        608,
        96
      ],
      "parameters": {
        "url": "https://api.heygen.com/v2/video/generate",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"video_inputs\": [\n    {\n      \"character\": {\n        \"type\": \"avatar\",\n        \"avatar_id\": \"{{ $json.avatar_id }}\",\n        \"avatar_style\": \"normal\"\n      },\n      \"voice\": {\n        \"type\": \"text\",\n        \"input_text\": \"{{ $json.content }}\",\n        \"voice_id\": \"{{ $json.voice_id }}\",\n        \"speed\": 1.1\n      }\n    }\n  ],\n  \"dimension\": {\n    \"width\": 1280,\n    \"height\": 720\n  }\n}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "headerParameters": {
          "parameters": [
            {
              "name": "X-Api-Key",
              "value": "={{ $json['x-api-key'] }}"
            }
          ]
        }
      },
      "typeVersion": 4
    },
    {
      "id": "ff31c0bd-26af-4065-8e7f-9910955e5326",
      "name": "Sticky - Polling Cycle",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        784,
        0
      ],
      "parameters": {
        "width": 208,
        "height": 272,
        "content": "Delay polling to avoid rate limits; increase wait for long video generations"
      },
      "typeVersion": 1
    },
    {
      "id": "2661127a-2c82-4a88-9336-0a04df5eddb3",
      "name": "Wait for Video (HeyGen)",
      "type": "n8n-nodes-base.wait",
      "position": [
        832,
        96
      ],
      "parameters": {
        "unit": "minutes",
        "amount": 0.1
      },
      "typeVersion": 1
    },
    {
      "id": "36b2a0f9-84d4-4b1d-b61b-f2233b28ffe2",
      "name": "Get Avatar Video Status (HeyGen)",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1056,
        96
      ],
      "parameters": {
        "url": "https://api.heygen.com/v1/video_status.get",
        "options": {},
        "sendQuery": true,
        "sendHeaders": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "video_id",
              "value": "={{ $('Create Avatar Video (HeyGen)').item.json.data.video_id }}"
            }
          ]
        },
        "headerParameters": {
          "parameters": [
            {
              "name": "X-Api-Key",
              "value": "={{ $('Setup Heygen Parameters').item.json['x-api-key'] }}"
            }
          ]
        }
      },
      "typeVersion": 4
    },
    {
      "id": "37a4815e-7562-4764-8883-03e2502a897a",
      "name": "If Processing Completed",
      "type": "n8n-nodes-base.if",
      "position": [
        1264,
        96
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "2b0f3da8-9f60-4a14-af38-8064531cf6d4",
              "operator": {
                "type": "string",
                "operation": "notEquals"
              },
              "leftValue": "={{ $json.data.status }}",
              "rightValue": "processing"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "7de09738-3b54-4b96-a46d-65c85767da8e",
      "name": "Sticky - Download Result (Binary)",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1424,
        -16
      ],
      "parameters": {
        "height": 256,
        "content": "If status is not 'processing' -> Try to download; if download fails it means the video generation in HeyGen errored for whatever reason."
      },
      "typeVersion": 1
    },
    {
      "id": "a97d12ea-8280-41bc-a415-42df2083c017",
      "name": "Download Video",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1488,
        96
      ],
      "parameters": {
        "url": "={{ $json.data.video_url }}",
        "options": {}
      },
      "typeVersion": 4
    },
    {
      "id": "d2f7447a-232a-4817-89ef-b2058d570643",
      "name": "Sticky - YouTube Upload (Binary Property & Metadata)",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1680,
        0
      ],
      "parameters": {
        "width": 224,
        "height": 240,
        "content": "Upload the video (downloaded data) to Youtube."
      },
      "typeVersion": 1
    },
    {
      "id": "6056c5ef-2c7f-47fd-b75c-0cf3ad286997",
      "name": "Upload a video",
      "type": "n8n-nodes-base.youTube",
      "position": [
        1712,
        96
      ],
      "parameters": {
        "title": "={{ $('Setup Heygen Parameters').item.json.title }}",
        "options": {},
        "resource": "video",
        "operation": "upload",
        "categoryId": "28",
        "regionCode": "US"
      },
      "credentials": {
        "youTubeOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "2ee94e2e-531d-40d7-8d83-0a805b96b3b4",
      "name": "Sticky - Polling Cycle1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1008,
        0
      ],
      "parameters": {
        "width": 208,
        "height": 272,
        "content": "Get status of the generated video from HeyGen."
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "e8f0e6b5-b9a0-4b09-8106-2e326dbd3f14",
  "connections": {
    "Code": {
      "main": [
        [
          {
            "node": "Setup Heygen Parameters",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "WebHook": {
      "main": [
        [
          {
            "node": "Code",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Download Video": {
      "main": [
        [
          {
            "node": "Upload a video",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If Processing Completed": {
      "main": [
        [
          {
            "node": "Download Video",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Wait for Video (HeyGen)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Setup Heygen Parameters": {
      "main": [
        [
          {
            "node": "Create Avatar Video (HeyGen)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait for Video (HeyGen)": {
      "main": [
        [
          {
            "node": "Get Avatar Video Status (HeyGen)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create Avatar Video (HeyGen)": {
      "main": [
        [
          {
            "node": "Wait for Video (HeyGen)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Avatar Video Status (HeyGen)": {
      "main": [
        [
          {
            "node": "If Processing Completed",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}