spicyapiDocumentazione
Guide
Contenuto principale

Tutorial: da immagine a video

Parti da un’immagine sul tuo computer e arriva a un file video scaricato. Ogni passaggio mostra la CLI, l’SDK TypeScript e l’HTTP puro.

Questo tutorial prende un’immagine dal tuo computer e la trasforma in una breve clip video che scarichi e conservi. Segue tutto il percorso, in ordine: scegli un modello, carichi l’immagine, controlli il prezzo, avvii la generazione, aspetti che finisca, scarichi il risultato e gestisci qualsiasi cosa vada storta. Non devi ricostruirlo mettendo insieme i pezzi delle pagine di riferimento.

Ogni passaggio mostra tre modi per fare la stessa cosa. Scegline uno e usalo dall’inizio alla fine:

ModoSceglilo seTi serve
CLIVuoi digitare comandi senza scrivere codiceNode.js 22.13 o successivo
TypeScript SDKStai costruendo un programma Node.js e vuoi vedere le chiamate che faNode.js 22.13 o successivo
HTTP (curl)Vuoi vedere l’API così com’è, per esempio per usarla più avanti da un altro linguaggio di programmazioneUn terminale bash con curl e jq (macOS, Linux oppure WSL su Windows)

Preferisci chiedere semplicemente a un assistente IA di farlo per te? Vedi Fallo fare a un assistente IA.

Che cosa otterrai

  • Il risultato: un breve file video, di solito MP4, che parte dalla tua immagine e si muove come descrive la tua frase.
  • Il tuo tempo: la prima volta calcola circa 20 minuti, in gran parte di lettura. La generazione vera e propria di solito richiede qualche minuto; con alcuni modelli e impostazioni ci vuole di più.
  • Dove avviene: su SpicyAPI. Il tuo computer invia soltanto l’immagine e le istruzioni, poi scarica il file finito.

Quanto costa, e come saperlo prima di pagare

I prezzi sono in dollari statunitensi. Dipendono dal modello che scegli e dalle tue impostazioni, come la durata e la risoluzione del video, quindi questa pagina non indica una cifra. Puoi vedere il prezzo in tre punti, e nessuno di questi costa nulla:

  1. Il catalogo in tempo reale (passaggio 1) elenca ogni modello che il tuo account può usare, con i prezzi del tuo account. Di solito i video hanno un prezzo per_second, cioè per ogni secondo di output. Quando un modello indica più prezzi, ciascuno corrisponde a un’impostazione, per esempio una risoluzione.
  2. Un preventivo (passaggio 3) ti dà il prezzo esatto della tua richiesta esatta. Non avvia nulla e non accantona denaro.
  3. La conferma: la CLI mostra di nuovo il prezzo e aspetta il tuo y prima di avviare qualsiasi cosa.

Che cosa succede al tuo denaro:

  • Solo il passaggio 4 costa denaro, e lo stesso vale per rieseguire un’attività fallita. Elencare i modelli, caricare, chiedere un preventivo, aspettare e scaricare sono gratuiti.
  • Quando una generazione parte, l’importo del preventivo viene accantonato dal tuo saldo (un accantonamento). Quell’importo è anche il massimo che il video può costare.
  • Se il video riesce, ti viene addebitato ciò che è stato prodotto, mai più dell’accantonamento, e quello che avanza torna sul tuo saldo.
  • Le attività fallite o scadute normalmente liberano l’intero importo accantonato. Alcuni rifiuti di contenuto vengono addebitati al preventivo accettato, solo se la pagina del modello indica esplicitamente questa eccezione. Controlla settled e cost per conoscere l’importo finale.
  • I nuovi account non includono alcun importo gratuito, quindi prima ti serve un saldo. Vedi Fatturazione.

Come funziona

la tua immagine ──caricamento──▶ indirizzo spicy:// (valido un giorno)
                                      │
la tua frase + impostazioni ──────────┴──▶ preventivo (gratis) ──▶ avvia l’attività
                                                                   (importo accantonato)
                                                                    │
                                       queued ──▶ running ──▶ succeeded / failed / expired
                                                                    │
                                       link di download (circa 20 minuti) ──▶ il tuo file

Un’attività è un singolo lavoro di generazione. SpicyAPI la elabora in background, quindi avviarla e ritirarne il risultato sono due azioni separate. Ogni attività ha un ID che inizia con job_; conservalo, perché è così che ritrovi l’attività. Le altre parole usate in questa pagina sono spiegate nel Glossario.

Prima di iniziare

Procurati un account, un saldo e una chiave API

Segui prima Configura il tuo account. Alla fine dovresti avere:

  • un account SpicyAPI con del denaro sul saldo;
  • una chiave API, che inizia con sk-spicy-;
  • quella chiave salvata in una variabile d’ambiente chiamata SPICY_API_KEY. Una variabile d’ambiente è un valore con un nome che il terminale passa ai programmi che esegue, così la chiave non deve mai comparire in un comando o nel tuo codice.

Controlla che la chiave sia impostata nella finestra del terminale che stai usando, senza stampare la chiave intera:

echo "${SPICY_API_KEY:0:9}"

Dovresti vedere sk-spicy-. Se non vedi nulla o compare un errore, la chiave non è impostata in questa finestra; torna a Configura il tuo account.

Metti l’immagine in una cartella di lavoro

Crea una cartella per questo tutorial e apri il terminale al suo interno. Ogni comando di questa pagina va eseguito da questa cartella, e ogni file che viene creato finisce qui.

mkdir -p ~/spicy-video
cd ~/spicy-video

Copia l’immagine in quella cartella e chiamala start-frame.jpg (oppure start-frame.png se è un PNG; in quel caso usa quel nome ovunque questa pagina scrive start-frame.jpg).

Com’è fatta una buona immagine di partenza:

  • Formato e dimensione: JPEG, PNG, WebP o GIF, fino a 10 MiB (circa 10 megabyte). Un modello può fissare limiti propri più severi, che vedrai nel passaggio 1.
  • Il file deve essere davvero in quel formato. SpicyAPI controlla il contenuto del file, non solo il nome. Le foto scattate con il telefono sono spesso in HEIC, e rinominarne una in .jpg non la converte. Prima aprila ed esportala o salvala come JPEG.
  • Forma: l’immagine diventa il primo fotogramma. Usa un’immagine orizzontale per un video orizzontale e una verticale per un video verticale; alcuni modelli offrono anche un’impostazione aspect_ratio.
  • Diritti: usa un’immagine che hai il diritto di usare.

Prepara lo strumento che hai scelto

La CLI è un programma chiamato spicyapi che esegui nel terminale. Installala una volta (istruzioni complete, Node.js compreso: CLI: prima di iniziare):

npm install -g @spicyapi/cli
spicyapi --version

Se l’installazione fallisce con EACCES, saltala e scrivi npx @spicyapi/cli ovunque questa pagina scrive spicyapi.

Poi controlla che la chiave funzioni e che tu abbia un saldo:

spicyapi balance

Dovresti vedere available, held e total in dollari statunitensi. available deve essere maggiore di zero.

I sette passaggi

Sostituisci MODEL_ID_FROM_CATALOG con un vero ID di modello

MODEL_ID_FROM_CATALOG è un segnaposto, non un modello. Nel passaggio 1 scegli un vero ID di modello dal catalogo in tempo reale (spicyapi models list, listModels() nell’SDK oppure GET /api/v1/models). Incollalo ovunque questa pagina mostra il segnaposto. Se invii il segnaposto così com’è, ricevi soltanto un errore «not found».

Usi Windows? Scegli la scheda CLI o SDK

La scheda HTTP è scritta per bash. Windows PowerShell tratta in modo diverso le virgolette, gli a capo (\) e $(...), quindi lì quei comandi non funzionano così come sono scritti. Su Windows usa la scheda CLI o SDK, oppure esegui i comandi HTTP dentro WSL (Sottosistema Windows per Linux, in inglese Windows Subsystem for Linux).

1. Scegli un modello e leggi le sue impostazioni

Fai così: elenca i modelli da immagine a video che il tuo account può usare, scegline uno, poi leggi quali impostazioni accetta.

Elenca i modelli:

spicyapi models list --modality video --task image-to-video --json

Dovresti vedere un elenco JSON. Questo è accorciato, e gli importi compaiono come …:

{
  "total": 1,
  "items": [
    {
      "model": "MODEL_ID_FROM_CATALOG",
      "displayName": "Example video model",
      "modality": "video",
      "tasks": ["image-to-video"],
      "enabled": true,
      "available": true,
      "quantityField": "duration_seconds",
      "maxOutputDurationSeconds": 10,
      "taskTimeoutSeconds": 1800,
      "pricing": [
        { "variant": "720p", "unit": "per_second", "price": "…", "currency": "USD" },
        { "variant": "1080p", "unit": "per_second", "price": "…", "currency": "USD" }
      ]
    }
  ]
}

Scegli un modello in cui enabled e available valgano entrambi true e copia il suo valore model. Poi leggi le sue impostazioni:

spicyapi models get MODEL_ID_FROM_CATALOG --json

La risposta contiene gli stessi campi più inputSchema (le impostazioni) ed examples (input che il server ha già verificato).

Che cosa guardare nell’elenco:

CampoChe cosa ti dice
modelL’ID del modello che userai in tutti i passaggi successivi
enabled, availableUsa un modello solo quando valgono entrambi true
pricingUna voce per ogni livello di prezzo: variant (l’impostazione a cui si applica, spesso una risoluzione), unit (per i video di solito per_second) e price in dollari statunitensi. regularPrice e offerLabel compaiono quando è applicato uno sconto
quantityFieldL’impostazione che decide quante unità paghi, di solito duration_seconds. Se è vuoto, paghi un’unità per video
maxOutputDurationSecondsIl video più lungo che il modello consente
taskTimeoutSecondsPer quanto tempo può andare avanti una generazione prima di fermarsi come expired (senza addebito)

Come leggere le impostazioni. inputSchema è l’elenco delle impostazioni del modello, scritto in JSON Schema:

  • required elenca le impostazioni che devi inviare. Per questo tipo di modello image_url è sempre tra queste, e la maggior parte dei modelli richiede anche prompt.
  • properties elenca tutte le impostazioni che il modello accetta, ciascuna con un type, una description in inglese semplice e spesso enum (gli unici valori ammessi), minimum e maximum, e default (il valore usato quando ometti l’impostazione).
  • Dentro ogni impostazione, x-ui contiene indicazioni per la visualizzazione. x-ui.affects_price: true significa che cambiare quell’impostazione cambia il prezzo.
  • Alcuni modelli aggiungono condizioni al livello principale, come «se invii A devi inviare anche B». Spicy Schema spiega come leggerle.
  • examples contiene input completi che il server ha già verificato: sono un punto di partenza sicuro.

Le impostazioni che incontrerai più spesso. I nomi sono gli stessi per tutti i modelli, ma ogni modello ne accetta solo alcuni, ciascuno con i propri valori ammessi:

ImpostazioneChe cosa faCambia il prezzo?
image_urlL’immagine di partenza, usata come primo fotogramma. Accetta l’indirizzo spicy:// del passaggio 2 oppure un link pubblico https://No
promptChe cosa deve succedere: il movimento, la telecamera, l’atmosfera. Descrivi il movimento invece di ripetere ciò che l’immagine mostra giàDi solito no
duration_secondsDurata del video in secondi. I valori ammessi sono in enum oppure tra minimum e maximum; alcuni modelli accettano un valore speciale, spiegato nella description dell’impostazioneSì sulla maggior parte dei modelli: di solito il video si paga al secondo, quindi una clip più lunga costa di più
resolutionDimensione dell’output, come 720p o 1080pDi solito sì: le risoluzioni più alte tendono ad avere un prezzo proprio, più alto
aspect_ratioLa forma del video, come 16:9, 9:16 o 1:1. Alcuni modelli offrono adaptive, che segue le proporzioni dell’immagineControlla x-ui.affects_price
generate_audioGenera anche una colonna sonora in sintonia con l’immagineSu alcuni modelli
last_image_urlUn’immagine per l’ultimo fotogramma; vedi Primo e ultimo fotogrammaChiedi un preventivo per saperlo
negative_promptChe cosa il video deve evitareDi solito no
seedUn numero che rende più facile confrontare i risultati tra un’esecuzione e l’altra; non garantisce video identiciNo

Invia solo le impostazioni elencate da questo modello

Ogni modello ha il proprio elenco. Un’impostazione che non compare nelle properties di quel modello, un nome scritto male o un valore fuori da enum fanno rifiutare l’intera richiesta con 400. Non viene addebitato nulla, ma non copiare l’input di un altro modello senza controllarlo.

Che cosa è appena successo: hai letto il catalogo in tempo reale del tuo account, compresi i tuoi prezzi. Non è stato addebitato nulla. Leggere il catalogo conta nel limite di richieste del tuo account, quindi non serve ripeterlo prima di ogni video: rifallo quando cambi modello o ricevi un 400.

2. Carica la tua immagine

Fai così: carica start-frame.jpg e copia l’indirizzo spicy:// che ricevi. Il caricamento è gratuito.

spicyapi files upload start-frame.jpg

Dovresti vedere:

fileId: fil_01k3m8x9q2z4v7n5p6r8s0t1w3
status: ready
bytes: 402118
contentType: image/jpeg
sha256: a91f4c2e5b7d16809e3f2a4c8d0b61e7c4a890e5d2f71b3c609ae8427d15f0c6
uri: spicy://f/fil_01k3m8x9q2z4v7n5p6r8s0t1w3
expiresAt: 2026-09-18T09:12:11Z

Copia il valore uri esattamente come viene stampato.

Che cosa è appena successo: la tua immagine è stata salvata in forma privata per il tuo account, controllata (il suo formato reale deve corrispondere al tipo dichiarato) e ha ricevuto un indirizzo spicy://. Quell’indirizzo non è un link web: solo il tuo account può usarlo, e solo dentro l’input di un’attività. Si può usare per un giorno (vedi expiresAt); dopo, carica di nuovo l’immagine.

L’immagine è già online?

Se l’immagine si trova già a un indirizzo pubblico https:// che si apre senza login, puoi saltare questo passaggio e mettere quell’indirizzo in image_url. Deve restare raggiungibile per tutto il tempo in cui il video viene generato.

Se il caricamento fallisce:

VediChe cosa significaChe cosa fare
Unsupported file type, oppure la CLI o l’SDK dice che non riesce a capire il tipoIl file non è JPEG, PNG, WebP o GIFConverti l’immagine, oppure dalle un nome con l’estensione giusta
File exceeds the 10 MB limitL’immagine supera i 10 MiBEsporta una versione più piccola
The uploaded file does not match the upload ticketIl contenuto del file non è del tipo indicato dal nome o dalla dichiarazione, per esempio una foto HEIC rinominata in .jpgEsportala come vero JPEG o PNG e caricala di nuovo
The upload ticket has expiredTra il ticket e il commit sono passati più di circa 20 minutiRicomincia il caricamento da capo

3. Descrivi il video e controlla il prezzo

Fai così: scrivi le impostazioni in un file chiamato input.json, poi chiedi un preventivo.

Scrivi input.json. Parti dalle due impostazioni che ogni modello da immagine a video accetta. Metti la tua frase in prompt e sostituisci il valore di image_url con l’uri che hai copiato nel passaggio 2:

input.json
{
  "prompt": "The camera slowly pushes in while rain runs down the window and neon light flickers",
  "image_url": "spicy://f/fil_01k3m8x9q2z4v7n5p6r8s0t1w3"
}

Le impostazioni che ometti usano il default del modello. Per sceglierle tu, aggiungi solo impostazioni presenti nelle properties del tuo modello, con valori che il modello ammette. Per esempio, se il tuo modello elenca duration_seconds e resolution e ammette questi valori:

{
  "prompt": "The camera slowly pushes in while rain runs down the window and neon light flickers",
  "image_url": "spicy://f/fil_01k3m8x9q2z4v7n5p6r8s0t1w3",
  "duration_seconds": 5,
  "resolution": "720p"
}

Salva il file nella cartella di lavoro:

Incolla tutte le righe in una volta, dopo averci messo il tuo testo e il tuo uri:

cat > input.json <<'EOF'
{
  "prompt": "The camera slowly pushes in while rain runs down the window and neon light flickers",
  "image_url": "spicy://f/fil_01k3m8x9q2z4v7n5p6r8s0t1w3"
}
EOF

Usa le virgolette dritte semplici ("), non quelle tipografiche, e non mettere la virgola dopo l’ultima impostazione.

Chiedi il preventivo:

spicyapi tasks quote --model MODEL_ID_FROM_CATALOG --input-file input.json

Dovresti vedere (gli importi compaiono come …):

quoteId: eyJ2IjoxLCJtIjoi…
model: MODEL_ID_FROM_CATALOG
estimatedCost: …
maxCharge: …
currency: USD
quantity: 5
unit: per_second
expiresAt: 2026-09-17T08:05:00Z

Che cosa è appena successo: SpicyAPI ha confrontato il tuo input con le impostazioni del modello e ha calcolato il prezzo di questa richiesta esatta. Non è stato avviato nulla e non è stato addebitato nulla. estimatedCost è l’importo che verrà accantonato se avvii adesso, e maxCharge è il massimo che può costare. quantity e unit mostrano che cosa paghi, per esempio 5 secondi.

Un preventivo vale cinque minuti e solo per questo input esatto. Cambia la durata o la risoluzione e chiedi un nuovo preventivo per confrontare i prezzi. Il preventivo esegue gli stessi controlli dell’avvio dell’attività, quindi i problemi emergono qui, gratis: un 400 significa che l’input non corrisponde alle impostazioni del modello (correggi input.json con l’aiuto del passaggio 1), e un 40201 significa che il saldo non basterebbe. Il passaggio 7 elenca gli altri codici.

Vuoi fare una prova senza la tua immagine?

Gli examples del modello visti nel passaggio 1 sono input completi che il server ha già verificato. Puoi metterne uno in input.json così com’è, chiedere il preventivo e generarlo, per vedere l’intero flusso funzionare prima di usare la tua immagine.

4. Avvia la generazione

Questo passaggio costa denaro

Avviare la generazione accantona dal tuo saldo l’importo del preventivo. Una volta che SpicyAPI l’ha accettata, l’attività non si può annullare: arriva fino in fondo e viene addebitata se riesce. Le attività fallite o scadute normalmente liberano l’intero importo accantonato. Alcuni rifiuti di contenuto vengono addebitati al preventivo accettato, solo se la pagina del modello indica esplicitamente questa eccezione. Controlla settled e cost per conoscere l’importo finale.

La chiave di idempotenza, in parole semplici. È un’etichetta per un video, come un numero d’ordine. Se la connessione cade e non sai se il video è partito, invia di nuovo la stessa richiesta con la stessa etichetta: SpicyAPI ti restituisce l’attività che ha già avviato, invece di avviarne (e addebitarne) una seconda. Un’etichetta vale per 24 ore con la stessa chiave API. Per un video diverso usa un’etichetta nuova: la stessa etichetta con un input diverso viene rifiutata con 409. Maggiori dettagli in Idempotenza.

Fai così:

spicyapi tasks create --model MODEL_ID_FROM_CATALOG --input-file input.json

La CLI chiede di nuovo il preventivo, mostra il prezzo e aspetta la tua risposta:

Estimated charge: USD …; maximum charge: USD …. Quote expires: 2026-09-17T08:05:00Z.
Idempotency-Key: 4f6755a5-0d72-4420-9f6b-9faf0e2b0241
Create a billable task with model MODEL_ID_FROM_CATALOG? … Continue? [y/N]

Digita y e premi Invio. Qualsiasi altra risposta annulla, e non viene addebitato nulla. Prima di rispondere, copia da qualche parte il valore di Idempotency-Key: la CLI crea un’etichetta nuova a ogni esecuzione, e se la connessione cade ti serve proprio questa.

Dovresti vedere:

idempotencyKey: 4f6755a5-0d72-4420-9f6b-9faf0e2b0241
taskId: job_01k3m8x9q2z4v7n5p6r8s0t1w3
state: queued
estimatedCost: …
deadlineAt: 2026-09-17T08:35:00Z

Copia il taskId.

Che cosa è appena successo: SpicyAPI ha accettato la generazione, che adesso è un’attività, e ha accantonato estimatedCost dal tuo saldo. È anche il massimo che questo video può costare. state: queued significa che l’attività aspetta il suo turno. deadlineAt è l’ora entro cui deve finire; se a quell’ora non è conclusa, termina come expired e non viene addebitato nulla. deadlineAt non indica quando scadono i tuoi file.

Passare il preventivo significa «accetta la richiesta solo al prezzo che mi è stato mostrato». Se nel frattempo il prezzo o l’input sono cambiati, la richiesta viene rifiutata con 40901 invece di accantonare un importo diverso. La CLI lo fa per te.

Se la connessione è caduta e non hai mai visto un ID attività, non ricominciare semplicemente con un’etichetta nuova: creeresti e pagheresti un secondo video. Ripeti la richiesta con la stessa etichetta:

  • CLI: spicyapi tasks create --model MODEL_ID_FROM_CATALOG --input-file input.json --idempotency-key <the value you copied> (al posto di <the value you copied> metti il valore che hai copiato). Vedi Riprendere un’attività dopo un’attesa interrotta.
  • SDK: esegui di nuovo node generate.mjs --yes; riusa idempotency-key.txt.
  • HTTP: esegui di nuovo il blocco «Avvia il video»; riusa idempotency-key.txt.

Se il passaggio 4 è stato rifiutato, non è stato creato nulla e non è stato addebitato nulla; la causa e la soluzione sono nel passaggio 7.

5. Aspetta il video

Fai così: controlla l’attività finché non finisce. Di solito i video richiedono qualche minuto.

spicyapi tasks wait job_01k3m8x9q2z4v7n5p6r8s0t1w3 --wait-timeout-ms 1800000 --json

Usa il tuo ID attività. --wait-timeout-ms 1800000 aspetta fino a 30 minuti invece dei 10 predefiniti.

Dovresti vedere, a lavoro finito (versione accorciata):

{
  "taskId": "job_01k3m8x9q2z4v7n5p6r8s0t1w3",
  "model": "MODEL_ID_FROM_CATALOG",
  "state": "succeeded",
  "output": {
    "assets": [
      {
        "key": "tasks/2026/09/17/job_01k3m8x9q2z4v7n5p6r8s0t1w3/result.mp4",
        "url": "https://…",
        "expiresAt": "2026-09-17T08:40:00Z",
        "mime": "video/mp4",
        "durationSeconds": 5,
        "width": 1280,
        "height": 720,
        "bytes": 4839211
      }
    ]
  },
  "cost": "…",
  "settled": true
}

La prossima volta puoi unire i passaggi 4 e 5 aggiungendo --wait a tasks create.

Che cosa è appena successo: il tuo strumento ha chiesto a SpicyAPI lo stato dell’attività ogni pochi secondi. Gli stati sono queued (in attesa), running (in generazione) e poi uno stato finale: succeeded, failed o expired. Dopo la riuscita il file viene copiato nello storage di SpicyAPI, il che richiede qualche secondo in più; fino ad allora il risultato mostra pending: true. cost è definitivo quando settled vale true.

  • Chiudere il terminale o premere Ctrl + C non annulla l’attività. Interrompe solo l’attesa. Conserva l’ID attività ed esegui di nuovo questo passaggio più tardi.
  • Non controllare più spesso di una volta ogni pochi secondi. Ogni controllo di un’attività usa la disponibilità di lettura dell’account, indipendentemente dall’avvio delle attività; vedi Limiti di frequenza.
  • Per un’app o un server, lascia che sia SpicyAPI ad avvisarti quando l’attività è finita, invece di chiederlo tu: vedi Ricevi un avviso invece di aspettare.

6. Scarica e conserva il video

Fai così: ottieni un link di download nuovo e salva il file sul tuo computer.

Ottieni un link nuovo:

spicyapi files download-url job_01k3m8x9q2z4v7n5p6r8s0t1w3
key: tasks/2026/09/17/job_01k3m8x9q2z4v7n5p6r8s0t1w3/result.mp4
url: https://…
expiresAt: 2026-09-17T08:52:00Z

Incolla l’url in un browser per scaricare il video, oppure salvalo dal terminale (lascia le virgolette, perché il link contiene caratteri &):

curl -L -o my-video.mp4 "PASTE_THE_URL_HERE"

In Windows PowerShell scrivi curl.exe invece di curl. Se un’attività ha prodotto più file, spicyapi tasks get <task-id> --json li elenca e --key ne sceglie uno.

Che cosa è appena successo: ogni risultato arriva con un link di download diretto. Il link funziona per circa 20 minuti e non richiede la chiave API: non aggiungerci mai la tua chiave. Quando scade, chiedi di nuovo l’attività (oppure usa files download-url) per ottenerne uno nuovo.

Conserva una copia tua

SpicyAPI conserva i file generati per circa 14 giorni al massimo, meno se l’impostazione di conservazione del tuo account è più breve, e poi li elimina per sempre. L’immagine caricata si può usare per un giorno, e il testo del prompt viene cancellato dopo 30 giorni per impostazione predefinita. Il registro dell’attività e del suo costo invece resta. Per eliminare prima i file e il prompt di un’attività conclusa, usa spicyapi tasks purge, purgeTask() oppure POST /api/v1/jobs/purge: elimina solo il contenuto e non è un rimborso. Vedi Conservazione e distruzione.

7. Quando qualcosa va storto

I problemi sono di due tipi, e si gestiscono in modo diverso.

Una richiesta viene rifiutata. Il comando o la chiamata riceve subito un errore. Non è stato creato nulla e non è stato addebitato nulla. Il messaggio spiega il motivo, e l’errore riporta un code e un ID richiesta (req_…) da citare se contatti l’assistenza.

CodiceChe cosa significaChe cosa fare
400, oppure un codice più specifico che inizia con 400L’input non corrisponde alle impostazioni del modello: manca un’impostazione obbligatoria, ce n’è una sconosciuta o scritta male, un valore non è ammesso, un indirizzo spicy:// è scaduto o non appartiene al tuo account, il modello al momento non può servire quella combinazione di impostazioni, oppure l’indirizzo di callback non è validoConfronta input.json con le impostazioni del passaggio 1 e correggilo. Se l’indirizzo è scaduto, carica di nuovo l’immagine
401La chiave API manca, è scritta male o è stata revocataControlla SPICY_API_KEY come in Prima di iniziare
40201Il saldo non copre l’importo da accantonareAggiungi fondi in Fatturazione nella console
40202È stato raggiunto un limite di spesa della chiave (giornaliero, mensile o complessivo)Alzalo nella pagina Chiavi API, oppure aspetta che si azzeri
403, 40301Questa chiave non può usare questo modello, oppure la richiesta arriva da un luogo da cui non è consentitaControlla i Modelli consentiti e gli IP consentiti della chiave nella pagina Chiavi API
404Nessun modello con quell’ID per il tuo account (oppure hai inviato il segnaposto), oppure nessuna attività con quell’ID per questa chiaveCopia di nuovo l’ID esatto; usa la stessa chiave che ha creato l’attività
409Questa chiave di idempotenza è già stata usata per una richiesta diversaUsa un’etichetta nuova per un video nuovo
40901Il preventivo è scaduto (cinque minuti) oppure il prezzo è cambiatoChiedi di nuovo il preventivo, poi avvia di nuovo
429Troppe richieste in poco tempoAspetta il numero di secondi indicato nell’errore, poi continua più lentamente
50301Il modello al momento non può accettare nuovo lavoroRiprova più tardi, oppure scegli un altro modello

L’attività fallisce. L’attività è stata accettata, ma termina come failed o expired invece che succeeded. L’attività mostra un errorCode che dice perché e un errorMessage che lo spiega più nel dettaglio a parole. Le attività fallite o scadute normalmente liberano l’intero importo accantonato. Alcuni rifiuti di contenuto vengono addebitati al preventivo accettato, solo se la pagina del modello indica esplicitamente questa eccezione. Controlla settled e cost per conoscere l’importo finale.

Leggilo:

spicyapi tasks get job_01k3m8x9q2z4v7n5p6r8s0t1w3

Guarda state, errorCode ed errorMessage.

Poi decidi che cosa fare in base a errorCode, non in base a come è formulato il messaggio:

errorCodeChe cosa significaChe cosa fare
rate_limited, upstream_unavailable, upstream_failedLa generazione era sovraccarica o temporaneamente non disponibileEseguila di nuovo dopo una breve pausa
timeout (oppure lo stato è expired)Il video non è stato completato in tempoRiprova una volta; se succede di nuovo, scegli una durata più breve o una risoluzione più bassa e avvia una nuova attività
generation_failedLa generazione è stata eseguita ma non ha prodotto nullaDi solito lo stesso input fallisce allo stesso modo. Cambia il prompt o l’immagine e avvia una nuova attività
invalid_assetNon è stato possibile usare l’immagine, per esempio perché il caricamento era scaduto o il file non era leggibileCarica di nuovo l’immagine e avvia una nuova attività con il nuovo indirizzo
invalid_request, unsupported_combinationLe impostazioni non sono state accettateCambia le impostazioni e avvia una nuova attività
content_rejectedIl modello selezionato ha rifiutato questa richiesta in base alla propria policyCambia il prompt o l’immagine, oppure scegli un altro modello

Qualsiasi altro valore va trattato come upstream_failed. L’elenco completo è in Errori.

Esegui di nuovo un’attività fallita. Un nuovo tentativo crea una nuova attività con lo stesso modello e lo stesso input, al prezzo attuale del modello. Costa denaro, come il passaggio 4, e mantiene l’input originale: se quell’input usava un caricamento che nel frattempo è scaduto, carica di nuovo l’immagine e avvia invece una nuova attività.

spicyapi tasks retry job_01k3m8x9q2z4v7n5p6r8s0t1w3 --wait --wait-timeout-ms 1800000

Ti chiede di confermare ma, a differenza di tasks create, non mostra prima un prezzo. Per vedere il prezzo, esegui il comando tasks quote del passaggio 3.

Si possono ripetere solo le attività failed ed expired. Per una versione diversa di un video riuscito, torna al passaggio 3 con un’etichetta nuova. Non c’è modo di annullare un’attività una volta accettata. Maggiori dettagli in Impegno dell’attività e nuovi tentativi.

In alternativa: fallo fare a un assistente IA

Se usi un assistente IA che supporta MCP, come Claude Code, Cursor o Codex, il server MCP di SpicyAPI gli permette di fare tutti e sette i passaggi al posto tuo. Configuralo una volta seguendo Server MCP: configura il tuo client, poi chiediglielo con parole tue, per esempio:

Carica su SpicyAPI l’immagine che si trova in /Users/me/spicy-video/start-frame.jpg. Trova i modelli da immagine a video che la mia chiave può usare e chiedi un preventivo per una clip di 5 secondi sui due più economici. Poi, quando te lo confermo, genera il video con il più economico dei due, aspetta che sia pronto e dammi il link di download.

Su Windows, indica il percorso come C:\Users\me\spicy-video\start-frame.jpg.

Che cosa succede:

  1. spicyapi_upload_file carica l’immagine e ottiene il suo indirizzo spicy://. È gratuito, ma invia davvero il file, quindi indica con precisione il file che intendi. Per impostazione predefinita si possono leggere solo i file che si trovano nella tua cartella home; vedi File locali.
  2. spicyapi_models_list e spicyapi_model_get trovano un modello e le sue impostazioni, e spicyapi_task_quote calcola il prezzo delle varie opzioni. Tutto gratis.
  3. spicyapi_task_create si ferma e ti chiede conferma, mostrando il modello, l’addebito stimato e quello massimo e la scadenza del preventivo. Non viene addebitato nulla finché non confermi, e l’assistente non può confermare al posto tuo.
  4. spicyapi_task_wait aspetta fino a cinque minuti per volta, quindi per un video più lungo l’assistente può dover aspettare più di una volta. Alla fine ti dà il link di download, che funziona per circa 20 minuti.

Altri esempi e tutti gli strumenti: Server MCP.

Per andare oltre

Primo e ultimo fotogramma

Alcuni modelli da immagine a video accettano anche last_image_url: una seconda immagine su cui il video deve terminare. Per sapere se il tuo la accetta, cerca last_image_url nelle properties del passaggio 1. Se non c’è, il modello non la supporta, e inviarla fa rifiutare la richiesta con 400.

Carica entrambe le immagini come nel passaggio 2, poi metti entrambi gli indirizzi in input.json:

{
  "prompt": "The flower slowly opens as morning light spreads across the table",
  "image_url": "spicy://f/fil_01k3m8x9q2z4v7n5p6r8s0t1w3",
  "last_image_url": "spicy://f/fil_01k3m8x9q2z4v7n5p6r8s0t1w4"
}

La description dell’impostazione spiega come quel modello usa l’immagine finale. Prima di avviare chiedi di nuovo il preventivo, per vedere se la seconda immagine cambia il prezzo.

Più video

  • Riusa il caricamento. Un indirizzo spicy:// si può usare in più attività fino al suo expiresAt, a meno che la conservazione dei caricamenti del tuo account non sia impostata per eliminarli appena un’attività finisce.
  • Un’etichetta per ogni video. Dai a ogni video la propria chiave di idempotenza, per esempio campaign-clip-1, campaign-clip-2. Così, se esegui di nuovo lo script, ottieni i video già avviati invece di pagarli due volte.
  • Non avviare tutto insieme. Ogni attività in corso tiene accantonato un importo, un limite di spesa rifiuta con 40202 le attività che lo superano, e ogni controllo di stato conta nel limite di richieste. Comincia con due alla volta.

Script pronti all’uso: Eseguire un lotto con concorrenza limitata (SDK) ed Eseguire la CLI da uno script.

Ricevi un avviso invece di aspettare

Per un sito web o un servizio in background, tenere acceso un programma solo per chiedere «ha finito?» è uno spreco. Dai invece all’attività un indirizzo di callback: un indirizzo web pubblico sul tuo server che SpicyAPI chiama una volta, quando l’attività finisce, inviando gli stessi dettagli dell’attività che vedi nel passaggio 5.

Che cosa ti serve:

  • un server raggiungibile da internet a un indirizzo https://, sulla porta standard (localhost viene rifiutato);
  • la chiave di firma dei webhook, che trovi nella console, così il tuo server può verificare che ogni chiamata arrivi davvero da SpicyAPI;
  • codice che verifichi la firma, risponda in fretta e gestisca la stessa notifica ricevuta due volte.

Webhook spiega il formato, la firma e la sequenza dei nuovi tentativi, e l’SDK ha un ricevitore minimo. Tieni anche un piano di riserva: ogni tanto controlla le attività che hanno superato da tempo la loro deadlineAt senza che sia arrivata una notifica.

Aggiungi l’indirizzo di callback quando chiedi il preventivo e avvii l’attività:

spicyapi tasks create --model MODEL_ID_FROM_CATALOG --input-file input.json --callback-url https://your-app.example.com/hooks/spicy

La CLI include l’indirizzo nel preventivo che chiede, quindi il controllo del prezzo continua a corrispondere.

Prossimi passi

In questa pagina