Text to Video
Generate a video from a prompt alone (Seedance 2.5 text_to_video).
Seedance 2.5 generates a video from a prompt alone, with no images, video or audio.
Create a task
https://api.nanoapi.ai/v1/tasksUse the shared create endpoint with model: "seedance-2.5". It usually responds in under 1 second and the cost is frozen within a few seconds; the video usually takes several minutes. Get the result once the task has finished.
Headers
| Header | Required | Description |
|---|---|---|
Authorization | Yes | Bearer <API key>, see Authentication. |
Content-Type | Yes | application/json |
Idempotency-Key | No | A unique string for every new task, ideally a UUID (1–255 characters). See Preventing duplicate tasks. |
Body
| Parameter | Type | Required | Description |
|---|---|---|---|
model | string | Yes | seedance-2.5. |
mode | string | Yes | text_to_video. |
prompt | string | Yes | What to generate, at most 8000 characters. |
resolution | string | Yes | 480p, 720p or 1080p. Sets the price. |
aspect_ratio | string | Yes | auto, 21:9, 16:9, 4:3, 1:1, 3:4 or 9:16. There's nothing to follow in this mode, so auto gives 16:9. |
duration | integer | Yes | Output length in seconds, 4–30. It's what you pay for, see Pricing. |
generate_audio | boolean | No | Whether the output has sound, default true. Same price either way. |
webhook_url | string | No | Notified when the task succeeds or fails: https, up to 2048 characters, not a private, loopback or reserved address. See Webhooks. |
image_urls, video_url, video_urls and audio_urls aren't accepted: sending any of them returns 400 invalid_request with param set to it (for example image_urls is not allowed for mode text_to_video).
A 5-second 16:9 clip at 720p:
curl https://api.nanoapi.ai/v1/tasks \
-H "Authorization: Bearer $NANOAPI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "seedance-2.5",
"mode": "text_to_video",
"prompt": "A red fox trotting through a snowy pine forest at dawn",
"aspect_ratio": "16:9",
"resolution": "720p",
"duration": 5
}'Response: 200 OK. data is the newly created task, with only these fields; each one is described in Create a task: Response. Keep data.id to get the result: once the task succeeds, the video is at data.outputs[0].url of the retrieved task or the webhook. The task can still fail after it's created (for example if your balance can't cover it), so go by what retrieving the task or the webhook tells you.
{
"code": 200,
"message": "success",
"data": {
"object": "task",
"id": "tk_01jbd2s8x4c6v9b3n5m7q1w4e8",
"model": "seedance-2.5",
"status": "queued",
"error": null,
"created_at": "2026-10-31T08:30:00Z"
}
}Pricing
cost = duration × price per second of the resolutionLoading the current prices…
Example: the request above (720p, 5 seconds) freezes 5 × the 720p price per second and is charged the same when it succeeds, with or without sound.
Billed seconds are the duration you ask for. Prices change, so read the current ones from GET /v1/products (the prices rows whose mode is this mode) instead of hard-coding them; billing.frozen on the retrieved task is what counts. All Seedance 2.5 prices: Seedance 2.5 → Pricing.
Errors
Create request errors: the request fails with an HTTP error and no task is created. Specific to this mode:
| Status | error.type | When | What to do |
|---|---|---|---|
400 | invalid_request | prompt is missing (prompt is required for mode text_to_video), image_urls, video_url, video_urls or audio_urls was sent, or resolution, aspect_ratio or duration isn't one of the values above. param names the parameter. | Fix the parameter param names and send the request again. |
Other errors of the create endpoint (401, 402, 429 and so on): Create a task → Errors.
Task failures: the create request succeeded (200) and the task later turned failed. There's no HTTP status: the reason is the task's error.type, from retrieving the task or the webhook.
This mode has no failure reasons of its own.
Failure reasons shared by every mode (such as a balance too low for the task): Seedance 2.5 → Errors; all of them: Failure reasons.