{
"id": "vancine-seedance-starter",
"name": "Generate Seedance videos with Vancine API and bounded polling",
"active": false,
"nodes": [
{
"name": "manualTrigger",
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [
240,
300
],
"parameters": {},
"id": "mt_06aa62101478b04e"
},
{
"name": "setFields",
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
460,
300
],
"id": "sf_ce466658d13cf5de",
"parameters": {
"assignments": {
"assignments": [
{
"id": "model",
"name": "model",
"value": "Doubao-Seedance-1.5-pro",
"type": "string"
},
{
"id": "prompt",
"name": "prompt",
"value": "A timelapse of a flower blooming at sunrise",
"type": "string"
},
{
"id": "size",
"name": "size",
"value": "1280x720",
"type": "string"
},
{
"id": "base_url",
"name": "base_url",
"value": "https://vancine.com",
"type": "string"
},
{
"id": "intervalSeconds",
"name": "intervalSeconds",
"value": 5,
"type": "number"
},
{
"id": "maxPolls",
"name": "maxPolls",
"value": 120,
"type": "number"
}
]
},
"options": {}
}
},
{
"name": "submitTask",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
680,
300
],
"id": "st_017726b463a0f380",
"parameters": {
"method": "POST",
"url": "={{$json.base_url}}/v1/video/generations",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Content-Type",
"value": "application/json"
}
]
},
"sendBody": true,
"bodyParameters": {
"parameters": [
{
"name": "model",
"value": "={{$json.model}}"
},
{
"name": "prompt",
"value": "={{$json.prompt}}"
},
{
"name": "size",
"value": "={{$json.size}}"
}
]
},
"options": {}
},
"nodeCredentialType": "httpHeaderAuth",
"credentials": {}
},
{
"name": "saveTaskId",
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
900,
300
],
"id": "sv_e9f9b7cde8c72b43",
"parameters": {
"assignments": {
"assignments": [
{
"id": "task_id",
"name": "task_id",
"value": "={{$json.task_id || $json.id || ($json.data && $json.data.task_id) || ($json.data && $json.data.id)}}",
"type": "string"
},
{
"id": "base_url",
"name": "base_url",
"value": "={{$('setFields').first().json.base_url || 'https://vancine.com'}}",
"type": "string"
},
{
"id": "intervalSeconds",
"name": "intervalSeconds",
"value": "={{$('setFields').first().json.intervalSeconds || 5}}",
"type": "number"
},
{
"id": "maxPolls",
"name": "maxPolls",
"value": "={{$('setFields').first().json.maxPolls || 120}}",
"type": "number"
},
{
"id": "poll_index",
"name": "poll_index",
"value": 0,
"type": "number"
}
]
},
"options": {}
}
},
{
"name": "waitInterval",
"type": "n8n-nodes-base.wait",
"typeVersion": 1.1,
"position": [
1120,
300
],
"id": "wt_617d429b0526fd9e",
"parameters": {
"amount": "={{$json.intervalSeconds || 5}}",
"unit": "seconds"
}
},
{
"name": "pollTask",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
1340,
200
],
"id": "pt_182f5f47f46f88d4",
"parameters": {
"method": "GET",
"url": "={{$json.base_url}}/v1/video/generations/{{$json.task_id}}",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"options": {}
},
"nodeCredentialType": "httpHeaderAuth",
"credentials": {}
},
{
"name": "carryState",
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
1340,
400
],
"id": "cs_3f26bc9f90379a38",
"parameters": {
"assignments": {
"assignments": [
{
"id": "task_id",
"name": "task_id",
"value": "={{$json.task_id}}",
"type": "string"
},
{
"id": "poll_index",
"name": "poll_index",
"value": "={{$json.poll_index || 0}}",
"type": "number"
},
{
"id": "maxPolls",
"name": "maxPolls",
"value": "={{$json.maxPolls || 120}}",
"type": "number"
},
{
"id": "intervalSeconds",
"name": "intervalSeconds",
"value": "={{$json.intervalSeconds || 5}}",
"type": "number"
},
{
"id": "base_url",
"name": "base_url",
"value": "={{$json.base_url || 'https://vancine.com'}}",
"type": "string"
}
]
},
"options": {}
}
},
{
"name": "mergeResults",
"type": "n8n-nodes-base.merge",
"typeVersion": 3,
"position": [
1560,
300
],
"id": "mr_a5d808a609f555e2",
"parameters": {
"mode": "append",
"options": {}
}
},
{
"name": "mergeState",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1780,
300
],
"id": "ms_aeaaa2c69144e9df",
"parameters": {
"language": "javaScript",
"mode": "runOnceForAllItems",
"jsCode": "// Merge the HTTP poll response with the carried loop state. NO network calls.\n// Items arrive via Merge(append): one from pollTask (response), one from carryState.\nconst items = $input.all();\nconst response = items.find(i => i.json.status !== undefined && i.json.object !== undefined) || items[0];\nconst carried = items.find(i => i.json.poll_index !== undefined) || items[items.length > 1 ? 1 : 0] || items[0];\nconst pollIndex = (carried.json.poll_index || 0) + 1;\nconst taskId = response.json.task_id || response.json.id || (response.json.data && response.json.data.task_id) || (response.json.data && response.json.data.id) || carried.json.task_id;\nconst status = response.json.status || (response.json.data && response.json.data.status);\nconst metadata = response.json.metadata || (response.json.data && response.json.data.metadata);\nconst data = response.json.data;\nconst error = response.json.error || (response.json.data && response.json.data.error);\nconst resultUrl = (metadata && metadata.url)\n || (data && data.result_url)\n || (data && data.data && data.data.content && data.data.content.video_url)\n || '';\nreturn [{ json: {\n task_id: taskId,\n status: status,\n metadata: metadata,\n data: data,\n error: error,\n poll_index: pollIndex,\n maxPolls: carried.json.maxPolls || 120,\n intervalSeconds: carried.json.intervalSeconds || 5,\n base_url: carried.json.base_url || 'https://vancine.com',\n result_url: resultUrl\n}}];"
}
},
{
"name": "ifCompleted",
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [
2000,
300
],
"id": "ic_6855f0082483c663",
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"type": "expression"
},
"conditions": [
{
"id": "c1",
"leftValue": "={{$json.status === 'completed' || $json.status === 'SUCCESS' || ($json.data && ($json.data.status === 'completed' || $json.data.status === 'SUCCESS'))}}",
"rightValue": true,
"operator": {
"type": "boolean",
"operation": "equals"
}
}
],
"combinator": "and"
},
"options": {}
}
},
{
"name": "outputResult",
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
2220,
200
],
"id": "or_89fefec94b364a33",
"parameters": {
"assignments": {
"assignments": [
{
"id": "result_url",
"name": "result_url",
"value": "={{$json.result_url}}",
"type": "string"
}
]
},
"options": {}
}
},
{
"name": "ifFailed",
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [
2220,
400
],
"id": "if_26951f656456684f",
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"type": "expression"
},
"conditions": [
{
"id": "c2",
"leftValue": "={{$json.status === 'failed' || $json.status === 'FAILURE' || ($json.data && ($json.data.status === 'failed' || $json.data.status === 'FAILURE'))}}",
"rightValue": true,
"operator": {
"type": "boolean",
"operation": "equals"
}
}
],
"combinator": "and"
},
"options": {}
}
},
{
"name": "failNode",
"type": "n8n-nodes-base.stopAndError",
"typeVersion": 1,
"position": [
2440,
400
],
"id": "fn_8d300061d1186ab7",
"parameters": {
"errorMessage": "={{'Seedance task ' + $json.task_id + ' failed: ' + (($json.error && $json.error.message) || ($json.data && $json.data.fail_reason) || 'unknown')}}"
}
},
{
"name": "ifTimeout",
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [
2220,
560
],
"id": "it_7f93fd8947db9b09",
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"type": "expression"
},
"conditions": [
{
"id": "c3",
"leftValue": "={{($json.poll_index || 0) >= ($json.maxPolls || 120)}}",
"rightValue": true,
"operator": {
"type": "boolean",
"operation": "equals"
}
}
],
"combinator": "and"
},
"options": {}
}
},
{
"name": "timeoutFail",
"type": "n8n-nodes-base.stopAndError",
"typeVersion": 1,
"position": [
2440,
560
],
"id": "tf_8302289baf1ddf07",
"parameters": {
"errorMessage": "={{'Polling exceeded ' + ($json.maxPolls || 120) + ' attempts for task ' + $json.task_id}}"
}
},
{
"name": "continuePolling",
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
2000,
560
],
"id": "cp_ff301842a4e8ea83",
"parameters": {
"assignments": {
"assignments": [
{
"id": "task_id",
"name": "task_id",
"value": "={{$json.task_id}}",
"type": "string"
},
{
"id": "poll_index",
"name": "poll_index",
"value": "={{$json.poll_index}}",
"type": "number"
},
{
"id": "maxPolls",
"name": "maxPolls",
"value": "={{$json.maxPolls || 120}}",
"type": "number"
},
{
"id": "intervalSeconds",
"name": "intervalSeconds",
"value": "={{$json.intervalSeconds || 5}}",
"type": "number"
},
{
"id": "base_url",
"name": "base_url",
"value": "={{$json.base_url || 'https://vancine.com'}}",
"type": "string"
}
]
},
"options": {}
}
},
{
"parameters": {
"content": "## Seedance\n\n### How it works\n\nThis workflow manually starts a Seedance video generation request, submits the configured prompt and model to a video generation API, then polls for completion. It carries loop state through each wait-and-poll cycle, merges the API response with that state, and routes the result to success, failure, timeout, or another polling iteration.\n\n### Setup steps\n\n- Configure the HTTP Request nodes with the required API authentication for the Seedance-compatible video generation service.\n- Update the setFields node with the desired model, prompt, output size, and base_url.\n- Adjust intervalSeconds and maxPolls in saveTaskId or related loop-state Set nodes to control polling frequency and timeout behavior.\n- Run the workflow manually from the manualTrigger node to test the full generation and polling flow.\n\n### Customization\n\nChange the prompt, model, size, polling interval, and maximum poll count to match the desired video output and service limits.",
"width": 480,
"height": 896
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-368,
48
],
"id": "82ebe33f-4cdd-4ee4-9300-c5e5eb7fe099",
"name": "Sticky Note"
},
{
"parameters": {
"content": "## Start and configure\n\nManual entry point and initial request configuration, including the model, prompt, size, and API base URL.",
"width": 416,
"height": 320,
"color": 7
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
192,
144
],
"id": "3fd1e53a-a10c-475d-aa5f-6ad12c6a4e48",
"name": "Sticky Note1"
},
{
"parameters": {
"content": "## Submit generation job\n\nSends the video generation POST request and extracts the task metadata needed for later polling.",
"width": 416,
"height": 320,
"color": 7
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
640,
144
],
"id": "f2c2ab13-014e-406c-85e6-381571095925",
"name": "Sticky Note2"
},
{
"parameters": {
"content": "## Wait before polling\n\nPauses between task submission or retry iterations before checking the generation status again.",
"width": 240,
"height": 336,
"color": 7
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
1104,
128
],
"id": "58fa6799-eba0-44d0-acb2-a0413de3fb59",
"name": "Sticky Note3"
},
{
"parameters": {
"content": "## Poll and merge state\n\nFetches the current task status, carries loop counters and configuration alongside it, then merges the API response with the retained polling state.",
"width": 640,
"height": 512,
"color": 7
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
1376,
48
],
"id": "abd0c0cf-d6db-482d-9033-489a57194439",
"name": "Sticky Note4"
},
{
"parameters": {
"content": "## Completion output routing\n\nChecks whether the generation completed and, if so, outputs the final result URL.",
"width": 416,
"height": 400,
"color": 7
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
2048,
64
],
"id": "18c689d3-5066-4114-992a-703eb0b04c39",
"name": "Sticky Note5"
},
{
"parameters": {
"content": "## Failure error handling\n\nEvaluates failed task states and stops the workflow with an error when the API reports generation failure.",
"width": 416,
"height": 320,
"color": 7
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
2176,
496
],
"id": "54645c99-32f4-4f96-b1bf-1dc11a0a41e6",
"name": "Sticky Note6"
},
{
"parameters": {
"content": "## Timeout and retry\n\nDetermines whether polling has exceeded the maximum number of attempts, raises a timeout error if needed, or updates state to continue polling.",
"width": 640,
"height": 320,
"color": 7
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
2048,
848
],
"id": "65f1bc33-fe8d-4996-ab7c-d3ac248ff3cc",
"name": "Sticky Note7"
}
],
"connections": {
"manualTrigger": {
"main": [
[
{
"node": "setFields",
"type": "main",
"index": 0
}
]
]
},
"setFields": {
"main": [
[
{
"node": "submitTask",
"type": "main",
"index": 0
}
]
]
},
"submitTask": {
"main": [
[
{
"node": "saveTaskId",
"type": "main",
"index": 0
}
]
]
},
"saveTaskId": {
"main": [
[
{
"node": "waitInterval",
"type": "main",
"index": 0
}
]
]
},
"waitInterval": {
"main": [
[
{
"node": "pollTask",
"type": "main",
"index": 0
},
{
"node": "carryState",
"type": "main",
"index": 0
}
]
]
},
"pollTask": {
"main": [
[
{
"node": "mergeResults",
"type": "main",
"index": 0
}
]
]
},
"carryState": {
"main": [
[
{
"node": "mergeResults",
"type": "main",
"index": 1
}
]
]
},
"mergeResults": {
"main": [
[
{
"node": "mergeState",
"type": "main",
"index": 0
}
]
]
},
"mergeState": {
"main": [
[
{
"node": "ifCompleted",
"type": "main",
"index": 0
}
]
]
},
"ifCompleted": {
"main": [
[
{
"node": "outputResult",
"type": "main",
"index": 0
}
],
[
{
"node": "ifFailed",
"type": "main",
"index": 0
}
]
]
},
"ifFailed": {
"main": [
[
{
"node": "failNode",
"type": "main",
"index": 0
}
],
[
{
"node": "ifTimeout",
"type": "main",
"index": 0
}
]
]
},
"ifTimeout": {
"main": [
[
{
"node": "timeoutFail",
"type": "main",
"index": 0
}
],
[
{
"node": "continuePolling",
"type": "main",
"index": 0
}
]
]
},
"continuePolling": {
"main": [
[
{
"node": "waitInterval",
"type": "main",
"index": 0
}
]
]
}
},
"settings": {},
"staticData": null
}