HiAPI
Blog

Tutorial

Cómo usar veo-3.1-lite/text-to-video a través de la API de hiapi: curl, Python y una solicitud ejecutable

Aug 27, 2026
Cómo usar veo-3.1-lite/text-to-video a través de la API de hiapi: curl, Python y una solicitud ejecutable

veo-3.1-lite/text-to-video genera clips de vídeo cortos a partir de un único prompt de texto, sin necesidad de una imagen inicial. Esta guía ofrece ejemplos de curl y Python listos para copiar y pegar contra la API real de tareas de hiapi, el esquema de entrada exacto (verificado contra el endpoint en producción) y las formas de error que realmente encontrarás en producción.

1. Requisitos previos

  • Una cuenta de hiapi y una API key (sk-...) obtenida desde el panel de API Keys.
  • curl, o Python 3 con requests instalado (pip install requests).
  • No necesitas nada más: text-to-video solo requiere una cadena de prompt.

Todos los modelos de generación de hiapi funcionan a través de la misma API unificada de tareas asíncronas: POST /v1/tasks crea la tarea y luego se consulta mediante sondeo o se espera una callback para obtener el resultado. veo-3.1-lite/text-to-video se invoca exactamente igual que cualquier otro modelo de vídeo (mismas cabeceras de autenticación, mismo ciclo de vida de la tarea); solo cambian model e input. El id del modelo es veo-3.1-lite/text-to-video, con el sufijo /text-to-video; la misma familia también ofrece veo-3.1-lite/image-to-video, un id de modelo independiente para animar una imagen de origen en su lugar.

2. Ejemplo mínimo ejecutable

2.1 Crear una tarea (curl)

curl -s -X POST https://api.hiapi.ai/v1/tasks \
  -H "Authorization: Bearer sk-<your-api-key>" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "veo-3.1-lite/text-to-video",
    "input": {
      "prompt": "a paper boat drifting down a rain-slicked city street at night, neon signs reflecting on wet asphalt",
      "duration": 6,
      "resolution": "720p",
      "aspect_ratio": "16:9",
      "generate_audio": true
    }
  }'

Una llamada correcta devuelve inmediatamente un id de tarea; la generación es asíncrona:

{"code":200,"data":{"taskId":"tk-hiapi-01XXXXXXXXXXXXXXXXXXXXXXXX"},"message":"success"}

2.2 Consultar el resultado

curl -s https://api.hiapi.ai/v1/tasks/tk-hiapi-01XXXXXXXXXXXXXXXXXXXXXXXX \
  -H "Authorization: Bearer sk-<your-api-key>"

Mientras el clip se está renderizando, status es "handling". Cuando termina:

{
  "code": 200,
  "data": {
    "taskId": "tk-hiapi-01XXXXXXXXXXXXXXXXXXXXXXXX",
    "model": "veo-3.1-lite/text-to-video",
    "status": "success",
    "storage": "temp",
    "output": [
      {"artifactId": "...", "type": "video", "url": "https://temp.hiapi.ai/.../result.mp4", "expireAt": 1786932195}
    ]
  },
  "message": "success"
}

output[0].url es un enlace temporal que caduca: descarga el archivo antes de que expire expireAt (o transfiere la salida a un almacenamiento persistente).

2.3 Ejemplo completo en Python

import time
import requests

API_KEY = "sk-<your-api-key>"
BASE = "https://api.hiapi.ai/v1/tasks"
HEADERS = {"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"}


def create_task(prompt: str) -> str:
    resp = requests.post(BASE, headers=HEADERS, json={
        "model": "veo-3.1-lite/text-to-video",
        "input": {
            "prompt": prompt,
            "duration": 6,
            "resolution": "720p",
            "aspect_ratio": "16:9",
        },
    }, timeout=30)
    resp.raise_for_status()
    return resp.json()["data"]["taskId"]


def wait_for_result(task_id: str, poll_seconds: int = 5, timeout_seconds: int = 600) -> str:
    deadline = time.time() + timeout_seconds
    while time.time() < deadline:
        resp = requests.get(f"{BASE}/{task_id}", headers=HEADERS, timeout=30)
        resp.raise_for_status()
        data = resp.json()["data"]
        if data["status"] == "success":
            return data["output"][0]["url"]
        if data["status"] == "failed":
            raise RuntimeError(f"task {task_id} failed: {data}")
        time.sleep(poll_seconds)
    raise TimeoutError(f"task {task_id} did not finish in {timeout_seconds}s")


if __name__ == "__main__":
    tid = create_task("a paper boat drifting down a rain-slicked city street at night")
    video_url = wait_for_result(tid)
    print(video_url)

3. Esquema de entrada

Todos los campos siguientes van dentro de input. El esquema es estricto: enviar un campo inexistente devuelve 400 (additional properties '<field>' not allowed), lo que constituye una buena forma de validar rápidamente la solicitud antes del renderizado.

Campo Tipo Obligatorio Descripción
prompt string Sí Descripción de la escena; especifica el sujeto, el movimiento y el comportamiento de cámara.
duration integer No Uno de 4, 6 u 8 (segundos).
resolution string No "720p" o "1080p".
aspect_ratio string No "16:9" o "9:16".
generate_audio boolean No Incluye audio ambiente/efectos sincronizados en el renderizado.
negative_prompt string No Elementos de contenido que el renderizado debe evitar.
seed integer No Valor fijo para reproducir la misma composición/movimiento entre reintentos.

Duraciones más largas y resoluciones más altas aumentan el coste de renderizado; antes de escalar tareas por lotes, consulta la tarifa actual por modelo en la página de precios.

4. Patrones de producción

Prefiere callbacks al sondeo a gran escala

Para cualquier caso que vaya más allá de un script puntual, registra una callback en lugar de sondear en un bucle:

{
  "model": "veo-3.1-lite/text-to-video",
  "input": {"prompt": "..."},
  "callback": {"url": "https://your-app.example.com/webhooks/hiapi", "when": "final"}
}

callback.url debe ser una URL http(s) accesible, y when solo acepta "final": hiapi hará un único POST cuando la tarea alcance un estado terminal (success o failed). Esto evita desperdiciar cuota de solicitudes en bucles de sondeo y obtiene el resultado en el instante en que está listo, algo aún más importante para vídeo (el tiempo de renderizado es mayor que en la generación de imágenes).

Idempotencia y reintentos

Si tu ejecutor de tareas puede reintentar el envío (caídas, timeouts, redespliegues), registra tu propia clave de idempotencia junto con el taskId devuelto antes de realizar la solicitud, de modo que al reintentar puedas comprobar "¿ya envié esto?" en lugar de crear un renderizado duplicado y pagar dos veces por él.

Manejo de errores

En la práctica aparecen dos formas de error distintas:

  • Entrada incorrecta (400): errores de validación del cuerpo de la solicitud:
    {"code":400,"data":null,"error_code":"INVALID_REQUEST","message":"invalid input: prompt: missing required field \"prompt\""}
    
  • Fallo de autenticación/permisos (401): clave ausente, inválida o sin permisos suficientes:
    {"error":{"code":"permission_denied","message":"This API key cannot use the selected model...","request_id":"...","type":"hiapi_error"}}
    

Ramifica primero según el código de estado HTTP y luego revisa el cuerpo de la respuesta: 400 casi siempre significa un nombre de campo o un valor incorrecto (corrige la solicitud), mientras que 401 significa que la clave en sí requiere atención (permisos en el panel o una nueva clave).

5. Páginas relacionadas

Preguntas frecuentes

¿veo-3.1-lite/text-to-video necesita una imagen inicial? No. Genera completamente a partir de la cadena prompt. Si tienes una imagen de origen que quieres animar, usa en su lugar el id de modelo independiente veo-3.1-lite/image-to-video.

¿Qué resoluciones y duraciones se admiten? resolution es "720p" o "1080p"; duration es 4, 6 u 8 segundos. Enviar cualquier otro valor devuelve 400 con el conjunto de valores permitidos.

¿Los clips generados pueden incluir audio? Sí: establece "generate_audio": true en input para incluir audio ambiente/efectos sincronizados.

¿Cómo evito sondear en un bucle? Pasa un objeto callback con la url de tu webhook y "when": "final". hiapi hará un POST a esa URL cuando la tarea finalice, sin que tengas que revisar periódicamente GET /v1/tasks/<id>.

¿Por qué mi solicitud devuelve 401 en lugar de 400? Un 401 con error_code/code igual a "permission_denied" indica que la API key en sí no es válida o no tiene acceso a ese modelo; revisa el panel de API Keys. Un 400 indica que el cuerpo de la solicitud está mal formado para una clave que sí es válida.

¿La URL del vídeo devuelto es permanente? No: output[0].url es un enlace temporal con una marca de tiempo expireAt. Descárgalo antes de que caduque o transfiérelo a un almacenamiento persistente.

Artículos relacionados

Ver todos los artículos →

Empieza a crear con artefactos de IA persistentes

Consigue tu API key y llama a modelos de imagen, vídeo y audio a través de una única API basada en tasks.

Leer la documentación de la API