HiAPI
Blog

Tutoriale

Come usare seedance-2.0-fast tramite l'API hiapi: curl, Python e richieste eseguibili

Jul 2, 2026
Come usare seedance-2.0-fast tramite l'API hiapi: curl, Python e richieste eseguibili

Questa guida mostra la richiesta minima per generare un video con seedance-2.0-fast, tutti i campi di input che il modello accetta effettivamente e come attendere il risultato tramite polling o callback. Ogni struttura di richiesta e messaggio di errore riportato di seguito è stato verificato eseguendolo sull'API reale, quindi puoi copiare il codice e usarlo direttamente.

Cosa costruirai e cosa ti serve

L'obiettivo è uno solo: inviare un prompt testuale e ottenere in cambio un URL MP4 scaricabile. seedance-2.0-fast è la versione ottimizzata per la velocità di Seedance 2.0: rinuncia alla risoluzione massima (limite di 720p) in cambio di una generazione più rapida, ed è quindi ideale per anteprime, cicli di iterazione e clip brevi in grandi quantità.

Ti serve solo una cosa: una chiave API hiapi. Ottienila dalla tua dashboard; ha un formato simile a sk-.... Tutti i modelli video (compreso questo) sono serviti tramite un endpoint unificato per attività asincrone: prima esegui POST /v1/tasks per creare l'attività, poi recuperi il risultato tramite l'id dell'attività. Per i video non esiste una modalità sincrona.

Per il prezzo attuale di una singola clip consulta la pagina dei prezzi (il modello è appena stato lanciato, quindi fai riferimento a quella pagina e non fidarti di qualsiasi numero citato in articoli di blog).

Esempio minimo eseguibile (curl)

Crea l'attività:

curl -X POST "https://api.hiapi.ai/v1/tasks" \
  -H "Authorization: Bearer sk-YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "seedance-2.0-fast",
    "input": {
      "prompt": "Un battello di carta scivola lungo una strada bagnata dalla pioggia al crepuscolo, cinematografico, lento dolly-in",
      "duration": 5,
      "resolution": "720p",
      "aspect_ratio": "16:9"
    }
  }'

L'id dell'attività nella risposta si trova in data.taskId:

{
  "data": {
    "taskId": "task_abc123..."
  }
}

Interroga l'attività con polling finché lo stato non raggiunge lo stato finale:

curl "https://api.hiapi.ai/v1/tasks/task_abc123..." \
  -H "Authorization: Bearer sk-YOUR_KEY"

Quando data.status è "success", l'URL del video si trova in data.output[0].url. L'URL è firmato e scade: scarica subito il file, non usare hotlink:

curl -o clip.mp4 "<the output url>"

Tutti i campi di input (verificati)

Solo prompt è obbligatorio. Qualsiasi campo non presente in questa tabella viene rifiutato con 400: lo schema non ammette proprietà aggiuntive.

Campo Tipo Obbligatorio Valori accettati
prompt string Sì lunghezza minima 3 caratteri
duration intero No 4–15 (secondi)
resolution string No 480p, 720p
aspect_ratio string No 1:1, 4:3, 3:4, 16:9, 9:16, 21:9, adaptive

Due punti meritano una nota specifica:

  • duration è un intero, non una stringa. Inviare "duration": "5" fallisce la validazione con l'errore duration: got string, want integer.
  • Non è previsto alcun input immagine. seedance-2.0-fast supporta solo la generazione da testo a video; campi come image_urls vengono rifiutati dallo schema. Se ti serve la generazione da immagine a video, consulta la guida al flusso di lavoro API da immagine a video per scoprire i modelli che supportano questa funzione.

Lo stesso flusso in Python

Non serve un SDK: basta requests:

import time
import requests

API_BASE = "https://api.hiapi.ai/v1/tasks"
HEADERS = {
    "Authorization": "Bearer sk-YOUR_KEY",
    "Content-Type": "application/json",
}

def create_task(prompt: str, duration: int = 5,
                resolution: str = "720p", aspect_ratio: str = "16:9") -> str:
    payload = {
        "model": "seedance-2.0-fast",
        "input": {
            "prompt": prompt,
            "duration": duration,
            "resolution": resolution,
            "aspect_ratio": aspect_ratio,
        },
    }
    r = requests.post(API_BASE, json=payload, headers=HEADERS, timeout=60)
    r.raise_for_status()
    return r.json()["data"]["taskId"]

def wait_task(task_id: str, timeout_s: int = 600, poll_interval: 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()["data"]
        if task["status"] == "success":
            return task
        if task["status"] == "fail":
            err = task.get("error") or {}
            raise RuntimeError(f"task failed: {err.get('code')}: {err.get('message')}")
        time.sleep(poll_interval)
    raise TimeoutError(f"task {task_id} still running after {timeout_s}s")

task_id = create_task(
    "Un barista versa latte art in un caffè illuminato dal sole, profondità di campo ridotta"
)
task = wait_task(task_id)
video_url = task["output"][0]["url"]

# The URL is signed and expires — persist the bytes immediately.
with open("clip.mp4", "wb") as f:
    f.write(requests.get(video_url, timeout=120).content)
print("saved clip.mp4")

Considera qualsiasi stato diverso da success / fail come "ancora in esecuzione": così il ciclo resta robusto anche se in futuro cambiano i nomi degli stati intermedi.

Considerazioni per la produzione

Usa i callback invece del polling

Per qualsiasi scenario che vada oltre uno script, registra un callback al momento della creazione dell'attività e salta del tutto il polling:

{
  "model": "seedance-2.0-fast",
  "input": { "prompt": "..." },
  "callback": { "url": "https://your-app.com/hooks/hiapi", "when": "final" }
}

Con "when": "final", quando l'attività raggiunge lo stato finale il tuo endpoint riceve esattamente una POST. Il polling va bene per CLI e notebook; quando esegui su larga scala i callback sono migliori (nessuna richiesta sprecata e nessuna latenza dovuta all'intervallo di polling). Se il tuo hook sembra non attivarsi, consulta la guida alla risoluzione dei problemi dei callback: quasi sempre si tratta di un problema di raggiungibilità dell'URL o del fatto che il tuo handler restituisce una risposta non 2xx.

Idempotenza

Creare un'attività non è gratuito, quindi evita invii duplicati dal tuo lato: fai in modo che ogni evento di business corrisponda al massimo a una chiamata POST /v1/tasks (ad esempio, memorizzando il taskId associato alla riga dell'ordine/attività prima di riprovare). Se il tuo processo va in crash dopo aver creato l'attività, puoi riprendere rileggendo il taskId memorizzato e riprendendo con GET /v1/tasks/<id>: l'attività continua a essere eseguita sul server indipendentemente dal fatto che tu faccia polling o meno.

Gli errori che incontrerai realmente

Sintomo Significato Correzione
400 con error_code: "INVALID_REQUEST" L'input non ha superato la validazione dello schema; message indica il campo specifico, ad esempio duration: maximum: got 20, want 15 Correggi quel campo; sono ammessi solo i quattro campi della tabella precedente
401 con error.code: "permission_denied" La chiave non è valida, oppure è valida ma non è abilitata per questo modello Controlla la chiave nella dashboard; i permessi sui modelli sono impostati per singola chiave
404 durante la GET con "task not found" L'id dell'attività è errato o non appartiene a questo account Usa il taskId restituito alla creazione, appartenente allo stesso account
Stato dell'attività "fail" con un oggetto error La generazione stessa è fallita Leggi error.code/error.message; modifica il prompt e riprova

Nota i due diversi incapsulamenti degli errori: gli errori di validazione mettono message al livello superiore, mentre gli errori di autenticazione sono annidati sotto error. Se scrivi un middleware generico, devi gestire entrambi i casi.

Quando usare seedance-2.0-fast

Se ti serve un output a 1080p o 4K, usa il modello completo seedance-2.0: stesso endpoint, stesso flusso, limite di risoluzione più alto (e richiede di specificare esplicitamente aspect_ratio). Per una panoramica più completa del confronto tra la famiglia Seedance e gli altri modelli video sulla piattaforma, consulta il confronto tra modelli video. Il riferimento completo dei parametri di ogni modello è nella documentazione; la pagina del modello tiene traccia delle capacità attuali e dello stato dei prezzi.

Domande frequenti

Quali risoluzioni supporta seedance-2.0-fast? 480p e 720p. Questo è il prezzo da pagare per la velocità: il modello completo seedance-2.0, con lo stesso flusso /v1/tasks, arriva fino a 1080p e 4k.

Posso usare seedance-2.0-fast per la generazione da immagine a video? No. Lo schema di input accetta solo prompt, duration, resolution e aspect_ratio; i campi immagine vengono rifiutati con un errore di validazione. Per le opzioni di generazione da immagine a video su hiapi, consulta la guida al flusso di lavoro da immagine a video.

Quanto può durare il video generato? duration accetta un intero da 4 a 15 secondi. I valori al di fuori di questo intervallo falliscono la validazione prima della creazione dell'attività (le richieste rifiutate non vengono fatturate).

Devo usare il polling o i callback? Per script e volumi bassi, un polling ogni ~5 secondi va bene. Su scala di produzione, passa callback: {"url": ..., "when": "final"} al momento della creazione e lascia che hiapi ti invii lo stato finale: una sola richiesta invece di decine.

Perché una chiave che funziona con altri modelli qui restituisce 401 permission_denied? L'accesso ai modelli è limitato per singola chiave. Un 401 con permission_denied su questo modello significa che la chiave esiste ma non è abilitata per seedance-2.0-fast: controlla i permessi sui modelli di quella chiave nella dashboard.

Quanto dura l'URL di output? È un URL firmato e scade. Scarica subito l'MP4 dopo il successo dell'attività e archivialo tu stesso; non incorporare l'URL di output originale in alcun contesto di lunga durata.

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