HiAPI
Blog

Tutoriel

Comment utiliser le mode image-à-image de gpt-image-2 via l'API hiapi

Une recette de code directement exécutable pour apprendre à appeler le point de terminaison image-à-image de gpt-image-2 sur hiapi : enveloppe de requête, paramètres d'image de référence et d'aspect_ratio, arbitrage entre polling et callback, ainsi que des exemples curl, Python et Node.js prêts à copier-coller.

Jun 26, 2026
Comment utiliser le mode image-à-image de gpt-image-2 via l'API hiapi

Cette recette vous montre pas à pas comment appeler le mode image-à-image de gpt-image-2 via l'API de tâches unifiée de hiapi. Vous obtiendrez un exemple curl directement exécutable, un script Python prêt à intégrer dans votre backend, une version Node.js adaptée aux environnements serverless, ainsi que les paramètres qui comptent vraiment et les pièges courants en production.

À la fin de cet article, vous disposerez d'un script qui prend une URL d'image de référence et un prompt, et renvoie l'URL d'une image générée, que vous pouvez télécharger directement ou transmettre à votre couche de stockage.

Préparation

  • Un compte hiapi et une clé API. Disponibles dans la console hiapi.
  • Une image de référence hébergée sur une URL HTTPS publique (ou une URL de données base64 — les deux fonctionnent).
  • Un prompt textuel décrivant ce que vous souhaitez que le modèle fasse avec cette image de référence.

C'est tout. Aucun SDK à installer — hiapi, c'est du HTTP + JSON, utilisable depuis n'importe quel langage capable d'envoyer une requête POST.

Vous voulez d'abord découvrir la génération d'images purement textuelle ? Consultez Comment générer des images avec l'API hiapi. Le schéma ci-dessous suit le même flux de tâches asynchrones, avec simplement un champ image en plus.

Appel minimal fonctionnel

hiapi expose tous les modèles d'image via la même interface de tâches asynchrones :

  1. POST /v1/tasks — soumet une tâche et renvoie un taskId.
  2. Soit vous interrogez GET /v1/tasks/{taskId} jusqu'à ce que status === "success", soit vous fournissez callback.url pour recevoir le résultat final via webhook.
  3. Lisez l'URL de l'image dans data.output[0].url, puis téléchargez-la ou stockez-la.

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 réponse immédiate vous donne l'identifiant de tâche :

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

Puis interrogez le résultat :

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

Une fois la tâche prête, la réponse ressemble à ceci :

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

output[0].url a une durée de validité limitée (notez expireAt), donc téléchargez-la immédiatement ou réhébergez-la dans votre propre stockage — ne fournissez jamais de lien direct à vos utilisateurs finaux.

Les paramètres qui comptent vraiment

Champ Type Description
model string Utilisez l'identifiant brut gpt-image-2/image-to-image. N'ajoutez pas de préfixe models/.
input.prompt string La transformation que vous souhaitez appliquer à l'image de référence.
input.image string URL HTTPS ou URL data:image/...;base64,....
input.aspect_ratio string L'une des valeurs : 1:1, 3:2, 2:3, 4:3, 3:4, 5:4, 4:5, 16:9, 9:16, 21:9 ou auto.
input.resolution string 1K, 2K ou 4K. Par défaut 1K.

Deux comportements importants :

  • Certains modèles hiapi n'acceptent que aspect_ratio (sans resolution) ; d'autres exigent des dimensions en pixels. gpt-image-2/image-to-image accepte la combinaison aspect_ratio + resolution illustrée ci-dessus — ne transmettez pas size: "1024x1024" ici.
  • Le champ image correspond à l'image de référence. Si vous passez une URL de données base64, assurez-vous que la charge utile reste sous la limite de taille du corps de requête de votre plateforme (quelques Mo passent sans problème ; les images de plusieurs mégaoctets doivent d'abord être téléversées puis transmises par URL).

Script Python de production

Cette version gère le polling avec échéance et se termine proprement en cas d'échec :

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))

Exécutez avec HIAPI_API_KEY=sk-... python recipe.py.

Node.js (fetch, sans dépendance)

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

Interroger toutes les 5 secondes convient à un script ponctuel, mais cela immobilise un worker pendant toute la durée de la tâche. Dans un vrai backend, vous préférerez généralement 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" }
}

Lorsque la tâche se conclut (succès ou échec), hiapi envoie en POST vers cette URL la même charge utile que celle obtenue via GET /v1/tasks/{id}. Traitez ce gestionnaire comme idempotent — des tentatives de renvoi sont possibles — et validez la requête avant de lui faire confiance (jeton de signature personnalisé dans l'URL, vérification de l'en-tête Authorization, etc.).

Un schéma propre consiste à : soumettre la tâche, persister le taskId avec votre propre identifiant de job comme clé, renvoyer 202 Accepted à l'appelant, et laisser le webhook effectuer le stockage puis la notification.

Gestion des erreurs

En pratique, vous rencontrerez trois modes d'échec :

  1. 401 permission_denied accompagné de "This API key cannot use the selected model." — la clé n'est pas autorisée à utiliser gpt-image-2/image-to-image. Vérifiez dans la console hiapi et confirmez sur la page tarifs que le modèle est inclus dans votre offre.
  2. 400 accompagné de additional properties not allowed — vous avez envoyé un champ que le modèle donné n'accepte pas (par exemple size au lieu de aspect_ratio). Le message d'erreur indique la clé fautive ; retirez-la et réessayez.
  3. status: "fail" lors du polling, accompagné d'un objet data.error — le modèle lui-même a rejeté l'entrée (contenu non sûr, URL de référence injoignable, etc.). Journalisez error.code et error.message, et ne réessayez pas automatiquement à l'aveugle.

Définissez toujours un délai d'attente de requête pour l'appel POST /v1/tasks (30 secondes suffisent — il renvoie rapidement le taskId), et un délai distinct plus long pour la boucle de polling ou le chemin de réception du webhook.

Liens utiles

Questions fréquentes

Q : gpt-image-2/image-to-image prend-il en charge plusieurs images de référence ? R : Le contrat minimal utilise un seul champ image. Si votre cas d'usage nécessite plusieurs images de référence (par exemple une image de sujet + une image de style), combinez-les d'abord en une seule, ou consultez la page du modèle pour les champs les plus récemment pris en charge.

Q : Puis-je transmettre un fichier local plutôt qu'une URL ? R : Oui — encodez-le en URL data:image/png;base64,... et passez-le comme input.image. Pour les fichiers dépassant environ 3 Mo, téléversez-les d'abord dans votre propre stockage et transmettez une URL publique ; c'est plus rapide et cela évite les limites de taille du corps de requête.

Q : Combien de temps prend une tâche ? R : La plupart des tâches image-à-image gpt-image-2 se terminent en 10 à 30 secondes en résolution 1K. Les résolutions plus élevées et les prompts complexes peuvent prendre plus de temps — par prudence, fixez un délai d'attente de polling de 5 minutes.

Q : Comment contrôler le degré d'écart entre la sortie et l'image de référence ? R : Exprimez-le explicitement dans le prompt. « Keep the subject's pose and composition, only restyle to watercolor » produit une cohérence plus stricte que « make this a watercolor ». Le mode image-à-image de gpt-image-2 est piloté par le prompt — il n'y a pas de curseur « strength » distinct dans l'enveloppe de requête.

Q : output[0].url est-elle permanente ? R : Non. Elle porte un horodatage expireAt (généralement quelques heures). Dès que la tâche réussit, téléchargez les octets et téléversez-les dans votre propre stockage (R2, S3, etc.).

Q : Combien coûte chaque image ? R : Cela dépend de votre offre et de la résolution. Consultez la page tarifs pour le coût actuel par appel.

Articles similaires

Voir tous les articles →

Commencez avec des artefacts IA persistants

Obtenez votre clé API et appelez des modèles d'image, de vidéo et d'audio via une API unique basée sur les tasks.

Lire la documentation de l'API