HiAPI
Blog

Tutoriale

Come usare gpt-image-2 image-to-image tramite l'API hiapi

Una ricetta di codice eseguibile che ti mostra come chiamare l'endpoint image-to-image di gpt-image-2 su hiapi: envelope della richiesta, immagine di riferimento e parametro aspect_ratio, scelta tra polling e callback, e esempi curl, Python e Node.js pronti da copiare e incollare.

Jun 26, 2026
Come usare gpt-image-2 image-to-image tramite l'API hiapi

Questa ricetta ti guiderà passo dopo passo su come chiamare la modalità image-to-image di gpt-image-2 tramite l'API unificata delle attività di hiapi. Otterrai un esempio curl eseguibile, uno script Python da integrare direttamente nel backend, una versione Node.js adatta agli scenari serverless, e i parametri che contano davvero più i dettagli che causano problemi in produzione.

Alla fine di questo articolo avrai uno script che riceve l'URL di un'immagine di riferimento e un prompt, e restituisce l'URL di un'immagine generata che puoi scaricare direttamente o affidare al tuo livello di archiviazione.

Preparazione

  • Un account hiapi e una chiave API. Puoi ottenerli nella console hiapi.
  • Un'immagine di riferimento ospitata su un URL HTTPS pubblico (oppure un data URL base64 — entrambi vanno bene).
  • Un prompt testuale che descriva cosa vuoi che il modello faccia con quell'immagine di riferimento.

Tutto qui. Nessun SDK da installare — hiapi è solo HTTP + JSON, qualsiasi linguaggio in grado di inviare richieste POST può essere usato.

Vuoi prima capire la generazione di immagini da solo testo? Consulta Come generare immagini con l'API hiapi. Lo schema sottostante è lo stesso flusso di attività asincrono, con in più un campo image.

Chiamata minima funzionante

hiapi espone tutti i modelli di immagini tramite la stessa interfaccia di attività asincrona:

  1. POST /v1/tasks — invia l'attività, restituisce un taskId.
  2. Esegui il polling di GET /v1/tasks/{taskId} finché status === "success", oppure fornisci callback.url per ricevere il risultato finale via webhook.
  3. Leggi l'URL dell'immagine da data.output[0].url e scaricala o archiviala.

curl

curl -X POST https://api.hiapi.ai/v1/tasks \
  -H "Authorization: Bearer sk-YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-image-2/image-to-image",
    "input": {
      "prompt": "transform the subject into a watercolor painting, soft pastel palette",
      "image": "https://example.com/reference.jpg",
      "aspect_ratio": "1:1",
      "resolution": "1K"
    }
  }'

La risposta immediata ti fornisce l'id dell'attività:

{ "data": { "taskId": "task_01HXXXX..." } }

Poi esegui il polling del risultato:

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

Quando l'attività è pronta, la risposta è simile a questa:

{
  "data": {
    "status": "success",
    "output": [{ "url": "https://cdn.hiapi.ai/...png", "expireAt": "..." }]
  }
}

output[0].url ha una validità limitata nel tempo (nota il campo expireAt), quindi scaricala subito o ricaricala nel tuo archivio — non fornire mai un hotlink agli utenti finali.

I parametri che contano davvero

Campo Tipo Descrizione
model string Usa l'id semplice gpt-image-2/image-to-image. Non aggiungere il prefisso models/.
input.prompt string La trasformazione che vuoi applicare all'immagine di riferimento.
input.image string URL HTTPS oppure URL data:image/...;base64,....
input.aspect_ratio string Uno dei seguenti valori: 1:1, 3:2, 2:3, 4:3, 3:4, 5:4, 4:5, 16:9, 9:16, 21:9 o auto.
input.resolution string 1K, 2K o 4K. Predefinito 1K.

Due comportamenti importanti:

  • Alcuni modelli hiapi accettano solo aspect_ratio (senza resolution); altri richiedono dimensioni in pixel. gpt-image-2/image-to-image accetta la combinazione aspect_ratio + resolution mostrata sopra — non passare qui size: "1024x1024".
  • Il campo image è l'immagine di riferimento. Se passi un data URL base64, assicurati che il payload sia sotto il limite del corpo della richiesta della tua piattaforma (qualche MB va bene, immagini di più megabyte dovrebbero essere prima caricate e poi passate come URL).

Script Python di livello produttivo

Questa versione gestisce il polling con una scadenza e termina in modo pulito in caso di fallimento:

import os
import time
import requests

API = "https://api.hiapi.ai/v1/tasks"
TOKEN = os.environ["HIAPI_API_KEY"]
HEADERS = {"Authorization": f"Bearer {TOKEN}", "Content-Type": "application/json"}


def submit(prompt: str, image_url: str, aspect_ratio: str = "1:1") -> str:
    payload = {
        "model": "gpt-image-2/image-to-image",
        "input": {
            "prompt": prompt,
            "image": image_url,
            "aspect_ratio": aspect_ratio,
            "resolution": "1K",
        },
    }
    r = requests.post(API, headers=HEADERS, json=payload, timeout=30)
    r.raise_for_status()
    return r.json()["data"]["taskId"]


def wait(task_id: str, timeout_s: int = 300, interval_s: int = 5) -> str:
    deadline = time.time() + timeout_s
    while time.time() < deadline:
        r = requests.get(f"{API}/{task_id}", headers=HEADERS, timeout=20)
        r.raise_for_status()
        task = r.json()["data"]
        status = task.get("status")
        if status == "success":
            return task["output"][0]["url"]
        if status == "fail":
            err = task.get("error") or {}
            raise RuntimeError(f"task failed: {err.get('code')} {err.get('message')}")
        time.sleep(interval_s)
    raise TimeoutError(f"task {task_id} did not finish in {timeout_s}s")


if __name__ == "__main__":
    task_id = submit(
        prompt="transform the subject into a watercolor painting, soft pastel palette",
        image_url="https://example.com/reference.jpg",
    )
    print("task:", task_id)
    print("url:", wait(task_id))

Esegui con HIAPI_API_KEY=sk-... python recipe.py.

Node.js (fetch, senza dipendenze)

const API = "https://api.hiapi.ai/v1/tasks";
const TOKEN = process.env.HIAPI_API_KEY;
const headers = {
  Authorization: `Bearer ${TOKEN}`,
  "Content-Type": "application/json",
};

async function submit(prompt, imageUrl, aspectRatio = "1:1") {
  const r = await fetch(API, {
    method: "POST",
    headers,
    body: JSON.stringify({
      model: "gpt-image-2/image-to-image",
      input: { prompt, image: imageUrl, aspect_ratio: aspectRatio, resolution: "1K" },
    }),
  });
  const data = await r.json();
  if (!r.ok) throw new Error(JSON.stringify(data));
  return data.data.taskId;
}

async function wait(taskId, timeoutMs = 300000, intervalMs = 5000) {
  const deadline = Date.now() + timeoutMs;
  while (Date.now() < deadline) {
    const r = await fetch(`${API}/${taskId}`, { headers });
    const task = (await r.json()).data;
    if (task.status === "success") return task.output[0].url;
    if (task.status === "fail") throw new Error(JSON.stringify(task.error));
    await new Promise((res) => setTimeout(res, intervalMs));
  }
  throw new Error(`task ${taskId} timed out`);
}

(async () => {
  const id = await submit(
    "transform the subject into a watercolor painting, soft pastel palette",
    "https://example.com/reference.jpg",
  );
  console.log("task:", id, "\nurl:", await wait(id));
})();

Polling vs. callback

Eseguire il polling ogni 5 secondi va bene per uno script una tantum, ma occupa un worker per tutta la durata dell'attività. In un backend reale di solito vuoi un webhook:

{
  "model": "gpt-image-2/image-to-image",
  "input": { "prompt": "...", "image": "https://example.com/reference.jpg" },
  "callback": { "url": "https://your-app.example.com/api/hiapi-callback", "when": "final" }
}

Quando l'attività si conclude (con successo o fallimento), hiapi invia tramite POST a quell'URL lo stesso payload che ottieni da GET /v1/tasks/{id}. Considera quel gestore come idempotente — i retry sono possibili — e verifica prima di fidarti della richiesta (un token di firma tuo nell'URL, controllo dell'header Authorization, ecc.).

Un pattern pulito è: invia l'attività, persisti il taskId con la tua job id come chiave, restituisci 202 Accepted al chiamante, e lascia che il webhook si occupi di archiviazione e notifica.

Gestione degli errori

In pratica incontrerai tre modalità di fallimento:

  1. 401 permission_denied con "This API key cannot use the selected model." — la chiave non è autorizzata a usare gpt-image-2/image-to-image. Controlla nella console hiapi e verifica nella pagina dei prezzi che il modello sia incluso nel tuo piano.
  2. 400 con additional properties not allowed — hai inviato un campo che quel modello specifico non accetta (ad esempio size invece di aspect_ratio). Il messaggio di errore indica la chiave non valida; rimuovila e riprova.
  3. status: "fail" durante il polling con un oggetto data.error — il modello stesso ha rifiutato l'input (contenuto non sicuro, URL di riferimento non raggiungibile, ecc.). Registra nei log error.code e error.message, non riprovare automaticamente alla cieca.

Imposta sempre un timeout per la chiamata a POST /v1/tasks (30 secondi sono sufficienti — restituisce rapidamente il taskId), e un timeout separato e più lungo per il ciclo di polling o per il percorso di ricezione del webhook.

Link correlati

Domande frequenti

D: gpt-image-2/image-to-image supporta più immagini di riferimento? R: Il contratto minimo usa un singolo campo image. Se il tuo caso d'uso richiede più immagini di riferimento (ad esempio un'immagine del soggetto + un'immagine di stile), combinale prima in una sola, oppure consulta la pagina del modello per i campi supportati più recenti.

D: Posso passare un file locale invece di un URL? R: Sì — codificalo come URL data:image/png;base64,... e passalo come input.image. Per file superiori a circa 3 MB, caricali prima nel tuo archivio e passa un URL pubblico; è più veloce ed evita i limiti del corpo della richiesta.

D: Quanto tempo richiede un'attività? R: La maggior parte delle attività image-to-image di gpt-image-2 si completa in 10–30 secondi con risoluzione 1K. Risoluzioni più alte e prompt complessi possono richiedere più tempo — per sicurezza, imposta il timeout di polling a 5 minuti.

D: Come posso controllare quanto l'output differisce dall'immagine di riferimento? R: Esprimilo esplicitamente nel prompt. "Keep the subject's pose and composition, only restyle to watercolor" produce una coerenza più stretta rispetto a "make this a watercolor". La modalità image-to-image di gpt-image-2 è guidata dal prompt — nell'envelope della richiesta non c'è un cursore "strength" separato.

D: output[0].url è permanente? R: No. Ha un timestamp expireAt (di solito qualche ora). Dopo il successo dell'attività, scarica i byte il prima possibile e caricali nel tuo archivio (R2, S3, ecc.).

D: Quanto costa ogni immagine? R: Dipende dal tuo piano e dalla risoluzione. Il costo attuale per chiamata è nella pagina dei prezzi.

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