Tutoriel
Comment utiliser gpt-image-2.5-sunburst/image-to-image via l'API HiAPI : curl et Python
Requêtes exécutables, flux d'envoi d'images de référence et diagnostic d'erreurs pour les développeurs
Sur cette page
Ce que permet l'image-vers-image sur ce point de terminaison
Le point de terminaison gpt-image-2.5-sunburst/image-to-image suit une convention simple : vous envoyez une image de référence accompagnée d'une instruction d'édition en langage naturel, et le modèle renvoie une nouvelle image qui applique cette instruction tout en restant ancrée sur l'image de référence. Contrairement au texte-vers-image — qui part de zéro et repose entièrement sur votre prompt — l'image-vers-image utilise l'image de référence comme contexte visuel : la composition, le sujet, le style et les indices de couleur sont hérités, sauf si votre instruction demande explicitement de les modifier.
Cela en fait le bon choix dans les situations où vous disposez déjà d'un visuel existant et souhaitez une transformation contrôlée, par exemple changer le style d'une photo produit, modifier l'éclairage ou l'arrière-plan, ajuster l'apparence d'un sujet, ou générer des variantes d'un concept existant. Choisissez le texte-vers-image lorsque vous n'avez pas de source et recherchez une liberté créative maximale ; choisissez l'image-vers-image lorsque la fidélité à une image existante importe plus que la nouveauté.
Le modèle mental clé à retenir pour les développeurs : l'image de référence est une contrainte d'entrée, et l'instruction d'édition est l'incrément. Une bonne instruction décrit ce qui doit changer, pas tout ce qui doit exister. « Remplace l'arrière-plan par un dégradé de studio propre et neutre, en conservant le sujet et son ombre » fonctionne mieux qu'une description complète de scène, car l'image de référence fournit déjà la scène. Gardez cela à l'esprit en lisant la structure de requête ci-dessous — le corps de requête est petit, mais la qualité de l'instruction détermine la qualité de la sortie.
Prérequis et structure de la requête
Avant le premier appel, vérifiez que trois éléments sont en place :
- Une clé API, émise par votre compte HiAPI. Placez-la dans une variable d'environnement plutôt que dans le code source.
- L'URL de base, c'est-à-dire l'URL de base de l'API HiAPI, à consulter dans votre tableau de bord ou la documentation de référence de l'API.
- Le chemin du point de terminaison :
gpt-image-2.5-sunburst/image-to-image.
Chaque requête est une requête POST portant un corps JSON et un en-tête Authorization. Conceptuellement, le corps de requête comporte trois parties logiques :
- Sélection du modèle — l'identifiant de modèle de ce point de terminaison, afin que la passerelle route correctement l'appel.
- Entrée — l'image de référence (URL hébergée ou chaîne de données base64) et le texte de l'instruction d'édition.
- Contrôle de sortie — tout paramètre optionnel listé dans la documentation du point de terminaison, comme la taille ou le nombre. N'utilisez que les paramètres figurant dans la documentation de référence officielle ; ne devinez pas les noms.
Un conseil de discipline : comme il s'agit d'un point de terminaison hébergé, les champs réellement acceptés sont définis par la documentation de référence actuelle de l'API, et non par analogie avec d'autres API d'image. En cas de doute, envoyez d'abord un corps minimal valide (model, image, prompt), vérifiez qu'une réponse 200 est renvoyée, puis ajoutez les champs optionnels un par un. Ainsi, chaque panne peut être attribuée à une seule modification, plutôt qu'à un corps assemblé d'un coup.
Envoyer l'image de référence et l'instruction d'édition
Deux méthodes de fourniture de l'image de référence sont prises en charge, le choix dépendant principalement de l'emplacement des octets de l'image.
URL hébergée
Si l'image est accessible publiquement, transmettez directement son URL. Le corps de requête reste ainsi petit, la sérialisation est rapide, et c'est l'option la plus simple en phase de développement. L'URL doit être directement récupérable par le service — elle ne doit pas être derrière une authentification, ni une chaîne de redirections, ni une page HTML contenant accidentellement une image.
Données base64
Si l'image est locale ou privée, encodez-la et envoyez-la en ligne. Le base64 gonfle le corps de requête d'environ un tiers, ce qui peut approcher la limite de taille avec une grande source. Si vous approchez la limite, réduisez l'échantillonnage avant l'encodage.
Pièges de format et de taille
- Tenez-vous aux formats courants (PNG, JPEG, WebP) et assurez-vous que l'extension du fichier correspond aux octets réels.
- Les images trop volumineuses sont la cause la plus fréquente de rejet de requête. Choisissez une source de taille raisonnable ; un actif en pleine résolution n'est généralement pas nécessaire pour piloter une édition.
- Si vous construisez vous-même la chaîne base64, n'ajoutez le préfixe data URI que si les exemples de la documentation de référence de l'API le contiennent ; sinon, retirez-le. Mélanger ces deux conventions est une source courante d'erreurs « invalid image ».
Rédiger l'instruction d'édition
La qualité de la sortie dépend entièrement de l'instruction. Soyez précis sur ce qui doit changer et indiquez explicitement ce qui doit être conservé. Précisez la cible (« la veste »), la transformation (« recolorer en bleu marine profond ») et la contrainte (« conserver la pose du mannequin et les ombres existantes »). Évitez d'empiler plusieurs modifications sans rapport dans une seule instruction — si les changements sont indépendants, faites des appels séparés, ce qui rend aussi chaque résultat plus facile à évaluer.
Une requête curl exécutable
Voici une requête entièrement exécutable dans un terminal. Remplacez les espaces réservés de clé et d'image par vos propres valeurs.
curl -X POST "$HIAPI_BASE_URL/gpt-image-2.5-sunburst/image-to-image" \
-H "Authorization: Bearer $HIAPI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-image-2.5-sunburst/image-to-image",
"image": "https://your-cdn.example.com/reference.png",
"prompt": "Remplace l'arrière-plan par un dégradé de studio doux et neutre ; conserve le sujet, sa pose et les ombres existantes."
}'
Détail par détail :
-X POST— cette opération crée une nouvelle image, d'où l'usage de POST.- L'URL est formée par la concaténation de l'URL de base et du chemin du point de terminaison ; placer l'URL de base dans une variable d'environnement facilite le changement d'environnement.
Authorization: Bearer ...— votre clé API. Exportez-la sousHIAPI_API_KEYpour qu'elle n'apparaisse pas dans l'historique du shell ou les journaux.Content-Type: application/json— le corps est du JSON ; omettre cet en-tête est une cause courante de réponses 4xx déroutantes.model— l'identifiant du point de terminaison. Il doit être strictement identique à la documentation.image— l'image de référence, ici une URL hébergée. Pour utiliser plutôt du base64, remplacez par la chaîne de données ou une variable encodée localement.prompt— l'instruction d'édition. Contentez-vous d'indiquer le changement et ce qui doit être conservé.
Si vous voulez tester avec un fichier local sans encodage manuel, la plupart des shells permettent de construire le JSON avec un petit script ou jq ; l'essentiel est que le corps final soit un JSON valide contenant ces champs.
La même requête en Python
La version Python conserve exactement le même corps de requête, ce qui permet de comparer les réponses côte à côte. Utilisez requests :
import os
import requests
base_url = os.environ["HIAPI_BASE_URL"]
api_key = os.environ["HIAPI_API_KEY"]
payload = {
"model": "gpt-image-2.5-sunburst/image-to-image",
"image": "https://your-cdn.example.com/reference.png",
"prompt": (
"Remplace l'arrière-plan par un dégradé de studio doux et neutre ; "
"conserve le sujet, sa pose et les ombres existantes."
),
}
response = requests.post(
f"{base_url}/gpt-image-2.5-sunburst/image-to-image",
headers={
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json",
},
json=payload,
timeout=120,
)
response.raise_for_status()
print(response.json())
Deux points méritent l'attention. Premièrement, json=payload définit le type de contenu et sérialise le corps à votre place, éliminant toute une catégorie d'erreurs liées à l'assemblage manuel du JSON. Deuxièmement, timeout=120 est intentionnel : la génération d'images n'est pas instantanée, et un client qui attend indéfiniment est pire qu'un client qui échoue proprement. Adaptez le délai à votre charge de travail, mais définissez-le toujours.
Pour utiliser plutôt un fichier local, lisez ses octets, encodez-les en base64 et affectez le résultat à image. Avec une URL hébergée, conservez la chaîne telle quelle. Une fois que les appels curl et Python renvoient la même structure, vous avez confirmé que les deux se comportent de manière identique et pouvez poursuivre le développement à partir de l'un ou l'autre.
Diagnostiquer les échecs de requête courants
La plupart des échecs se rangent dans quatre catégories. Parcourez-les dans cet ordre, car chacune peut se déguiser en la suivante.
Erreurs d'authentification
Les codes 401 ou 403 signifient presque toujours une clé absente, mal formée ou expirée. Vérifiez que l'en-tête est exactement Authorization: Bearer <key>, assurez-vous qu'aucune guillemet ou retour à la ligne parasite n'a été introduit par copier-coller, et confirmez que la variable d'environnement est bien définie dans le shell ou le processus qui exécute la requête. Une clé qui fonctionne en curl mais pas en Python indique généralement une variable non définie, plutôt qu'une clé cassée.
Corps de requête mal formé
Un code 400 accompagné d'informations de validation signifie généralement un JSON invalide ou un champ obligatoire manquant. Affichez joliment le corps avant l'envoi, vérifiez que model correspond à l'identifiant du point de terminaison, et que le nom du champ d'instruction d'édition correspond à la documentation. En curl, les virgules finales et les guillemets simples sont les coupables classiques du JSON écrit à la main ; le json= de Python évite ces problèmes.
Entrée d'image invalide ou trop volumineuse
Si le service rejette l'image, vérifiez trois choses : l'URL est récupérable publiquement et renvoie bien une image (et non une redirection ou une page d'erreur), le format est pris en charge, et le corps de requête ne dépasse pas la limite de taille indiquée dans la documentation. Pour une entrée base64, vérifiez que l'encodage est propre et que la convention de préfixe data URI correspond à l'exemple de référence. En cas de doute, réduisez l'échantillonnage et réessayez — une source plus petite résout une bonne partie de ces erreurs.
Délais d'attente et incidents transitoires
Une génération longue peut dépasser le délai d'attente du client, tandis qu'une réponse 429 ou 5xx indique une limitation de débit ou un problème serveur transitoire. Distinguez-les des erreurs client : ne réessayez pas tel quel un 400, mais un 429 ou un 503 se prête à une nouvelle tentative avec backoff. Enregistrez le code d'état et le corps de réponse à chaque échec — un journal d'erreurs clair transforme le diagnostic de devinette en vérification point par point.
Du script au client réutilisable
Un script ponctuel prouve que le point de terminaison fonctionne ; une petite enveloppe le fait tourner de manière fiable dans un pipeline. Enveloppez l'appel dans une fonction responsable de trois choses : la requête, le délai d'attente et une stratégie de nouvelle tentative bornée.
import os
import time
import requests
class ImageEditClient:
def __init__(self, base_url: str, api_key: str, timeout: int = 120):
self.base_url = base_url.rstrip("/")
self.api_key = api_key
self.timeout = timeout
def edit(self, image: str, prompt: str, retries: int = 3):
url = f"{self.base_url}/gpt-image-2.5-sunburst/image-to-image"
headers = {
"Authorization": f"Bearer {self.api_key}",
"Content-Type": "application/json",
}
payload = {
"model": "gpt-image-2.5-sunburst/image-to-image",
"image": image,
"prompt": prompt,
}
last_error = None
for attempt in range(retries):
try:
resp = requests.post(
url, headers=headers, json=payload, timeout=self.timeout
)
except requests.Timeout as err:
last_error = err
time.sleep(2 ** attempt)
continue
if resp.status_code in (429, 500, 502, 503, 504):
last_error = RuntimeError(f"transient {resp.status_code}: {resp.text}")
time.sleep(2 ** attempt)
continue
if resp.status_code >= 400:
raise RuntimeError(f"request failed {resp.status_code}: {resp.text}")
return resp.json()
raise RuntimeError(f"exhausted retries: {last_error}")
Les choix de conception importent plus que le code lui-même. Les nouvelles tentatives ne s'appliquent qu'aux délais d'attente et aux codes d'état transitoires, jamais aux erreurs client 4xx, car réessayer un corps mal formé ne fait que gaspiller du quota. Le backoff exponentiel évite qu'un pipeline limité en débit ne martèle le point de terminaison. Les erreurs client sont levées immédiatement avec le corps de réponse, ce qui permet à l'appelant de voir exactement ce que le service refuse. Et centraliser l'identifiant de modèle à un seul endroit signifie que passer à un autre point de terminaison d'image ne demandera qu'une ligne de changement, sans avoir à fouiller toute la base de code.
Sur cette base, ajoutez une journalisation structurée à chaque tentative et effectuez une vérification de taille/forme avant que les consommateurs en aval n'utilisent la réponse. Lorsque vous serez prêt à explorer d'autres modèles d'image sur la même passerelle, le catalogue de modèles HiAPI est l'endroit idéal pour comparer les points de terminaison sans réécrire le client.
Articles similaires
Voir tous les articles →-
Tutoriel
Comment appeler kimi-k3.1-pro via l'API HiAPI : curl, Python et requêtes directement exécutables
Un guide d'intégration pratique couvrant les endpoints, les paramètres de requête, le streaming, les appels d'outils et le dépannage des erreurs
-
Tutoriel
API ElevenLabs Music sur HiAPI : générer de la musique avec curl, Python et des recettes de prompts
Un tutoriel pratique pour appeler elevenlabs/music-v2.5 via HiAPI, avec des recettes de prompts prêtes à copier pour le style, l'ambiance et la durée
-
Tutoriel
Comment utiliser gemini-omni-1.2-flash via l'API HiAPI : curl et Python