HiAPI
Blog

Tutoriale

Errore di input immagine su HiAPI: passa un URL accessibile pubblicamente, non Base64

Oct 22, 2026
Errore di input immagine su HiAPI: passa un URL accessibile pubblicamente, non Base64

I modelli image-to-image e con immagine di riferimento su HiAPI recuperano l'immagine sorgente da un URL HTTP(S) accessibile pubblicamente: non accettano stringhe di byte base64 e non riescono a raggiungere indirizzi privati. La trappola più comune è questa: un input immagine errato sembra andato a buon fine — POST /v1/tasks restituisce 200 con un taskId, e il vero fallimento emerge solo quando interroghi il task. I due tipi di fallimento che vedrai realmente sono questi:

{ "code": 200, "message": "success",
  "data": { "status": "fail", "model": "gpt-image-2/image-to-image", "storage": "temp", "taskId": "tk-...",
    "error": { "code": "INVALID_REQUEST",
      "message": "The image URL could not be downloaded. Please provide a reachable public HTTP(S) URL and try again." } } }
{ "code": 200, "message": "success",
  "data": { "status": "fail", "model": "gpt-image-2/image-to-image", "storage": "temp", "taskId": "tk-...",
    "error": { "code": "TASK_FAILED", "message": "task failed" } } }

Il primo è il ritorno per un URL irraggiungibile; il secondo è il risultato generico che ottieni quando passi un base64 data URI come immagine — nessun indizio, solo un task failed, ed è questo il punto in cui la maggior parte delle persone si blocca. Nota che il "message": "success" esterno indica solo che la richiesta di polling stessa è riuscita; il risultato vero è in data.status.

Cause comuni (in ordine di probabilità decrescente)

  • Hai incollato base64 nel campo immagine — una stringa data:image/...;base64,.... Questo campo vuole un URL che il server possa scaricare, non byte inline. Su gpt-image-2/image-to-image, il data URI viene accettato in fase di invio, poi il task termina con status: fail, codice errore TASK_FAILED / task failed.

  • L'URL non è raggiungibile pubblicamente. http://localhost, 127.0.0.1, IP di rete interna, file che richiedono login per essere visti, link pre-firmati scaduti: tutti falliscono con INVALID_REQUEST — "The image URL could not be downloaded…".

  • Nome del campo sbagliato (varia da modello a modello, vedi tabella sotto). Il campo di input immagine non è uniforme tra le famiglie di modelli. Un nome errato viene bloccato in fase di invio con HTTP 400, per esempio usando per errore image_url su gpt-image-2/image-to-image:

    { "code": 400, "data": null, "error_code": "INVALID_REQUEST",
      "message": "invalid input: input_urls: missing required field \"input_urls\"; <root>: additional properties 'image_url' not allowed" }
    
  • Hai usato il model id nudo per fare editing. Un id nudo (ad esempio gpt-image-2) è puro text-to-image, non definisce affatto il campo immagine, quindi il campo immagine viene rifiutato: 400 invalid input: <root>: additional properties 'input_urls' not allowed. Per fare editing usa l'id della route image-to-image: gpt-image-2/image-to-image.

Come leggere i codici di errore: capire se è un «problema di input» o un «problema upstream»

Dividi il ritorno in due fasi: fase di invio (la risposta diretta di POST /v1/tasks) e stato finale (data.status ottenuto interrogando GET /v1/tasks/<taskId>):

  • HTTP 400 in fase di invio, envelope piatto {"code":400,"data":null,"error_code":"INVALID_REQUEST","message":"invalid input: ..."} → c'è un problema nella struttura/campi della tua richiesta (problema di input). Il task non viene creato, nessun addebito. Basta correggere il nome del campo o il model id.
  • HTTP 401 in fase di invio, envelope annidato {"error":{"code":"permission_denied","type":"hiapi_error","request_id":"..."}} → è un problema di autenticazione (key errata o senza permessi), non di input.
  • HTTP 200 in fase di invio + taskId, ma al polling data.status: "fail": guarda data.error.code —
    • INVALID_REQUEST con message "could not be downloaded" → l'URL dell'immagine non è scaricabile (è comunque un tuo problema di input: sostituisci l'immagine con un URL raggiungibile pubblicamente).
    • TASK_FAILED con message "task failed" → fallimento generico, senza indizi. Escludi prima base64 / input errati; se dopo averli esclusi fallisce ancora, trattalo come problema di «generazione upstream».

In sintesi: i 4xx in fase di invio sono problemi a livello di richiesta / autenticazione, solo il fail in stato finale può coinvolgere il download o la generazione upstream; e in ogni caso, non farti ingannare dal "message":"success" esterno: fa sempre fede data.status.

Il nome del campo di input immagine varia da modello a modello

La tabella seguente è verificata empiricamente sugli input schema attuali dei rispettivi modelli (controlla comunque sempre la pagina del modello, i campi variano da famiglia a famiglia):

Model id (route image-to-image) Campo di input immagine Tipo
gpt-image-2/image-to-image input_urls array di stringhe
seedream-5.0-pro/image-to-image image_urls array di stringhe
nano-banana-pro image_input array di stringhe

Il campo va messo dentro l'oggetto input; la maggior parte dei modelli con immagine di riferimento richiede un array (anche se c'è una sola immagine).

Passi per la correzione

  1. Ospita l'immagine su un URL HTTP(S) accessibile pubblicamente. Caricala su qualsiasi object storage / CDN (Cloudflare R2, S3, GCS, ecc.) e imposta l'oggetto in lettura pubblica, oppure usa un URL pre-firmato ancora valido.
  2. Verifica che sia accessibile senza autenticazione. In una sessione pulita (o da una macchina diversa dalla tua) esegui curl -sI "<il-tuo-URL>": deve rispondere 200 con content-type image/*. Se richiede cookie, header o VPN, il server non riesce a scaricarla.
  3. Usa il model id image-to-image, non l'id nudo. Per fare editing chiama gpt-image-2/image-to-image (o la route i2i corrispondente al tuo modello), non gpt-image-2.
  4. Usa il nome del campo indicato nella documentazione di quel modello (input_urls / image_urls / image_input), dentro input.
  5. Non passare mai base64. Se hai solo i byte, prima caricali, poi passa l'URL ottenuto.
  6. Prima invia, poi interroga. GET /v1/tasks/<taskId> finché data.status non è success o fail. In caso di fallimento leggi data.error.message: se compare "could not be downloaded" è un problema di URL, non del tuo prompt.

Esempio minimo di verifica

Fai prima un controllo di connettività a costo zero: elencare i modelli non crea alcun task e non costa nulla.

curl -s https://api.hiapi.ai/v1/models \
  -H "Authorization: Bearer $HIAPI_API_KEY"

Se restituisce 200 con un array data, la tua key funziona. Una key errata restituisce 401 + {"error":{"code":"permission_denied", ... ,"type":"hiapi_error"}} — quello è un problema di autenticazione, non di input. Poi invia una richiesta image-to-image corretta: nel campo del modello metti un URL raggiungibile pubblicamente.

curl -s -X POST https://api.hiapi.ai/v1/tasks \
  -H "Authorization: Bearer $HIAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-image-2/image-to-image",
    "input": {
      "prompt": "把背景换成干净的影棚白",
      "input_urls": ["https://your-public-host.example.com/source.png"]
    }
  }'

Sostituisci input_urls con l'URL della tua immagine raggiungibile. Un invio riuscito restituisce data.taskId; poi interroga GET https://api.hiapi.ai/v1/tasks/<taskId> finché data.status non è success, e prendi il risultato da data.output[0].url (quell'URL ha una scadenza: scaricalo o copialo altrove appena possibile, non salvarlo come hotlink).

Link correlati

Domande frequenti

Posso passare base64 ai modelli image-to-image di HiAPI? No. Il campo immagine vuole un URL HTTP(S) pubblico che il server possa scaricare. Una stringa data:image/...;base64,... viene accettata in fase di invio da alcuni modelli, ma il task poi termina con status: fail, codice errore TASK_FAILED / task failed. Carica i byte in una posizione pubblica e passa l'URL.

Il mio POST /v1/tasks ha restituito 200, ma il task è fallito: perché? Il 200 in fase di invio indica solo che la richiesta è stata accettata. Il download dell'immagine e la generazione avvengono dopo. Interroga GET /v1/tasks/<taskId>: un input immagine errato si manifesta lì con data.status: fail, con error.code pari a INVALID_REQUEST ("The image URL could not be downloaded…") oppure TASK_FAILED.

In quale campo va messo esattamente l'URL dell'immagine? Dipende dal modello. gpt-image-2/image-to-image usa input_urls, seedream-5.0-pro/image-to-image usa image_urls, nano-banana-pro usa image_input (tutti array). Prima di inviare la richiesta, verifica lo schema attuale sulla pagina del modello.

Un URL localhost o privato va bene? No. HiAPI scarica le immagini dai propri server, quindi localhost, 127.0.0.1, indirizzi di rete interna, link visibili solo dopo il login e URL pre-firmati scaduti falliscono tutti con "The image URL could not be downloaded.". Usa un URL risolvibile pubblicamente e senza autenticazione.

Cosa significa additional properties 'input_urls' not allowed? Hai passato il campo immagine a un modello che non lo definisce — di solito perché hai usato l'id nudo text-to-image (gpt-image-2) invece della route image-to-image (gpt-image-2/image-to-image), oppure il nome del campo di un altro modello. È un 400 in fase di invio, vedi la guida 400 Bad Request sopra.

I task immagine falliti vengono addebitati? Le richieste respinte con 400 in fase di invio non vengono addebitate; ma un task accettato (200 + taskId) che fallisce in seguito può essere addebitato — vedi «Le richieste fallite vengono addebitate?» sopra. Quindi, prima di riprovare, correggi l'URL.

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