HiAPI
Blog

Tutoriel

Comment utiliser gpt-image-2/text-to-image via l'API hiapi : paramètres, code et exemples exécutables

Jun 25, 2026
Comment utiliser gpt-image-2/text-to-image via l'API hiapi : paramètres, code et exemples exécutables

Ce tutoriel présente le minimum de code nécessaire pour générer une image avec gpt-image-2/text-to-image via l'API unifiée de tâches hiapi, puis explique chaque paramètre un par un, ainsi que les modèles de production à adopter une fois le code fonctionnel (callbacks, idempotence, gestion des erreurs).

Prérequis

Vous avez besoin d'une clé API. Créez-la depuis la page des clés API de la console hiapi — les clés commencent par sk-. La page du modèle gpt-image-2/text-to-image indique le prix actuel par image ; le détail complet se trouve sur la page de tarification.

Tous les appels de ce guide ciblent le point de terminaison unifié des tâches asynchrones :

  • POST https://api.hiapi.ai/v1/tasks — créer une tâche de génération
  • GET https://api.hiapi.ai/v1/tasks/{taskId} — interroger l'état de la tâche

La documentation de référence générale de la plateforme se trouve dans la documentation de l'API hiapi.

Exemple minimal exécutable (curl)

Une génération unique est une interaction en deux étapes : créer la tâche, puis attendre qu'elle se termine.

# 1. Create the task
curl -s -X POST https://api.hiapi.ai/v1/tasks \
  -H "Authorization: Bearer sk-YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-image-2/text-to-image",
    "input": {
      "prompt": "a calico cat curled up on a sunlit windowsill, soft focus background",
      "aspect_ratio": "1:1",
      "resolution": "1K"
    }
  }'
# => {"code":200,"data":{"taskId":"tk-hiapi-01KVY...."},"message":"success"}

# 2. Poll until status == "success"
TASK_ID="tk-hiapi-01KVY...."
curl -s "https://api.hiapi.ai/v1/tasks/$TASK_ID" \
  -H "Authorization: Bearer sk-YOUR_KEY"
# => {"code":200,"data":{"status":"success","output":[{"url":"https://..."}], ...}}

L'URL de l'image se trouve dans data.output[0].url. Téléchargez-la immédiatement — output[0].expireAt est très court, donc cette URL sert uniquement à la récupération, pas à une intégration permanente.

Python : création + interrogation + enregistrement sur disque

import os
import time
import urllib.request
import requests  # pip install requests

API_BASE = "https://api.hiapi.ai/v1/tasks"
TOKEN = os.environ["HIAPI_API_KEY"]  # sk-...

def create_task(prompt: str, aspect_ratio: str = "1:1", resolution: str = "1K") -> str:
    payload = {
        "model": "gpt-image-2/text-to-image",
        "input": {
            "prompt": prompt,
            "aspect_ratio": aspect_ratio,
            "resolution": resolution,
        },
    }
    r = requests.post(API_BASE, json=payload,
                      headers={"Authorization": f"Bearer {TOKEN}"},
                      timeout=60)
    r.raise_for_status()
    body = r.json()
    if body.get("error"):
        raise RuntimeError(f"create failed: {body['error']}")
    return body["data"]["taskId"]

def wait_task(task_id: str, timeout_s: int = 600, poll_s: int = 5) -> dict:
    deadline = time.time() + timeout_s
    while time.time() < deadline:
        r = requests.get(f"{API_BASE}/{task_id}",
                         headers={"Authorization": f"Bearer {TOKEN}"},
                         timeout=30)
        r.raise_for_status()
        task = r.json().get("data") or {}
        status = task.get("status")
        if status == "success":
            return task
        if status == "fail":
            raise RuntimeError(f"task failed: {task.get('error')}")
        time.sleep(poll_s)
    raise TimeoutError(f"task {task_id} did not finish in {timeout_s}s")

if __name__ == "__main__":
    task_id = create_task(
        "a calico cat curled up on a sunlit windowsill, soft focus background",
        aspect_ratio="3:2",
        resolution="1K",
    )
    task = wait_task(task_id)
    url = task["output"][0]["url"]
    urllib.request.urlretrieve(url, "cat.png")
    print(f"saved cat.png from task {task_id}")

Node.js : le même flux avec fetch

// Node 18+ has global fetch
const API_BASE = "https://api.hiapi.ai/v1/tasks";
const TOKEN = process.env.HIAPI_API_KEY;

async function createTask(prompt, aspectRatio = "1:1", resolution = "1K") {
  const res = await fetch(API_BASE, {
    method: "POST",
    headers: {
      "Authorization": `Bearer ${TOKEN}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      model: "gpt-image-2/text-to-image",
      input: { prompt, aspect_ratio: aspectRatio, resolution },
    }),
  });
  const body = await res.json();
  if (body.error) throw new Error(`create failed: ${body.error.code} ${body.error.message}`);
  return body.data.taskId;
}

async function waitTask(taskId, { timeoutMs = 600_000, pollMs = 5_000 } = {}) {
  const deadline = Date.now() + timeoutMs;
  while (Date.now() < deadline) {
    const res = await fetch(`${API_BASE}/${taskId}`, {
      headers: { "Authorization": `Bearer ${TOKEN}` },
    });
    const task = (await res.json()).data || {};
    if (task.status === "success") return task;
    if (task.status === "fail") throw new Error(`task failed: ${JSON.stringify(task.error)}`);
    await new Promise(r => setTimeout(r, pollMs));
  }
  throw new Error(`task ${taskId} timed out`);
}

(async () => {
  const id = await createTask(
    "a calico cat curled up on a sunlit windowsill, soft focus background",
    "16:9",
    "1K",
  );
  const task = await waitTask(id);
  const url = task.output[0].url;
  const img = await fetch(url).then(r => r.arrayBuffer());
  const { writeFileSync } = await import("node:fs");
  writeFileSync("cat.png", Buffer.from(img));
  console.log(`saved cat.png from task ${id}`);
})();

Référence des paramètres

Le corps de la requête contient toujours deux champs de premier niveau : model (chaîne, ID de modèle brut gpt-image-2/text-to-image) et input (objet de paramètres propre à chaque modèle).

Champ input Obligatoire Type Description
prompt Oui string Description textuelle de l'image souhaitée.
aspect_ratio Oui string L'une des valeurs suivantes : 1:1, 3:2, 2:3, 4:3, 3:4, 5:4, 4:5, 16:9, 9:16, 21:9 ou auto.
resolution Non string 1K (par défaut), 2K ou 4K. Les dimensions en pixels s'ajustent selon le rapport d'aspect choisi.
callback Non object { "url": "https://yours.example/hook", "when": "final" } — voir la section suivante.

Une création réussie renvoie {"code":200, "data":{"taskId":"tk-hiapi-..."}, "message":"success"}. Le champ data.status renvoyé par GET /v1/tasks/{taskId} vaut handling, success ou fail ; en cas de succès, data.output est un tableau dont le premier élément contient l'url de l'image et l'horodatage expireAt.

Les autres modèles d'image hiapi (par exemple z-image, qwen-image) utilisent des champs input légèrement différents — aspect_ratio est la convention adoptée par gpt-image-2/text-to-image. Lorsque vous changez de modèle, consultez la page du modèle pour confirmer la structure exacte de input.

Modèles de production

Utiliser des callbacks au lieu de l'interrogation

Interroger toutes les 5 secondes convient au prototypage, mais pour le trafic de production, vous voulez que hiapi vous pousse les tâches terminées afin de libérer vos workers. Ajoutez un bloc callback dans input :

{
  "model": "gpt-image-2/text-to-image",
  "input": {
    "prompt": "an astronaut sketching the moon",
    "aspect_ratio": "3:2",
    "resolution": "1K",
    "callback": {
      "url": "https://your-app.example.com/webhooks/hiapi",
      "when": "final"
    }
  }
}

when: "final" se déclenche une fois lorsque la tâche atteint un état terminal (success ou fail). La structure de la charge utile reçue par votre point de terminaison est identique à celle de GET /v1/tasks/{id}, donc le gestionnaire peut réutiliser la logique d'analyse de l'interrogation. Vérifiez le taskId par rapport à celui que vous avez stocké lors de la création de la tâche, afin de savoir à quelle requête appartient le callback.

Rendre l'opération de création idempotente

Si un worker plante après POST /v1/tasks mais avant d'avoir stocké le taskId, vous risquez de générer deux fois la même image. La solution la moins coûteuse : au moment de recevoir la réponse de création, stockez (your_request_id → taskId) en base de données dans la même transaction que la soumission de la requête. Si le worker réessaie, il trouvera le taskId existant et reprendra l'interrogation au lieu de créer une nouvelle tâche.

Gérer correctement les erreurs d'authentification

En cas d'échec d'authentification, hiapi renvoie HTTP 200 avec une charge utile d'erreur intégrée dans le corps de la réponse :

{"error":{"code":"permission_denied","message":"This API key cannot use the selected model. ...","type":"hiapi_error"}}

Ainsi, un code de statut 200 ne signifie pas à lui seul le succès. Vérifiez toujours d'abord body.error ; s'il est présent, examinez error.code (permission_denied, invalid_request, etc.) et error.message. Le request_id présent dans le message est ce que vous collez dans un ticket de support lorsque vous avez besoin d'aide.

Télécharger immédiatement, réhéberger vous-même

data.output[0].url est une URL à durée de vie courte — la réponse contient expireAt. Ne placez pas directement l'URL hiapi dans un <img src> de votre produit ; dès que la tâche réussit, téléchargez immédiatement le flux d'octets, téléversez-le vers votre propre stockage (S3, R2, Supabase Storage, etc.), puis servez-le depuis là.

Définir des délais d'attente raisonnables

Une valeur par défaut raisonnable : délai d'attente de 60 secondes pour la requête POST (la création de tâche est rapide — vous attendez en réalité juste la confirmation de réception de l'API), budget total de 10 minutes pour la boucle d'interrogation, intervalle d'interrogation de 5 secondes. Une tâche qui dépasse 10 minutes signifie presque toujours que la tâche est passée silencieusement en état fail, donc expirer et journaliser le dernier corps de réponse de la tâche est plus utile qu'attendre indéfiniment.

Questions fréquentes

Quelle est la différence entre gpt-image-2 et gpt-image-2/text-to-image ?

gpt-image-2 est la famille de modèles ; gpt-image-2/text-to-image est le point de terminaison spécifique que vous appelez pour transformer un prompt texte en une nouvelle image. Les autres variantes de cette famille exposent des structures input différentes (par exemple, l'édition d'image accepte une image de référence). En cas de doute, utilisez l'ID de modèle brut que vous voyez sur la page du modèle.

À quoi sert aspect_ratio: auto ?

auto laisse le modèle décider du rapport d'aspect en fonction du prompt. Utilisez-le lorsque vous n'avez pas d'exigence de mise en page forte ; sinon, fixez vous-même le ratio afin que le recadrage en aval soit prévisible.

Pourquoi ma requête renvoie-t-elle HTTP 200 avec permission_denied ?

Soit la clé API est incorrecte (faute de frappe, révoquée, préfixe sk- manquant), soit le forfait de cette clé n'inclut pas gpt-image-2/text-to-image. Ouvrez la console des clés API, vérifiez la chaîne de la clé et consultez votre forfait sur la page de tarification. Vérifiez toujours body.error.code — ne vous fiez jamais au seul code de statut HTTP.

Puis-je générer plusieurs images en une seule requête ?

gpt-image-2/text-to-image ne génère qu'une seule image par tâche — data.output est un tableau, mais sa longueur est toujours de 1 pour ce modèle. Pour générer N variantes, lancez N tâches en parallèle et utilisez le mode callback ci-dessus afin de ne pas garder N workers occupés à attendre.

Comment annuler une tâche en cours d'exécution ?

L'API unifiée de tâches ne propose actuellement pas de point de terminaison d'annulation. La mitigation la plus simple consiste à ce que le worker côté client abandonne le résultat lorsque l'utilisateur n'en a plus besoin — la génération déjà exécutée sera tout de même facturée, donc le bon endroit pour imposer une annulation est avant l'appel à POST /v1/tasks.

Comment basculer vers un autre modèle d'image ?

Changez model pour le nouvel ID brut (par exemple z-image/text-to-image) et ajustez input pour correspondre à la structure de ce modèle. Les structures ne sont pas identiques d'un modèle à l'autre — certains acceptent size, d'autres aspect_ratio, et quelques-uns n'acceptent pas resolution. Le catalogue de modèles liste tous les modèles disponibles, et chaque page de modèle documente ses champs input.

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