Generación de vídeo
POST /v1/videos · GET /v1/videos/{id} · DELETE /v1/videos/{id}
Genera vídeos cortos a partir de un prompt de texto, opcionalmente guiados por fotogramas de referencia (primero/último). Es una API de jobs asíncronos con la forma estándar create + poll: POST /v1/videos crea una tarea que responde en ~2 segundos, la sondeas hasta que termina, y la cabecera Prefer: wait convierte las generaciones rápidas en una sola llamada síncrona. Modelos Seedance, una única clave de API, la misma facturación que el resto de endpoints.
La API de vídeo está en preview limitada (pruebas por invitación). Los modelos aparecen en el catálogo y en los precios, pero crear tareas requiere que tu espacio de trabajo esté en la lista de permitidos — contáctanos para habilitarlo.
Endpoints y ciclo de vida de la tarea
Un recurso de tarea, cuatro operaciones. Una tarea pasa de queued → in_progress → un estado terminal: completed, failed o cancelled. La respuesta de creación incluye enlaces status_url / cancel_url listos para usar — nunca montas URLs a mano.
| Endpoint | Descripción |
|---|---|
POST /v1/videos | Crea una tarea de generación. Responde en ~2 s con el objeto de tarea (status queued) y los enlaces de sondeo. |
GET /v1/videos/{id} | Sondea la tarea. En completed obtienes data[0].url, usage.completion_tokens y los parámetros realmente aplicados; en failed un error estructurado con el código y el mensaje del proveedor. |
DELETE /v1/videos/{id} | Cancela la tarea. Solo las tareas queued pueden cancelarse; una tarea cancelada nunca se factura. |
GET /v1/videos/models | Lista los modelos de vídeo disponibles para tu clave, con las restricciones de resolución/duración y los precios de cada modelo. |
Azúcar síncrono — Prefer: wait
Añade una cabecera Prefer: wait o Prefer: wait=N (N acotado a 1..60 segundos) a la llamada de creación y el gateway mantiene la petición abierta. Si la tarea termina dentro de la ventana, recibes directamente el objeto terminal — con URL del vídeo y usage, sin polling. Si no llega a tiempo, la llamada se degrada con elegancia: recibes el objeto de estado actual (sin error, la tarea sigue en marcha) y continúas con el polling normal.
Cuerpo de la solicitud
| Parámetro | Tipo | Descripción |
|---|---|---|
model* | string | El modelo de vídeo a usar (p. ej. seedance-1-5-pro-251215). Lista todos los modelos disponibles vía GET /v1/videos/models. |
prompt* | string | Descripción en texto del vídeo deseado. |
image | string | string[] | Entrada image-to-video: una imagen = primer fotograma, dos imágenes = primer + último fotograma. Cada entrada es un data URI o una URL https. |
resolution | string | Resolución de salida: 480p, 720p, 1080p o 4k. El conjunto soportado varía por modelo — ver la tabla de modelos. |
ratio | string | Relación de aspecto: 16:9, 4:3, 1:1, 3:4, 9:16, 21:9 o adaptive. |
duration | integer | Duración del clip en segundos (rango por modelo dentro de 2..15). Algunos modelos también aceptan -1 para que el modelo elija. |
seed | integer | Seed opcional para salida reproducible (donde se soporte). |
watermark | boolean | Si se renderiza la marca de agua del proveedor. |
generate_audio | boolean | Generar pista de audio (true por defecto). En modelos con tarifa doble cambia el precio — ver la tabla de modelos. |
Modelos disponibles
La disponibilidad de modelos depende de tu despliegue. Obtén la lista en vivo y consciente del cumplimiento — con las restricciones de resolución/duración y los precios de cada modelo — vía GET /v1/videos/models. La alineación actual:
| Modelo | Resoluciones | Duración | Precio | Notas |
|---|---|---|---|---|
dreamina-seedance-2-0-260128 | 480p · 720p · 1080p · 4k | 4–15 s | 480p/720p $7.0 · 1080p $7.7 · 4k $4.0 | Buque insignia 2.0; hasta 4K |
dreamina-seedance-2-0-fast-260128 | 480p · 720p | 4–15 s | $5.6 | Variante 2.0 más rápida |
dreamina-seedance-2-0-mini-260615 | 480p · 720p | 4–15 s | $3.5 | Variante 2.0 más pequeña |
seedance-1-5-pro-251215 | 480p · 720p · 1080p | 4–12 s | $2.4 audio · $1.2 muted | Tarifa según generate_audio |
seedance-1-0-pro-fast-251015 | 480p · 720p · 1080p | 2–12 s | $1.0 | El más barato |
Precio: USD por 1M de video tokens. seedance-1-5-pro-251215 factura $2.4 con la pista de audio activada (generate_audio: true, el valor por defecto) y $1.2 sin ella; el resto de modelos cobra una tarifa única por tramo de resolución.
Video tokens y precios
El vídeo se factura en video tokens, derivados de la salida real: tokens ≈ ancho × alto × 24 fps × segundos / 1024. Las tarifas son por 1M de video tokens y siguen los parámetros realmente aplicados (devueltos en la tarea completed) — así, ratio: "adaptive" y duration: -1 se facturan por lo que el modelo produjo realmente.
Referencias intuitivas en seedance-1-5-pro-251215 con audio: un clip 480p / 16:9 / 4 s ≈ 40,6K video tokens ≈ $0.10; uno de 720p / 5 s ≈ 108,9K tokens ≈ $0.26.
Facturación
Solo se factura en caso de éxito: el cargo ocurre una única vez, cuando la tarea alcanza completed por primera vez, según el usage de video tokens devuelto. Las tareas fallidas (incluidos los rechazos de moderación de contenido) y las canceladas nunca se facturan — el error del proveedor se transmite tal cual.
El data[0].url devuelto es una URL prefirmada del proveedor que caduca en ~24 horas — descárgalo pronto y realoja el archivo en tu propio almacenamiento si lo necesitas a largo plazo.
Ejemplo — curl, en un solo paso (Prefer: wait)
curl https://synthorai.io/v1/videos \
-H "Authorization: Bearer $SYNTHORAI_API_KEY" \
-H "Content-Type: application/json" \
-H "Prefer: wait=60" \
-d '{
"model": "seedance-1-0-pro-fast-251015",
"prompt": "A corgi puppy chasing a butterfly across a meadow, cinematic",
"resolution": "480p",
"ratio": "16:9",
"duration": 4
}'
# Finished inside the wait window → the terminal object comes straight back:
{
"id": "vid_6091d8d1af805818b1470488",
"object": "video",
"model": "seedance-1-0-pro-fast-251015",
"status": "completed",
"data": [{ "url": "https://…tos….mp4?…" }],
"usage": { "completion_tokens": 40594, "total_tokens": 40594 },
"resolution": "480p", "ratio": "16:9", "duration": 4, "fps": 24,
"seed": 34142
}
# Not done in time → the current status object is returned instead (no error,
# the task keeps running) — continue polling status_url as usual. Ejemplo — curl, create + poll
# 1) Create — returns in ~2 s with a queued task object
curl https://synthorai.io/v1/videos \
-H "Authorization: Bearer $SYNTHORAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "seedance-1-5-pro-251215",
"prompt": "A corgi puppy chasing a butterfly across a meadow, cinematic",
"resolution": "720p",
"duration": 5,
"generate_audio": true
}'
{
"id": "vid_6091d8d1af805818b1470488",
"object": "video",
"model": "seedance-1-5-pro-251215",
"status": "queued",
"created_at": 1784619862,
"status_url": "https://synthorai.io/v1/videos/vid_6091d8d1af805818b1470488",
"cancel_url": "https://synthorai.io/v1/videos/vid_6091d8d1af805818b1470488"
}
# 2) Poll until status is terminal (completed | failed | cancelled)
curl https://synthorai.io/v1/videos/vid_6091d8d1af805818b1470488 \
-H "Authorization: Bearer $SYNTHORAI_API_KEY"
{
"id": "vid_6091d8d1af805818b1470488",
"object": "video",
"model": "seedance-1-5-pro-251215",
"status": "completed",
"data": [{ "url": "https://…tos….mp4?…" }],
"usage": { "completion_tokens": 108900, "total_tokens": 108900 },
"resolution": "720p", "ratio": "16:9", "duration": 5, "fps": 24,
"seed": 34142, "generate_audio": true
}
# 3) Download the video — the URL is pre-signed (no auth header) and expires
# in ~24 h: fetch promptly and re-host if you need it long-term.
curl -o out.mp4 "https://…tos….mp4?…" Ejemplo — Python (requests)
import time
import requests
BASE = "https://synthorai.io/v1"
HEADERS = {"Authorization": "Bearer YOUR_API_KEY"}
task = requests.post(f"{BASE}/videos", headers=HEADERS, json={
"model": "seedance-1-5-pro-251215",
"prompt": "A corgi puppy chasing a butterfly across a meadow, cinematic",
"resolution": "720p",
"duration": 5,
}).json()
while task["status"] not in ("completed", "failed", "cancelled"):
time.sleep(5)
task = requests.get(task["status_url"], headers=HEADERS).json()
if task["status"] == "completed":
url = task["data"][0]["url"] # pre-signed, valid ~24 h — re-host promptly
with open("out.mp4", "wb") as f:
f.write(requests.get(url).content)
else:
print(task["error"]) # provider code + message, passed through verbatim Ejemplo — Node (fetch)
import fs from "node:fs";
const BASE = "https://synthorai.io/v1";
const HEADERS = { Authorization: `Bearer ${process.env.SYNTHORAI_API_KEY}` };
let task = await (await fetch(`${BASE}/videos`, {
method: "POST",
headers: { ...HEADERS, "Content-Type": "application/json" },
body: JSON.stringify({
model: "seedance-1-5-pro-251215",
prompt: "A corgi puppy chasing a butterfly across a meadow, cinematic",
resolution: "720p",
duration: 5,
}),
})).json();
while (!["completed", "failed", "cancelled"].includes(task.status)) {
await new Promise((r) => setTimeout(r, 5000));
task = await (await fetch(task.status_url, { headers: HEADERS })).json();
}
if (task.status === "completed") {
const url = task.data[0].url; // pre-signed, valid ~24 h — re-host promptly
fs.writeFileSync("out.mp4", Buffer.from(await (await fetch(url)).arrayBuffer()));
} else {
console.error(task.error); // provider code + message, passed through verbatim
} Idempotencia
Pasa una cabecera X-Idempotency-Key en la llamada de creación para que los reintentos sean seguros: una petición repetida con la misma clave devuelve 409 en lugar de crear (y facturar) una segunda tarea. La generación de vídeo es lenta y propensa a reintentos — esto evita cargos dobles.