🎁 Nuevo Regístrate gratis, 10 llamadas de regalo. Hasta 1 $, sin tarjeta.

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 queuedin_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.

EndpointDescripción
POST /v1/videosCrea 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/modelsLista 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ámetroTipoDescripción
model*stringEl 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*stringDescripción en texto del vídeo deseado.
imagestring | 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.
resolutionstringResolución de salida: 480p, 720p, 1080p o 4k. El conjunto soportado varía por modelo — ver la tabla de modelos.
ratiostringRelación de aspecto: 16:9, 4:3, 1:1, 3:4, 9:16, 21:9 o adaptive.
durationintegerDuración del clip en segundos (rango por modelo dentro de 2..15). Algunos modelos también aceptan -1 para que el modelo elija.
seedintegerSeed opcional para salida reproducible (donde se soporte).
watermarkbooleanSi se renderiza la marca de agua del proveedor.
generate_audiobooleanGenerar 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:

ModeloResolucionesDuraciónPrecioNotas
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.