Tutoriale
Come usare nano-banana-pro tramite l'API HiAPI: esempi con curl e Python
Cosa ti offre nano-banana-pro su HiAPI
nano-banana-pro è un modello di generazione di immagini accessibile tramite l'API unificata di HiAPI. Non serve integrarsi direttamente con il provider del modello: basta inviare a HiAPI una richiesta in formato uniforme per ottenere l'immagine generata — come per gli altri modelli della piattaforma, con la stessa autenticazione, le stesse convenzioni sugli endpoint e lo stesso wrapper di risposta.
nano-banana-pro è progettato per la generazione di immagini guidata da prompt e consente di allegare immagini di riferimento oltre al prompt testuale. Le immagini di riferimento ti permettono di guidare l'output con un contesto visivo (soggetto, stile, composizione), senza dover descrivere tutto a parole. L'output viene fornito a risoluzione 2K, quindi il modello è più adatto ad asset di produzione che a bozze rapide.
Al termine di questo tutorial avrai un'integrazione completa e funzionante in grado di:
- inviare un prompt a nano-banana-pro tramite HiAPI con una richiesta
curlverificata; - riprodurre la stessa chiamata in Python senza modificare il payload della richiesta;
- allegare un'immagine di riferimento alla richiesta;
- inviare un job asincrono, fare polling fino al completamento e gestire i retry in modo sensato;
- scaricare l'immagine 2K completata e salvarla nella tua infrastruttura.
Ogni sezione si basa sulla precedente, quindi il percorso più sicuro è procedere in ordine: prima conferma la richiesta manualmente, poi spostala nel codice.
Prima di inviare la prima richiesta
Prima della prima chiamata ti servono tre cose.
Una chiave API
Crea una chiave API nel tuo account HiAPI e assicurati che non finisca nel controllo del codice sorgente. Trattala come qualsiasi altro segreto: caricala da una variabile d'ambiente (HIAPI_API_KEY) o da un gestore di segreti, non codificarla mai direttamente in file che potresti committare. Se la chiave viene compromessa, ruotala dalla dashboard invece di cercare di ripulirla dalla cronologia.
Un client HTTP
Qualsiasi strumento in grado di inviare richieste HTTPS va bene. Per la prima richiesta, curl da riga di comando è la scelta ideale, perché tra te e la rete non c'è alcun framework: ogni header e ogni byte del corpo della risposta sono visibili. Per la parte Python, la libreria standard urllib.request è sufficiente; se usi già requests o httpx, la corrispondenza è la stessa. Questo tutorial limita Python alla libreria standard, quindi non serve installare nulla in più.
Un posto dove salvare l'output
Poiché i job di nano-banana-pro sono asincroni, pianifica fin dall'inizio la directory o il bucket in cui salvare le immagini completate. In sviluppo va bene una cartella locale output/; in produzione punta all'object storage.
Non serve installare l'SDK del fornitore. HiAPI si chiama tramite normale HTTPS, quindi la richiesta che costruisci in curl è identica a quella che il tuo client Python invierà in seguito.
Una richiesta curl funzionante, spiegata passo passo
Il modo più rapido per verificare che chiave, endpoint e payload siano corretti è inviare manualmente una richiesta. Prima di digitarla, scomponila nelle sue parti.
Endpoint e metodo
Tutte le chiamate ai modelli vanno allo stesso URL di base di HiAPI; il modello è identificato nel corpo della richiesta, non nel percorso. Le richieste di generazione usano POST.
Header
Ci sono tre header importanti per ogni chiamata:
Authorization: Bearer $HIAPI_API_KEY— la tua chiave, passata come token bearer.Content-Type: application/json— per le richieste con solo prompt.Accept: application/json— per ottenere una risposta strutturata invece di una pagina di errore HTML.
Corpo della richiesta
Il corpo JSON contiene il nome del modello e i parametri di generazione. Come minimo devi inviare l'identificatore del modello e il tuo prompt:
curl -sS -X POST "$HIAPI_BASE_URL" \
-H "Authorization: Bearer $HIAPI_API_KEY" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"model": "nano-banana-pro",
"input": {
"prompt": "a glass terrarium on a sunlit windowsill, soft morning light, shallow depth of field"
}
}'
Prima di eseguire questo comando, imposta HIAPI_BASE_URL e HIAPI_API_KEY nella shell. Tenere l'URL in una variabile significa che in futuro potrai puntare lo stesso script a un URL di staging o sandbox senza modificare il comando.
Leggere la risposta
Un invio riuscito restituisce un oggetto JSON che identifica il job. Il campo importante è l'identificatore del job: lo userai nella fase di polling. Poiché la generazione richiede tempo, non aspettarti di ricevere l'immagine già nella prima risposta; nano-banana-pro lavora in modo asincrono e questa chiamata è solo la fase di invio dell'interazione.
Se il comando restituisce un errore, fermati qui e correggilo prima di scrivere qualsiasi codice. La richiesta curl verificata è la tua implementazione di riferimento: ogni passo successivo deve produrre la stessa richiesta HTTP.
Portare la richiesta in Python
Il porting è meccanico: URL, metodo, header e corpo JSON restano gli stessi. Cambia solo il client.
La stessa richiesta con urllib
import json
import os
import urllib.request
api_key = os.environ["HIAPI_API_KEY"]
base_url = os.environ["HIAPI_BASE_URL"]
payload = {
"model": "nano-banana-pro",
"input": {
"prompt": "a glass terrarium on a sunlit windowsill, soft morning light, shallow depth of field"
},
}
request = urllib.request.Request(
base_url,
data=json.dumps(payload).encode("utf-8"),
method="POST",
headers={
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json",
"Accept": "application/json",
},
)
with urllib.request.urlopen(request, timeout=60) as response:
body = json.loads(response.read().decode("utf-8"))
print(body)
Regole di mappatura
Quando converti da curl, ci sono tre dettagli in cui è facile sbagliare:
- Il corpo deve essere in byte.
json.dumpsproduce una stringa; prima di passarla all'oggetto request devi codificarla. - Gli header sono un dizionario, non dei flag. Ogni riga
-Hdiventa una coppia chiave/valore. Mantieni il prefissoBearercon lo spazio che lo segue. - Il metodo va specificato esplicitamente. In presenza di dati,
urllib.requestusaPOSTper impostazione predefinita, ma impostaremethod="POST"rende l'intento più chiaro e previene sorprese se in futuro rimuovi il corpo della richiesta.
Se usi requests, l'equivalente è requests.post(base_url, headers=headers, json=payload, timeout=60) — json= gestisce per te serializzazione e content type. Se usi httpx, la forma della chiamata è la stessa.
Una piccola funzione di supporto che vale la pena avere
Inserisci la chiamata di invio in una funzione che riceve un prompt e restituisce l'identificatore del job. Ogni sezione successiva — immagini di riferimento, polling, download — si basa su quella funzione; tenerla in un unico posto significa che i cambiamenti nella forma della richiesta avvengono una sola volta.
Inviare un'immagine di riferimento insieme al prompt
L'immagine di riferimento cambia la forma della richiesta, quindi decidi presto quale modalità di input userà la tua applicazione.
Due opzioni pratiche
Input basato su URL. Se l'immagine di riferimento è già accessibile via HTTPS, puoi allegare il suo URL insieme al prompt nel corpo della richiesta. Questo mantiene la richiesta come application/json, la forma più facile da ritentare e registrare.
Caricamento file. Se l'immagine si trova sul client o in uno storage privato, puoi inviarla come parte file in una richiesta multipart/form-data. In questo caso l'header Content-Type: application/json viene sostituito dal content type multipart — lascia che sia il tuo client HTTP a generarlo per garantire il boundary corretto — e i campi JSON diventano campi form nella stessa richiesta.
Per la maggior parte delle integrazioni lato server, l'input basato su URL è più semplice: le tue immagini sono già nell'object storage, la richiesta resta JSON e nei retry eviti di inviare due volte un corpo grande.
Mantenere prompt e immagine di riferimento allineati
Il prompt dovrebbe descrivere lo scopo dell'immagine di riferimento, non solo il suo contenuto. "Abbina l'illuminazione e la palette dell'immagine di riferimento; cambia il soggetto in un vaso di ceramica" dà al modello un compito chiaro. Un prompt che ignora l'immagine di riferimento spreca l'input.
Verifica prima dell'invio
Le immagini di riferimento sono la causa più comune di errori nelle richieste. Controlla che l'URL sia accessibile pubblicamente (oppure che entrambi i lati del tuo sistema siano d'accordo sulla scadenza dell'URL firmato), che il tipo di file sia accettato dal modello e che l'immagine non sia così grande da causare un timeout dell'upload. Esegui questi controlli prima nel tuo codice: il costo di debug di una validazione client fallita è molto inferiore a quello di una richiesta rifiutata.
Gestire i job asincroni e fare polling dei risultati
La generazione con nano-banana-pro è asincrona. Costruisci il tuo client attorno a tre passaggi distinti: invio, polling, download. Fonderli in un'unica funzione rende difficile ragionare su retry e timeout.
Passaggio 1: invio
Invia la richiesta descritta sopra e memorizza l'identificatore del job restituito. Persisti quell'identificatore in un luogo durevole — una riga di database o un messaggio in coda — perché il tuo processo potrebbe riavviarsi tra l'invio e il completamento.
Passaggio 2: polling
Usa lo stesso URL di base e lo stesso header Authorization, includendo l'identificatore del job nella richiesta, per ottenere lo stato del job. Fai polling a intervalli invece di un tight loop; qualche secondo tra un controllo e l'altro è tipico, e se più controlli consecutivi restituiscono uno stato in attesa dovresti applicare un backoff.
import time
TERMINAL = {"succeeded", "failed"}
def wait_for_job(job_id, timeout=300, interval=3):
deadline = time.monotonic() + timeout
while time.monotonic() < deadline:
status = get_job_status(job_id) # same headers as submit
if status in TERMINAL:
return status
time.sleep(interval)
raise TimeoutError(f"job {job_id} did not finish in time")
Passaggio 3: rispettare gli stati
Tratta il campo di stato come un'enumerazione. Il job è ancora in esecuzione, completato con successo oppure fallito. Gestisci esplicitamente tutti e tre i casi: in caso di successo passa al download; in caso di fallimento leggi il messaggio di errore e valuta se il problema riguarda l'input o il prompt; in caso di timeout interrompi il polling ed esponi l'identificatore del job per indagini successive.
I retry appartengono a due livelli
I retry a livello di rete vanno applicati alla chiamata di invio e a ogni richiesta di polling, con un numero limitato di tentativi. I retry a livello di job sono diversi: se un job fallisce per un prompt o un'immagine di riferimento scadenti, reinviare lo stesso payload fallirà allo stesso modo. Ritenta il job stesso solo dopo aver modificato l'input.
Un pattern di produzione comune è avere un worker che gestisce il ciclo di polling, così le richieste web non vengono mai bloccate dalla generazione. Invia dal tuo handler API, passa l'identificatore del job al worker e notifica il client quando il worker ha finito.
Scaricare e salvare l'output 2K
La risposta finale del job punta all'immagine generata invece di incorporarla, il che significa che il download è un passaggio di cui devi occuparti tu.
Recuperare l'immagine
Quando il job riporta successo, la risposta contiene la posizione dell'output. Recuperala con una normale richiesta GET, poi scrivi i byte su file o trasmettili in streaming allo storage. In sviluppo, salva in una directory locale con un nome prevedibile costruito dall'identificatore del job, così puoi collegare il file al record del job.
import pathlib
import urllib.request
def save_image(url, job_id, out_dir="output"):
pathlib.Path(out_dir).mkdir(exist_ok=True)
target = pathlib.Path(out_dir) / f"nano-banana-pro-{job_id}.png"
with urllib.request.urlopen(url, timeout=60) as response:
target.write_bytes(response.read())
return target
Salvare correttamente
In produzione, trasmetti la risposta direttamente all'object storage invece di scriverla su disco locale, così il comportamento è coerente indipendentemente dal worker che gestisce il job. Registra nel database la chiave dell'oggetto e l'identificatore del job, e verifica che il content type e l'estensione del file corrispondano a ciò che il modello genera. Se le immagini verranno servite su una pagina web, genera le miniature nella stessa pipeline, così le pagine pubbliche non caricano mai il file completo a risoluzione 2K.
Pianificare la politica di conservazione
Gli output generati sono i tuoi dati. Decidi per quanto tempo conservarli, se serve il versionamento e se la posizione finale è qualcosa che la tua applicazione può rigenerare in caso di perdita. Se la risposta è no, salva insieme al payload della richiesta anche l'immagine, così un futuro bug o un cambio di modello non ti impedirà mai di riprodurre il risultato.
Punti di errore comuni e come fare debug
La maggior parte delle prime integrazioni fallisce per pochi motivi. Prima di ipotizzare un problema del modello, controlla questa lista punto per punto.
- Errori di autorizzazione. Prefisso
Bearermancante, chiave con un carattere di newline finale per via della copia da un file di ambiente, oppure chiave presa da un ambiente diverso da quello dell'URL di base impostato. - Content type non corrispondente. Inviare campi JSON con header multipart, o inviare file con
application/json, è la causa più comune di rifiuto delle richieste con immagine di riferimento. Per i corpi multipart, lascia che sia il client a impostare l'header. - Metodo o forma del corpo sbagliati. Usare GET invece di POST, oppure un
promptdi primo livello invece dell'oggetto annidatoinput, produce errori di validazione che sembrano del tutto scollegati. Confronta la tua richiesta byte per byte con la chiamatacurlverificata —curl -vmostra gli header effettivamente inviati. - Polling troppo veloce o assente. Richiedere frequentemente l'endpoint di stato porta al rate limiting; non fare polling non porta a nulla. Usa un intervallo fisso con backoff e un timeout massimo.
- URL di output scaduto. Se aspetti troppo tra il completamento del job e il download, l'URL firmato dell'output potrebbe scadere. Scarica subito dopo il successo, oppure prepara un percorso di riacquisizione per ottenere una nuova posizione.
- Fallimenti silenziosi nel codice. Registra sempre il codice di stato HTTP e il corpo della risposta in caso di errore. Il messaggio generico di un'eccezione lanciata dal client HTTP nasconde le parti utili della risposta.
Quando qualcosa non è chiaro, torna alla richiesta curl verificata della prima sezione. Se quella funziona e la tua chiamata Python no, la differenza tra le due è il bug.
Articoli correlati
Vedi tutti gli articoli →-
Tutoriale
Come chiamare hailuo-2.3-fast/image-to-video tramite l'API HiAPI: pratica con curl e Python
La prima richiesta funzionante per il livello image-to-video veloce ed economico — dall'ID del modello al download di un MP4
-
Tutoriale
Come chiamare hailuo-2.3/text-to-video tramite l'API HiAPI: curl, Python ed esempi di richiesta eseguibili
-
Tutoriale
Utilizzare Kandinsky 6.0 Pro su HiAPI per la generazione di video da testo: tutorial con curl e Python
Dimostrazione pratica guidata dalla richiesta: costruire la chiamata da prompt a clip video, inviare la richiesta, monitorare lo stato di completamento e scaricare il risultato