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.
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
imageen plus.
Appel minimal fonctionnel
hiapi expose tous les modèles d'image via la même interface de tâches asynchrones :
POST /v1/tasks— soumet une tâche et renvoie untaskId.- Soit vous interrogez
GET /v1/tasks/{taskId}jusqu'à ce questatus === "success", soit vous fournissezcallback.urlpour recevoir le résultat final via webhook. - 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(sansresolution) ; d'autres exigent des dimensions en pixels. gpt-image-2/image-to-image accepte la combinaisonaspect_ratio+resolutionillustrée ci-dessus — ne transmettez passize: "1024x1024"ici. - Le champ
imagecorrespond à 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 :
401 permission_deniedaccompagné de"This API key cannot use the selected model."— la clé n'est pas autorisée à utilisergpt-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.400accompagné deadditional properties not allowed— vous avez envoyé un champ que le modèle donné n'accepte pas (par exemplesizeau lieu deaspect_ratio). Le message d'erreur indique la clé fautive ; retirez-la et réessayez.status: "fail"lors du polling, accompagné d'un objetdata.error— le modèle lui-même a rejeté l'entrée (contenu non sûr, URL de référence injoignable, etc.). Journalisezerror.codeeterror.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
- Page du modèle gpt-image-2 — matrice des capacités et niveaux tarifaires.
- Tous les modèles hiapi — le catalogue complet si vous avez besoin d'autres modèles d'image ou de vidéo.
- Documentation de l'API — référence complète de
/v1/taskset de toute l'interface. - Comment générer des images avec l'API hiapi — le pendant texte-vers-image de cette recette.
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 →-
Tutoriel
Comment appeler hailuo-2.3-fast/image-to-video via l'API HiAPI : curl et Python en pratique
La première requête exploitable du palier image-vers-vidéo rapide et économique — de l'ID du modèle au téléchargement du MP4
-
Tutoriel
Comment appeler hailuo-2.3/text-to-video via l'API HiAPI : curl, Python et exemples de requêtes exécutables
-
Tutoriel
Utiliser Kandinsky 6.0 Pro texte-vers-vidéo sur HiAPI : tutoriel curl et Python
Démonstration pratique axée sur la requête : construire l'appel du prompt au clip vidéo, soumettre la requête, interroger l'état d'achèvement et télécharger le résultat