HiAPI
Blog

Tutoriale

Chiamare l'API text-to-video di HappyHorse 1.1 tramite HiAPI: un tutorial funzionante con curl + Python

Jun 27, 2026
Chiamare l'API text-to-video di HappyHorse 1.1 tramite HiAPI: un tutorial funzionante con curl + Python
Modello
happyhorse-1.1

HappyHorse 1.1 è il modello text-to-video di Alibaba: supporta clip video a 720p / 1080p, con durata da 3 a 15 secondi e genera audio nativo con una singola chiamata (nessun passaggio separato per la colonna sonora). HiAPI espone questo modello tramite lo stesso endpoint asincrono unificato di tutti gli altri modelli generativi, quindi se hai già chiamato modelli di immagini su /v1/tasks, l'unica cosa che cambia è l'id del modello e alcuni campi di input.

Questa pagina fornisce il minimo indispensabile per realizzare un'integrazione funzionante: lo schema esatto, curl copiabili direttamente, un client Python con polling e il pattern di callback per la produzione. Inoltre segnala due cose poco ovvie che il modello non accetta (un interruttore audio e un seed), così non sprecherai una richiesta per un errore 400.

Prerequisiti. Ottieni una chiave dalla console HiAPI ed esportala come HIAPI_API_KEY. Ogni richiesta si autentica tramite Authorization: Bearer sk-…; per un ripasso, consulta Authentication.

Endpoint e struttura della richiesta

Tutto passa attraverso un unico endpoint:

POST https://api.hiapi.ai/v1/tasks
Authorization: Bearer sk-<your-key>
Content-Type: application/json

Il corpo della richiesta ha tre chiavi di primo livello:

  • model — happyhorse-1.1/text-to-video (id letterale del modello — la barra va mantenuta).
  • input — campi specifici del modello. Per HappyHorse 1.1 T2V:
    • prompt (stringa, obbligatorio) — descrive la clip video.
    • resolution (720p | 1080p, predefinito 1080p).
    • aspect_ratio (16:9 | 9:16 | 3:4 | 4:3 | 4:5 | 5:4 | 1:1 | 9:21 | 21:9, predefinito 16:9).
    • duration (intero, 3–15, predefinito 5). Il costo aumenta con i secondi.
  • callback (facoltativo, oggetto) — endpoint HTTPS in callback.url + callback.when: "final". HiAPI invierà a quell'indirizzo esattamente una POST con il risultato finale per ogni task.

Due cose che sembrano dovrebbero funzionare ma non funzionano:

  • ❌ Nessun campo audio. L'audio viene generato nativamente insieme al video; non esiste un interruttore. Inviare "audio": true restituisce additional properties 'audio' not allowed.
  • ❌ Nessun campo seed. Restituisce anch'esso 400. Se ti serve determinismo per un batch, genera più versioni e scegli — non c'è una leva seed da regolare.

Un corpo di richiesta minimo valido:

{
  "model": "happyhorse-1.1/text-to-video",
  "input": {
    "prompt": "Un golden retriever che corre su una spiaggia, slow motion, onde delicate, toni caldi del tramonto",
    "resolution": "1080p",
    "aspect_ratio": "16:9",
    "duration": 5
  }
}

Esempio minimo funzionante: curl

Crea il task — la risposta torna subito e contiene solo un taskId:

curl -sS -X POST https://api.hiapi.ai/v1/tasks \
  -H "Authorization: Bearer $HIAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "happyhorse-1.1/text-to-video",
    "input": {
      "prompt": "Un lago tra le montagne innevate nella nebbia mattutina, lenta carrellata in avanti, luce cinematografica calda",
      "resolution": "1080p",
      "aspect_ratio": "16:9",
      "duration": 5
    }
  }'
# => {"code":200,"data":{"taskId":"tk-hiapi-01KW3..."},"message":"success"}

Poi esegui il polling fino allo stato terminale:

TASK_ID=tk-hiapi-01KW3...

curl -sS "https://api.hiapi.ai/v1/tasks/$TASK_ID" \
  -H "Authorization: Bearer $HIAPI_API_KEY"
# finché .data.status è "handling", attendi qualche secondo e riprova.
# In caso di successo:
# {
#   "code": 200,
#   "data": {
#     "status": "success",
#     "model": "happyhorse-1.1/text-to-video",
#     "output": [
#       {"type":"video","url":"https://temp.hiapi.ai/.../...-0.mp4","expireAt":1783130616}
#     ],
#     ...
#   }
# }

L'URL dell'mp4 è temporaneo (expireAt è un timestamp Unix a circa 7 giorni di distanza). Scarica e salva in modo persistente subito dopo il successo del task — non usare hotlink. Se preferisci che HiAPI gestisca l'archiviazione a lungo termine, consulta la documentazione Output Storage per capire come promuovere gli output dall'archiviazione temporanea a quella persistente.

Python: un client compatto e orientato alla produzione

Un client reale richiede tre cose: una create_task che restituisce l'id, una wait_task che esegue il polling con una scadenza e un passaggio di download. Questo scheletro include tutti e tre e si avvicina al punto di partenza della pagina Python SDK di HiAPI — mantienilo compatto ed estendilo da lì.

# pip install requests
import os, time, json, requests

API_BASE = "https://api.hiapi.ai/v1/tasks"
HEADERS = {"Authorization": f"Bearer {os.environ['HIAPI_API_KEY']}"}


def create_task(prompt: str, *, resolution="1080p", aspect_ratio="16:9", duration=5) -> str:
    body = {
        "model": "happyhorse-1.1/text-to-video",
        "input": {
            "prompt": prompt,
            "resolution": resolution,
            "aspect_ratio": aspect_ratio,
            "duration": duration,
        },
    }
    r = requests.post(API_BASE, headers={**HEADERS, "Content-Type": "application/json"},
                      data=json.dumps(body), timeout=60)
    r.raise_for_status()
    data = r.json()
    if data.get("code") != 200:
        raise RuntimeError(f"create failed: {data}")
    return data["data"]["taskId"]


def wait_task(task_id: str, *, timeout_s: int = 600, poll: int = 5) -> dict:
    deadline = time.time() + timeout_s
    while time.time() < deadline:
        r = requests.get(f"{API_BASE}/{task_id}", headers=HEADERS, timeout=30)
        r.raise_for_status()
        task = r.json().get("data") or {}
        status = task.get("status")
        if status == "success":
            return task
        if status == "fail":
            raise RuntimeError(f"task {task_id} failed: {task.get('error')}")
        time.sleep(poll)
    raise TimeoutError(f"task {task_id} did not finish within {timeout_s}s")


def download(url: str, path: str) -> None:
    with requests.get(url, stream=True, timeout=120) as r:
        r.raise_for_status()
        with open(path, "wb") as f:
            for chunk in r.iter_content(1 << 14):
                f.write(chunk)


if __name__ == "__main__":
    task_id = create_task(
        "Una strada al neon di notte dopo la pioggia, riflessi sul terreno, "
        "atmosfera cyberpunk, lenta panoramica",
        resolution="720p", aspect_ratio="9:16", duration=5,
    )
    task = wait_task(task_id)
    url = task["output"][0]["url"]
    download(url, "out.mp4")
    print("saved out.mp4")

Alcune note per la produzione:

  • Campo di stato. Considera in corso qualsiasi valore diverso da success o fail (la piattaforma attualmente usa handling).
  • raise_for_status non basta. Per alcuni errori di validazione HiAPI restituisce HTTP 200 ma con code diverso da 200 — controlla sempre anche data["code"]. Per una nuova integrazione, il caso più comune è 401 permission_denied, che indica un bearer token errato o mancante — riesporta HIAPI_API_KEY e verifica nella console.

Produzione: preferisci i callback al polling

Per qualsiasi scenario oltre alla guida rapida, fornisci a HiAPI un webhook affinché ti chiami al completamento del task:

{
  "model": "happyhorse-1.1/text-to-video",
  "input": {
    "prompt": "Un lago tra le montagne innevate nella nebbia mattutina, lenta carrellata in avanti, luce cinematografica calda",
    "resolution": "1080p",
    "aspect_ratio": "16:9",
    "duration": 5
  },
  "callback": {
    "url": "https://your-domain.com/hiapi/callback",
    "when": "final"
  }
}

Assicurati che il tuo gestore di callback faccia quanto segue:

  • Deduplica per taskId. Sia success che fail sono stati terminali — il tuo servizio deve trattare due ricezioni dello stesso taskId come no-op (scrittura idempotente con chiave taskId).
  • Rispondi rapidamente con un 2xx. Sposta il lavoro pesante (download dell'mp4, persistenza, notifica all'utente) in una coda. Il gestore del webhook dovrebbe confermare entro pochi secondi.
  • Mantieni GET /v1/tasks/:id come fallback. Se un webhook va perso (deployment, instabilità di rete), un job di riconciliazione pianificato che recupera per id i task bloccati e applica lo stesso gestore è la rete di sicurezza più semplice.

Se devi scegliere un solo percorso: il polling va bene per script una tantum e debug locale, mentre ovunque ci sia traffico reale dovresti usare i callback.

Scegliere i parametri giusti (resolution × aspect_ratio × duration)

Esigenza resolution aspect_ratio duration
Clip verticale per social media, costo minimo 720p 9:16 5
Anteprima quadrata / loop per miniatura 720p 1:1 3
Narrazione orizzontale / spot pubblicitario 1080p 16:9 5–8
Clip key visual widescreen 1080p 21:9 8–12

Il costo aumenta con risoluzione e durata — per il prezzo esatto al secondo consulta la pagina prezzi di HiAPI. Quando non sei sicuro del valore corretto, non specificarlo: resolution predefinito è 1080p, aspect_ratio predefinito è 16:9, duration predefinito è 5.

Domande frequenti

Il text-to-video di HappyHorse 1.1 ha un parametro seed? No. L'API rifiuta seed con additional properties 'seed' not allowed. Se ti servono più opzioni tra cui scegliere, invia diversi task con lo stesso prompt — esecuzioni diverse producono naturalmente variazioni.

Come si attiva o disattiva l'audio? Non puoi — HappyHorse 1.1 genera la traccia audio nativamente nella stessa chiamata. Non c'è un interruttore audio nello schema; inviarlo restituisce 400. Se ti serve una clip muta, rimuovi l'audio in post-produzione.

Quali sono le durate valide? Un intero da 3 a 15 (secondi). Qualsiasi valore fuori da questo intervallo restituisce duration: minimum: got 0, want 3 o duration: maximum: got 20, want 15. Anche i decimali vengono rifiutati (il campo è di tipo intero).

Quali proporzioni supporta? Nove: 16:9, 9:16, 3:4, 4:3, 4:5, 5:4, 1:1, 9:21, 21:9. Il valore predefinito è 16:9.

Per quanto tempo resta valido output[].url? Circa una settimana — la risposta contiene un timestamp Unix expireAt. Scarica subito l'mp4 e ri-ospitalo (S3, R2, il tuo CDN), oppure promuovilo ad archiviazione persistente tramite la Output Storage API.

E il image-to-video? HappyHorse 1.1 ha una variante I2V sullo stesso endpoint — consulta HappyHorse 1.1 I2V. Stessa autenticazione, stesso ciclo di vita asincrono, schema input diverso.

Dove trovo il riferimento completo dell'API asincrona? L'involucro della richiesta è in Create Task, l'endpoint di polling in Get Task Detail e lo schema di input canonico nella pagina del modello HappyHorse 1.1 T2V. Se parti da zero, la Quickstart ti accompagna end-to-end nella prima chiamata.

Inizia a creare con artefatti IA persistenti

Ottieni la tua chiave API e chiama modelli di immagini, video e audio tramite un'unica API basata sui task.

Leggi la documentazione API