AutomationFlowsSocial Media › Create AI Video Reels From Profile Photos with Atlascloud and Blotato

Create AI Video Reels From Profile Photos with Atlascloud and Blotato

ByDr. Firas @drfiras on n8n.io

This workflow receives a webhook request, uses AtlasCloud (GPT Image 2 and HappyHorse) to turn a profile image into a short vertical video, then publishes the reel to TikTok and Instagram via Blotato. Receives a POST webhook containing an image prompt, a video prompt, and an…

Webhook trigger★★★★☆ complexity20 nodesHTTP Request@Blotato/N8N Nodes BlotatoStop And Error
Social Media Trigger: Webhook Nodes: 20 Complexity: ★★★★☆ Added:

This workflow corresponds to n8n.io template #16148 — we link there as the canonical source.

This workflow follows the Blotaton8N Nodes Blotato → HTTP Request 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 →

Download .json
{
  "id": "Xh4FbHplJcE2kMim",
  "meta": {
    "builderVariant": "mcp",
    "aiBuilderAssisted": true,
    "templateCredsSetupCompleted": true
  },
  "name": "Create reels with GPT Image 2 and HappyHorse, post to TikTok with Blotato - vide",
  "tags": [],
  "nodes": [
    {
      "id": "aaf83489-6a22-4748-950f-e73186f1dab7",
      "name": "Webhook Trigger",
      "type": "n8n-nodes-base.webhook",
      "position": [
        960,
        96
      ],
      "parameters": {
        "path": "16960223-46ec-46ec-b5d8-17180c89e6b7",
        "options": {},
        "httpMethod": "POST"
      },
      "typeVersion": 2.1
    },
    {
      "id": "44e7b0ef-0071-4b16-880d-9f61bd4e94c4",
      "name": "Config",
      "type": "n8n-nodes-base.set",
      "position": [
        1184,
        96
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "a-prompt",
              "name": "prompt",
              "type": "string",
              "value": "={{ $json.body?.prompt ?? $json.prompt }}"
            },
            {
              "id": "a-caption",
              "name": "caption",
              "type": "string",
              "value": "={{ $json.body?.caption ?? $json.caption ?? \"\" }}"
            },
            {
              "id": "a-profile",
              "name": "profile_image_url",
              "type": "string",
              "value": "YOUR-IMAGE-URL"
            },
            {
              "id": "6a628659-07c5-4eb8-ba1f-bcffbc304b9b",
              "name": "prompt_video",
              "type": "string",
              "value": "={{ $json.body?.prompt_video ?? $json.prompt_video }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "8741c20f-e53a-403c-ae98-f4daf4fcd2aa",
      "name": "Wait Image",
      "type": "n8n-nodes-base.wait",
      "position": [
        1632,
        96
      ],
      "parameters": {},
      "typeVersion": 1.1
    },
    {
      "id": "39f7f9f0-f139-43cc-ad7b-d20e83a51924",
      "name": "Poll Image",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1840,
        96
      ],
      "parameters": {
        "url": "=https://api.atlascloud.ai/api/v1/model/prediction/{{ $(\"Generate Image with GPT Image 2 Model\").item.json.data.id }}",
        "options": {},
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "Bearer YOUR_API"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        }
      },
      "typeVersion": 4.4
    },
    {
      "id": "b2cfd0b5-fac8-4316-b946-e8ae804e69a5",
      "name": "Generate Video",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        960,
        512
      ],
      "parameters": {
        "url": "https://api.atlascloud.ai/api/v1/model/generateVideo",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"model\": \"alibaba/happyhorse-1.0/image-to-video\",\n  \"resolution\": \"720P\",\n  \"duration\": 5,\n  \"seed\": -1,\n  \"prompt\": {{ JSON.stringify($('Config').item.json.prompt_video) }},\n  \"image\": {{ JSON.stringify($('Extract Image URL').item.json.image_url) }}\n}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "Bearer YOUR_API"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        }
      },
      "typeVersion": 4.4
    },
    {
      "id": "efa81474-ac7a-44d2-be03-a4901bddf8c4",
      "name": "Wait Video",
      "type": "n8n-nodes-base.wait",
      "position": [
        1184,
        512
      ],
      "parameters": {
        "amount": 10
      },
      "typeVersion": 1.1
    },
    {
      "id": "bc72b966-d9ff-4b92-b67d-f9828b0d73ad",
      "name": "Poll Video",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1408,
        512
      ],
      "parameters": {
        "url": "=https://api.atlascloud.ai/api/v1/model/prediction/{{ $(\"Generate Video\").item.json.data.id }}",
        "options": {},
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "Bearer YOUR_API"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        }
      },
      "typeVersion": 4.4
    },
    {
      "id": "0a6bb3a7-b859-4196-9d4c-22088c2f31c2",
      "name": "Generate Image with GPT Image 2 Model",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1408,
        96
      ],
      "parameters": {
        "url": "https://api.atlascloud.ai/api/v1/model/generateImage",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"model\": \"openai/gpt-image-2/edit\",\n  \"prompt\": \"A dynamic action shot of a man performing a powerful slam dunk, mid-air above the basketball hoop, ball gripped in one hand about to go through the net. Athletic posture, wearing a dark navy and forest-green basketball jersey with white trim and the number \\\"26\\\" printed boldly on the front. Indoor arena setting with bright court lighting, motion blur on the background crowd, dramatic low-angle perspective looking up at the player. Energetic, cinematic sports photography style, high detail, vibrant colors, 4k.\",\n  \"images\": [\"{{ $json.profile_image_url }}\"],\n  \"quality\": \"high\",\n  \"size\": \"1024x1536\"\n}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "Bearer YOUR_API"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        }
      },
      "typeVersion": 4.4
    },
    {
      "id": "8ea8db5b-8140-4a96-a4e1-7cf6bdf33e3b",
      "name": "Extract Image URL",
      "type": "n8n-nodes-base.code",
      "position": [
        2384,
        16
      ],
      "parameters": {
        "jsCode": "const r = $input.first().json;\nconst data = r.data || r;\nconst imageUrl = (data.outputs && data.outputs[0]) || data.output || data.image_url || data.image;\nif (!imageUrl) {\n  throw new Error('No image URL found in AtlasCloud response: ' + JSON.stringify(data).substring(0, 300));\n}\nreturn [{ json: { image_url: imageUrl } }];"
      },
      "typeVersion": 2
    },
    {
      "id": "3a464f42-79bf-46b3-868c-45916abde17f",
      "name": "Extract Video URL",
      "type": "n8n-nodes-base.code",
      "position": [
        2368,
        480
      ],
      "parameters": {
        "jsCode": "const r = $input.first().json;\nconst data = r.data || r;\nconst videoUrl = (data.outputs && data.outputs[0]) || data.output || data.video_url;\nif (!videoUrl) {\n  throw new Error('No video URL found in AtlasCloud response: ' + JSON.stringify(data).substring(0, 300));\n}\nreturn [{ json: { video_url: videoUrl } }];"
      },
      "typeVersion": 2
    },
    {
      "id": "8a1effb2-195b-413f-bdf3-8d3531627c9e",
      "name": "Create post Tiktok",
      "type": "@blotato/n8n-nodes-blotato.blotato",
      "position": [
        2720,
        288
      ],
      "parameters": {
        "options": {},
        "platform": "tiktok",
        "accountId": {
          "__rl": true,
          "mode": "id",
          "value": "=YOUR_ID_BLOTATO_TIKTOK"
        },
        "postContentText": "={{ $('Config').item.json.caption }}",
        "postContentMediaUrls": "={{ $json.video_url }}",
        "postCreateTiktokOptionIsAiGenerated": true
      },
      "credentials": {
        "blotatoApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2
    },
    {
      "id": "cef1622c-ef79-4d78-825a-8772d4ab5435",
      "name": "Create post Instagram",
      "type": "@blotato/n8n-nodes-blotato.blotato",
      "position": [
        2720,
        544
      ],
      "parameters": {
        "options": {},
        "accountId": {
          "__rl": true,
          "mode": "id",
          "value": "=YOUR_ID_BLOTATO_INSTAGRAM"
        },
        "postContentText": "={{ $('Config').item.json.caption }}",
        "postContentMediaUrls": "={{ $json.video_url }}"
      },
      "credentials": {
        "blotatoApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2
    },
    {
      "id": "71d829fa-075e-43a9-ad67-e828e495019f",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -64,
        -80
      ],
      "parameters": {
        "width": 912,
        "height": 864,
        "content": "# Create reels with GPT Image 2 and HappyHorse, post to TikTok with Blotato\n\n\n## \ud83d\udce5   [Open full documentation on Notion](https://automatisation.notion.site/Create-reels-with-GPT-Image-2-and-HappyHorse-post-to-TikTok-with-Blotato-3773d6550fd980fa915bcce066deaacb?source=copy_link)\n\n\u26a0\ufe0f **Community node \u2014 self-hosted n8n only.** This template uses the Blotato community node, which is not available on n8n Cloud.\n\nThis template turns a single profile photo into a vertical AI video reel and auto-publishes it to TikTok and Instagram. Send a topic via webhook, and the workflow edits your photo, animates it, and posts it \u2014 fully hands-off.\n\n## Who's it for\nContent creators, social media managers and personal brands who want to produce short-form vertical videos at scale without manual editing.\n\n## How it works\n- A **Webhook** receives an image prompt, a video prompt and a caption.\n- **GPT Image 2** ([AtlasCloud](https://www.atlascloud.ai/?ref=8QKPJE)) edits your profile photo based on the image prompt.\n- A polling loop waits until the image is ready, then extracts its URL.\n- **HappyHorse 1.0** ([AtlasCloud](https://www.atlascloud.ai/?ref=8QKPJE)) animates that image into a short vertical video.\n- A second polling loop waits for the video, then extracts its URL.\n- **[Blotato](https://blotato.com/?ref=firas)** uploads the video and publishes it to TikTok and Instagram.\n\n## How to set up\n1. Add your [AtlasCloud](https://www.atlascloud.ai/?ref=8QKPJE) API key as a Header Auth credential (`Authorization: Bearer YOUR_KEY`).\n2. Connect your [Blotato](https://blotato.com/?ref=firas) account credential.\n3. In the **Set your variables** node, set your profile photo URL and your TikTok / Instagram account IDs.\n\n## Requirements\n- [AtlasCloud](https://www.atlascloud.ai/?ref=8QKPJE) account (GPT Image 2 + HappyHorse 1.0)\n- [Blotato](https://blotato.com/?ref=firas) account with TikTok & Instagram connected\n- Self-hosted n8n (community node)\n\n## How to customize\n- Swap the AtlasCloud models for other image/video models.\n- Adjust resolution and duration in the video node.\n- Add or remove publishing destinations (LinkedIn, YouTube, etc.) via Blotato."
      },
      "typeVersion": 1
    },
    {
      "id": "4fafd210-9c4e-430c-93c1-7c4d679ca719",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2608,
        -80
      ],
      "parameters": {
        "color": 2,
        "width": 336,
        "height": 864,
        "content": "##  STEP 3 - Publish to social media\nThe video URL is extracted, uploaded to [Blotato](https://blotato.com/?ref=firas), and published to TikTok and Instagram. Configure which accounts to post to via the Blotato credential and account IDs."
      },
      "typeVersion": 1
    },
    {
      "id": "dfab6608-074a-476c-995a-db896414b4c9",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        896,
        -80
      ],
      "parameters": {
        "color": 7,
        "width": 1664,
        "height": 416,
        "content": "## STEP 1 - Image generation \u2014 GPT Image 2 (AtlasCloud)\nThe webhook receives `prompt`, `prompt_video` and `caption`. Set your profile photo URL and account IDs in the \"Set your variables\" node.\n\n**GPT Image 2** ([AtlasCloud](https://www.atlascloud.ai/?ref=8QKPJE)) edits your profile photo (image-to-image) using the image prompt, in vertical 2:3 format.\n\nGeneration is asynchronous: the Wait \u2192 Poll \u2192 \"Image Ready?\" loop runs until the status is \"completed\" or \"succeeded\", then \"Extract Image URL\" returns the generated image URL."
      },
      "typeVersion": 1
    },
    {
      "id": "74db6b5d-afc4-4e1e-a7c2-809af8c8e085",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        896,
        368
      ],
      "parameters": {
        "color": 7,
        "width": 1664,
        "height": 416,
        "content": "## STEP 2 - Video generation \u2014 HappyHorse 1.0 (AtlasCloud)\n**HappyHorse 1.0** ([AtlasCloud](https://www.atlascloud.ai/?ref=8QKPJE)) animates the generated image into a short vertical video (image-to-video) using the video prompt.\n\nSame asynchronous pattern: the Wait \u2192 Poll \u2192 \"Video Ready?\" loop runs until the status is \"completed\" or \"succeeded\", then \"Extract Video URL\" returns the final video URL ready for publishing."
      },
      "typeVersion": 1
    },
    {
      "id": "5c109220-5253-4efe-97fb-7cf070769c67",
      "name": "Image Status",
      "type": "n8n-nodes-base.switch",
      "position": [
        2064,
        80
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "outputKey": "done",
              "conditions": {
                "options": {
                  "version": 3,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "66660518-0c84-4332-b4fb-e848f63f5613",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.data.status }}",
                    "rightValue": "completed"
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "processing",
              "conditions": {
                "options": {
                  "version": 3,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "2885baf4-3583-4de8-9d77-2ab1cda7d2d7",
                    "operator": {
                      "name": "filter.operator.equals",
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.data.status }}",
                    "rightValue": "processing"
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "Stop and Error",
              "conditions": {
                "options": {
                  "version": 3,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "45757936-1524-45a6-b0ea-28ddc5e5265d",
                    "operator": {
                      "name": "filter.operator.equals",
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.data.status }}",
                    "rightValue": "failed"
                  }
                ]
              },
              "renameOutput": true
            }
          ]
        },
        "options": {}
      },
      "typeVersion": 3.4
    },
    {
      "id": "5e6679ab-3e86-432e-9562-3c812a73f3ab",
      "name": "Stop and Error",
      "type": "n8n-nodes-base.stopAndError",
      "position": [
        2384,
        176
      ],
      "parameters": {
        "errorMessage": "=={{ \"AtlasCloud image generation failed: \" + ($json.data.error || \"unknown error\") }}"
      },
      "typeVersion": 1
    },
    {
      "id": "3f0d0ec5-2d3d-4cd1-b747-fa74fc35e302",
      "name": "Video Status",
      "type": "n8n-nodes-base.switch",
      "position": [
        1632,
        496
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "outputKey": "done",
              "conditions": {
                "options": {
                  "version": 3,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "66660518-0c84-4332-b4fb-e848f63f5613",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.data.status }}",
                    "rightValue": "completed"
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "processing",
              "conditions": {
                "options": {
                  "version": 3,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "2885baf4-3583-4de8-9d77-2ab1cda7d2d7",
                    "operator": {
                      "name": "filter.operator.equals",
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.data.status }}",
                    "rightValue": "processing"
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "Stop and Error",
              "conditions": {
                "options": {
                  "version": 3,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "45757936-1524-45a6-b0ea-28ddc5e5265d",
                    "operator": {
                      "name": "filter.operator.equals",
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.data.status }}",
                    "rightValue": "failed"
                  }
                ]
              },
              "renameOutput": true
            }
          ]
        },
        "options": {}
      },
      "typeVersion": 3.4
    },
    {
      "id": "1dfa0f63-5722-435d-866f-b9c4ab432725",
      "name": "Stop and Error II",
      "type": "n8n-nodes-base.stopAndError",
      "position": [
        2368,
        640
      ],
      "parameters": {
        "errorMessage": "=={{ \"AtlasCloud image generation failed: \" + ($json.data.error || \"unknown error\") }}"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "availableInMCP": false,
    "executionOrder": "v1"
  },
  "versionId": "df0dacfb-5149-44e0-bc30-096819204642",
  "connections": {
    "Config": {
      "main": [
        [
          {
            "node": "Generate Image with GPT Image 2 Model",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Poll Image": {
      "main": [
        [
          {
            "node": "Image Status",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Poll Video": {
      "main": [
        [
          {
            "node": "Video Status",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait Image": {
      "main": [
        [
          {
            "node": "Poll Image",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait Video": {
      "main": [
        [
          {
            "node": "Poll Video",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Image Status": {
      "main": [
        [
          {
            "node": "Extract Image URL",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Wait Image",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Stop and Error",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Video Status": {
      "main": [
        [
          {
            "node": "Extract Video URL",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Wait Video",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Stop and Error II",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate Video": {
      "main": [
        [
          {
            "node": "Wait Video",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Webhook Trigger": {
      "main": [
        [
          {
            "node": "Config",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract Image URL": {
      "main": [
        [
          {
            "node": "Generate Video",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract Video URL": {
      "main": [
        [
          {
            "node": "Create post Tiktok",
            "type": "main",
            "index": 0
          },
          {
            "node": "Create post Instagram",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate Image with GPT Image 2 Model": {
      "main": [
        [
          {
            "node": "Wait Image",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

Credentials you'll need

Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.

Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

This workflow receives a webhook request, uses AtlasCloud (GPT Image 2 and HappyHorse) to turn a profile image into a short vertical video, then publishes the reel to TikTok and Instagram via Blotato. Receives a POST webhook containing an image prompt, a video prompt, and an…

Source: https://n8n.io/workflows/16148/ — original creator credit. Request a take-down →

More Social Media workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

Social Media

📄 Documentation: Notion Guide

Google Sheets, Anthropic, HTTP Request +1
Social Media

Instagram - Fluxo de mensagens. Uses rabbitmq, rabbitmqTrigger, googleSheets, httpRequest. Webhook trigger; 74 nodes.

Rabbitmq, Rabbitmq Trigger, Google Sheets +1
Social Media

This workflow automatically mirrors your YouTube to TikTok and Instagram, so you don’t have to manually download and re-upload your content across platforms.

@Blotato/N8N Nodes Blotato, Execute Command, HTTP Request +2
Social Media

Extracts a clean transcript from a videoId using youtube-transcript.io. AI summaries, sentiment analysis, keyword extraction Internal indexing/SEO Content pipelines (blog/newsletter) Batch transcript

HTTP Request, Execute Workflow Trigger, Stop And Error
Social Media

Automated n8n workflow: Receives videos via form, dubs/translates them to the selected languages, and—upon completion—uploads them to multiple social media channels and cloud drives, including Box, Dr

HTTP Request, Telegram, Box +3