A standalone, production-quality starter kit for overseas developers who want to build on supported Seedance text-to-video and image-to-video workflows through the Vancine API.
This repository contains only developer-facing integration assets: copyable examples, importable collections, and an automation workflow. It is intentionally small, language-agnostic at the protocol level, and designed to be verified offline.
Vancine provides access to supported Seedance workflows through its documented asynchronous API. New accounts receive $1 in free credit and no credit card is required to register.
Published Postman documentation: https://documenter.getpostman.com/view/56666133/2sBY4Mv2Nf
The public Collection ships with an empty api_key on purpose. To make a real
request, fork the Collection first, then fill in your API key through your own
private (forked) or local variable. Never save a real key into the public or any
shared Collection. New accounts receive $1 in free credit and no credit
card is required to register.
A general product landing page tells you that an API exists. This repository is meant to help you make a working request as quickly as possible:
- Submit a Seedance video task and get a
task_id. - Poll the task status with bounded retries.
- Handle success, failure, and timeout explicitly.
- Retrieve the result URL.
If you can run one of the examples end to end, the integration path works.
- Vancine Seedance page: https://vancine.com/seedance-api?utm_source=github&utm_medium=developer_resource&utm_campaign=seedance_starter_kit&utm_content=readme
- Documentation: https://vancine.com/docs#video
- Pricing: https://vancine.com/pricing
- API status: https://vancine.com/api/status
Seedance requests use an asynchronous submit-and-poll workflow. Each request requires an API key sent as a bearer token.
POST /v1/video/generations
-> { "task_id": "...", "status": "queued" }
GET /v1/video/generations/{task_id}
-> queued -> in_progress -> completed | failed
-> result URL once terminal
The submit call returns a task_id. You then poll the status endpoint on a
fixed interval until it reaches a terminal state. Under normal conditions a
video task completes within seconds to a few minutes depending on the model and
payload, but your code must treat polling as bounded: a configurable
interval, a maximum number of attempts or maximum wait time, and a clear exit
for failure and timeout.
Requests are authenticated with an API key generated from the Vancine console:
Authorization: Bearer $VANCINE_API_KEYREADME.md Product + integration guide
.env.example Environment variable template
.gitignore Default ignores
LICENSE MIT License (examples)
SECURITY.md Reporting and handling guidance
examples/
curl/
generate.sh Submit + poll from the shell
node/
package.json Node example (ESM, native fetch)
generate.mjs Submit + poll, importable functions
generate.test.mjs Offline unit tests (node:test)
python/
requirements.txt Runtime dependency (requests)
generate.py Submit + poll, importable functions
test_generate.py Offline unit tests (unittest)
postman/
Vancine-Seedance.postman_collection.json Importable Seedance requests
n8n/
vancine-seedance-workflow.json Importable async workflow
scripts/
validate-assets.mjs Structure + link + secret checks
Every example reads the API key from the environment. Copy the template first:
cp .env.example .env
# then edit .env and set VANCINE_API_KEYTo run the examples with the values from .env, load the file with set -a
(so every assignment is auto-exported to the environment) before running any
example, all from the repository root:
set -a
source .env
set +a| Variable | Required | Description |
|---|---|---|
VANCINE_API_KEY |
yes | API key from the Vancine console |
VANCINE_BASE_URL |
no | Override base URL (defaults to https://vancine.com) |
SEEDANCE_MODEL |
no | Model id (defaults to Doubao-Seedance-1.5-pro) |
POLL_INTERVAL_SECONDS |
no | Seconds between polls (default 5) |
POLL_MAX_ATTEMPTS |
no | Maximum poll attempts (default 120) |
chmod +x examples/curl/generate.sh
./examples/curl/generate.shPrerequisites: curl, jq. The script is written for bash, checks both
dependencies, exits cleanly on any non-2xx response, and never prints the
full API key.
cd examples/node
npm install
node cli.mjsRequirements: Node.js 18+. The example uses native fetch and has no runtime
dependencies beyond the Node standard library.
The code is split into two files on purpose:
examples/node/generate.mjsholds all param-driven, unit-testable logic (parsing, polling, network calls that takeapiKeyas a parameter). It never reads the environment, so it can be imported in tests without side effects.examples/node/cli.mjsis the runnable entrypoint: it readsVANCINE_API_KEYfrom the environment and calls intogenerate.mjs.
Functions are written to be imported and tested without network access:
import {
submitTask,
extractTaskId,
extractStatus,
extractResultUrl,
generateVideo,
} from "./generate.mjs";Run the offline unit tests (these exercise generate.mjs only):
node --testcd examples/python
pip install -r requirements.txt
python generate.pyRequirements: Python 3.10+, requests. Parsing and polling logic is split into
importable functions that can be tested without network access:
from generate import submit_task, fetch_task, extract_task_id, extract_status, extract_result_urlRun the offline unit tests:
python -m unittest test_generate.py -vThe collection is in
postman/Vancine-Seedance.postman_collection.json
and uses the v2.1 format.
It defines collection variables so you do not have to repeat shared values:
| Variable | Default | Purpose |
|---|---|---|
base_url |
https://vancine.com |
API host |
api_key |
(empty — set this first) | API credential |
model |
Doubao-Seedance-1.5-pro |
Example model |
task_id |
(empty) | Set automatically |
The collection contains two requests:
- Submit Seedance Video —
POST {{base_url}}/v1/video/generations - Get Video Task Status —
GET {{base_url}}/v1/video/generations/{{task_id}}
- Open Postman.
- Choose Import in the top left.
- Select the
Vancine-Seedance.postman_collection.jsonfile. - Open the collection, open the Variables tab, and set
api_keyto your key. - Send Submit Seedance Video first.
After a successful submit, the test script on the submit request saves the task
id into the task_id collection variable. The saved value comes from the first
present field in this order: task_id, id, data.task_id, data.id. You can
then send Get Video Task Status to poll the result. Set a bounded polling
loop in your own test runner rather than relying on a single manual send.
The collection ships with an empty api_key and contains no credential.
The workflow is in
n8n/vancine-seedance-workflow.json and
uses standard n8n nodes: Manual Trigger, Set/Edit Fields, two HTTP Request
nodes, Wait, IF, Merge, and a Code node (for state merging only — no network).
It expresses the same submit-and-poll lifecycle:
setFields
-> submitTask (HTTP Request + Header Auth)
-> saveTaskId (Set: extract task_id, carry config)
-> waitInterval
-> pollTask (HTTP Request + same Header Auth)
-> mergeState (Code: merge response + carried state, increment poll_index)
-> completed -> output result URL
-> failed -> stop with error (shows saved task_id + reason)
-> timeout -> stop (poll_index >= maxPolls)
-> otherwise -> continue polling (bounded loop back to waitInterval)
Both submitTask and pollTask are real HTTP Request nodes that use generic Header Auth. You must assign the same Header Auth credential to both nodes after import — the Code node never makes network requests.
Loop state (task_id, poll_index, maxPolls, base_url) is carried on
execution-scoped items via a Merge node (append mode) that combines the HTTP
poll response with a parallel state-carrying Set node. This avoids n8n's stale
$('NodeName') cross-node references inside loops and does not rely on global
workflow staticData, so concurrent executions never overwrite each other's
state.
A base_url field (default https://vancine.com) in the Set node is used by
both HTTP Request nodes. No change is needed for production use.
Like the other examples, maxPolls defaults to 120 at a 5-second interval —
about 10 minutes maximum — and stays user-configurable while the polling loop
remains strictly bounded (poll_index >= maxPolls stops it; there is no
infinite loop).
Verified in real n8n 2.30.4 against a local mock that enforces
Authorization: Beareron every request. All branches confirmed:completed(2 polls, correctresult_url),failed(1 poll, error with savedtask_id),timeoutwithmaxPolls=3(exactly 3 GETs, no 4th, no infinite loop). Two overlapping concurrent executions used differenttask_ids with no cross-contamination. Imports cleanly into a fresh, empty n8n database.
- In n8n, open Workflows -> Import from File.
- Select
vancine-seedance-workflow.json. - Create one HTTP Header Auth credential:
- Name:
Authorization - Value:
Bearer <YOUR_VANCINE_API_KEY>
- Name:
- Assign that same credential to both HTTP Request nodes
(
submitTaskandpollTask). - The
base_urlfield defaults tohttps://vancine.com— no change needed. - Update
model,prompt, andsizeon the Set node as needed, then run.
The Vancine API has grown across a few response shapes. These examples are written to accept both the current and the legacy shapes so they keep working without code changes when the upstream response format is normalized.
Resolved from the first present value in this order:
- top-level
task_id - top-level
id data.task_iddata.id
The values below are treated as terminal:
| Current API | Legacy upstream | Meaning |
|---|---|---|
queued |
— | Waiting |
in_progress |
IN_PROGRESS |
Running |
completed |
SUCCESS |
Done |
failed |
FAILURE |
Failed |
Examples treat completed/SUCCESS as success and failed/FAILURE as a
failure.
Resolved from the first present value in this order:
metadata.urldata.result_urldata.data.content.video_url
| Situation | HTTP | Typical body | What to do |
|---|---|---|---|
| Authentication failed | 401 | error.message about the key or endpoint |
Verify the key and that you POST to /v1/video/generations, not a chat or TTS path |
| Insufficient balance | 402 / 400 | error.message about balance or quota |
Top up in the console or check your remaining credit |
| Invalid model or payload | 400 | error.message about model, prompt, size, etc. |
Check the model id and required parameters |
| Task failure | 200 | terminal failed/FAILURE, error.message or data.fail_reason |
Read the reason and adjust the prompt or inputs |
| Polling timeout | — | no terminal state within the bounded window | Stop polling; report the task_id for debugging |
| Non-2xx poll response | 4xx/5xx | transport-level error | Stop; do not keep looping |
Rules the examples follow:
- A bounded polling loop with a configurable interval and a maximum attempt count. No infinite loop.
- Clear, distinct handling for submission error, authentication error, insufficient balance, task failure, and timeout.
- The full API key is never printed to logs or output.
- Always pass the API key through an environment variable. Never hard-code it.
- This repository ships with example prompts only; no real credential is committed. See SECURITY.md for how to report a vulnerability or a committed secret.
- Rotate the key from the Vancine console if you believe it is exposed.
This starter kit documents access to supported Seedance workflows. It does not guarantee:
- cheapest pricing
- unlimited or unrestricted usage
- guaranteed uptime
- guaranteed output for every prompt
- any safety-filter bypass
Vancine does not bypass model safety requirements. Model capabilities, input requirements, availability, and safety behavior follow their documented requirements. Model pricing and limits can change; the live pricing page and API documentation remain authoritative.
The example code in this repository is released under the MIT License.
The Seedance name and its underlying models are trademarks of their respective owners. This starter kit is an independent integration example and is not an official product of, or partnership with, those providers.