Tutoriel
Comment utiliser imagen4-ultra via l'API HiAPI : exemples curl et Python
Un exercice pratique complet de requête pour la génération d'images de haute qualité à partir de texte sur HiAPI
Ce que imagen4-ultra sur HiAPI peut vous offrir
imagen4-ultra est le modèle de génération d'images de haute qualité à partir de texte de HiAPI : vous envoyez un prompt et recevez une image générée. Ce qui le rend vraiment pratique pour les développeurs, c'est qu'il fonctionne, comme tous les autres modèles de la plateforme, derrière l'interface unifiée de HiAPI. Ainsi, la méthode d'authentification, la structure des requêtes et le mode de traitement des tâches que vous apprenez ici sont directement réutilisables sur les autres endpoints.
Ce tutoriel est un exercice pratique exécutable, et non une simple énumération de paramètres. À la fin de votre lecture, vous disposerez de :
- une requête
curldirectement copiable-collable pour soumettre une tâche de génération d'image à partir de texte, - un petit client Python réécrit à partir de la même requête,
- une compréhension claire de l'impact du rapport hauteur/largeur et des autres options sur le résultat,
- et d'une boucle de polling pour attendre la fin de la tâche et enregistrer l'image sur le disque.
Une mise au point préalable : la génération d'images n'est pas instantanée. imagen4-ultra fonctionne de manière asynchrone : vous soumettez une tâche, obtenez un identifiant de tâche, puis effectuez un polling jusqu'à ce que le rendu soit terminé. Si vous avez déjà utilisé d'autres endpoints asynchrones de HiAPI, ce flux vous sera familier ; sinon, la section sur le polling couvre l'intégralité du cycle de vie.
Nous resterons toujours dans le périmètre de l'API propre à HiAPI : pas de SDK spécifique à un fournisseur, pas de console tierce. Une URL de base, une clé, un format de requête.
Avant d'envoyer la première requête
Trois éléments sont nécessaires pour que le premier appel aboutisse.
1. Une clé API
Générez une clé depuis la console de votre compte HiAPI. Traitez-la comme un mot de passe : stockez-la dans une variable d'environnement plutôt que de la coller directement dans un fichier source.
export HIAPI_API_KEY="your-key-here"
2. L'URL de base
Toutes les requêtes HiAPI sont envoyées vers le même hôte API documenté dans la documentation de la plateforme. Centralisez-la à un seul endroit dans votre code, pour éviter de la coder en dur à plusieurs endroits :
export HIAPI_BASE_URL="https://api.hiapi.ai"
Si votre compte ou votre région utilise un autre hôte, utilisez la valeur indiquée dans la console : les chemins de requête ci-dessous restent inchangés.
3. Comment transmettre les informations d'authentification
HiAPI utilise un jeton bearer dans l'en-tête Authorization. Chaque requête — qu'il s'agisse de soumission ou de polling — porte les deux mêmes en-têtes :
Authorization: Bearer $HIAPI_API_KEY
Content-Type: application/json
C'est tout pour l'authentification. Pas d'étape de signature de requête, pas d'échange de jeton à chaque appel. Si vous savez définir des en-têtes, vous savez appeler cette API.
Avant de continuer, une vérification de base : assurez-vous que votre clé est exportée dans la même session shell que celle où vous exécuterez curl. Une proportion considérable des signalements de « 401 Unauthorized » se résume finalement à une clé exportée dans un onglet de terminal et utilisée dans un autre.
Dans ce qui suit, nous supposerons systématiquement que l'identifiant du modèle est imagen4-ultra. Si vous souhaitez vérifier la chaîne exacte exposée par votre compte, consultez la liste des modèles dans la documentation.
La requête curl exécutable
Voici une requête de soumission complète. Elle envoie le prompt, définit le rapport hauteur/largeur de sortie et demande la génération d'une seule image.
curl -sS -X POST "$HIAPI_BASE_URL/v1/images/generations" \
-H "Authorization: Bearer $HIAPI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "imagen4-ultra",
"prompt": "A lone lighthouse on a rocky coast at dusk, long exposure, dramatic clouds, cinematic lighting",
"aspect_ratio": "16:9",
"n": 1
}'
Détail champ par champ du corps de la requête :
model— l'identifiant du modèle que vous appelez. Il détermine le routage de la requête ; sans lui, l'API ne peut pas savoir quel modèle exécuter.prompt— la description en langage naturel de l'image. C'est le principal levier influençant la qualité du résultat. Soyez précis sur le sujet, l'éclairage, le style et la composition ; un prompt vague ne produira que des images vagues.aspect_ratio— la forme du canevas de sortie, exprimée en largeur:hauteur. Nous détaillerons cela plus loin.n— le nombre d'images à générer pour cette soumission. Gardez-le à1pendant les tests, afin que le coût de chaque exécution soit facile à calculer.
Selon la configuration de l'endpoint, la réponse contient soit l'image déjà terminée, soit — plus couramment pour ce type de modèle — un objet de tâche avec un identifiant et un champ de statut. Capturez cet identifiant ; la section sur le polling en dépend.
# 提交响应的典型结构
{
"id": "job_abc123",
"status": "queued"
}
Passez la réponse dans un formateur JSON (avec | jq . si disponible) pour pouvoir lire les noms de champs en fonction de la réponse de votre compte, plutôt que de plisser les yeux sur une seule ligne.
Écrire la même requête en Python
La version Python est une traduction ligne par ligne : même URL, mêmes en-têtes, même corps de requête. L'utilisation de requests rend la correspondance évidente :
import os
import requests
API_KEY = os.environ["HIAPI_API_KEY"]
BASE_URL = os.environ.get("HIAPI_BASE_URL", "https://api.hiapi.ai")
headers = {
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json",
}
payload = {
"model": "imagen4-ultra",
"prompt": "A lone lighthouse on a rocky coast at dusk, long exposure, dramatic clouds, cinematic lighting",
"aspect_ratio": "16:9",
"n": 1,
}
response = requests.post(
f"{BASE_URL}/v1/images/generations",
headers=headers,
json=payload,
timeout=30,
)
response.raise_for_status()
job = response.json()
print(job["id"], job["status"])
Lorsque vous intégrerez ce code dans un vrai service, plusieurs points méritent d'être conservés :
- Lisez la clé depuis une variable d'environnement, jamais depuis une valeur littérale dans un fichier. L'écriture
os.environ[...]échoue explicitement si la variable est absente, ce qui est précisément le comportement souhaité. - Définissez un timeout explicite pour l'appel de soumission. La tâche elle-même s'exécute de manière asynchrone, donc la requête HTTP doit revenir rapidement ; une limite de 30 secondes permet de détecter les problèmes réseau au lieu de laisser le programme se bloquer.
- Appelez
raise_for_status()avant de manipuler le JSON. Le corps d'une réponse 4xx n'a pas la structure attendue ; échouer tôt donne une trace plus claire qu'unKeyErrorlevé trois lignes plus loin. - Réutilisez
requests.Sessionsi vous soumettez un grand nombre de tâches — le pool de connexions compte plus qu'il n'y paraît.
Si vous préférez httpx ou aiohttp, la conversion est mécanique : même dictionnaire d'en-têtes, même corps JSON, même chemin. La requête elle-même est indépendante de la bibliothèque HTTP.
Rapport hauteur/largeur et options de requête
Le rapport hauteur/largeur est l'option que vous ajusterez le plus souvent, car il modifie à la fois la composition et les dimensions de sortie utilisables pour la mise en page en aval.
Le rapport hauteur/largeur est transmis dans le corps de la requête sous forme de chaîne "largeur:hauteur" — "1:1", "16:9", "9:16", "4:3", "3:2", etc. Choisissez un ratio correspondant à l'usage final de l'image :
1:1— avatars, vignettes produit, posts sociaux recadrés en carré.16:9/9:16— bannières principales, miniatures vidéo, emplacements au format story vertical.4:3/3:2— compositions photographiques classiques, mises en page de galerie.
Définissez le ratio de manière réfléchie, plutôt que de générer un carré puis de recadrer. Le recadrage élimine des pixels que vous avez déjà payés pour générer, et peut couper le sujet hors du cadre. Si vous connaissez l'emplacement final, encodez-le dans la requête.
Outre le rapport hauteur/largeur, les options importantes au quotidien sont :
prompt— toujours l'entrée la plus influente. Itérez ici avant d'itérer ailleurs.n— le nombre d'images générées par soumission. Utile lorsque vous voulez plusieurs variantes pour choisir ; gardez une valeur basse pendant la phase d'exploration du prompt.model— l'identifiant exact de la variante du modèle. Si votre compte expose plusieurs modèles d'image, c'est le commutateur entre eux.
Tenez-vous-en aux paramètres documentés pour cet endpoint, sans deviner les noms. Les champs inconnus sont une cause fréquente de réponses 400, et une option mal orthographiée passe facilement inaperçue dans un corps de requête volumineux. En cas de doute, envoyez d'abord un corps minimal — model, prompt, aspect_ratio —, vérifiez qu'il fonctionne, puis ajoutez les options une par une.
Polling d'une tâche asynchrone et téléchargement du résultat
La génération d'images prend du temps, donc l'appel de soumission renvoie une tâche, pas une image. Le cycle de vie est : soumettre → poller le statut → télécharger la sortie.
Étape 1 : soumettre et capturer l'ID de tâche
Réutilisez la requête précédente et extrayez l'id de la réponse :
job = response.json()
job_id = job["id"]
Étape 2 : poller jusqu'à ce que la tâche atteigne un état terminal
Interrogez l'endpoint de statut avec les mêmes en-têtes d'authentification, en dormant entre chaque tentative. Augmentez progressivement l'intervalle pour ne pas surcharger l'API :
import time
def wait_for_job(job_id, headers, base_url, timeout=300):
deadline = time.time() + timeout
delay = 2
while time.time() < deadline:
r = requests.get(
f"{base_url}/v1/images/generations/{job_id}",
headers=headers,
timeout=30,
)
r.raise_for_status()
data = r.json()
status = data["status"]
if status == "succeeded":
return data
if status == "failed":
raise RuntimeError(f"job failed: {data}")
time.sleep(delay)
delay = min(delay * 2, 15)
raise TimeoutError(f"job {job_id} not finished within {timeout}s")
Détails essentiels : une échéance stricte, un plafond sur l'intervalle de backoff, et une branche explicite pour l'état d'échec, afin que les tâches problématiques se manifestent sous forme d'exception plutôt que de rester bloquées indéfiniment.
Étape 3 : télécharger l'image
La réponse d'une tâche terminée contient l'emplacement de la sortie — une URL ou une référence d'artefact équivalente. Récupérez-la et écrivez les octets sur le disque :
result = wait_for_job(job_id, headers, BASE_URL)
image_url = result["output"][0]["url"]
img = requests.get(image_url, timeout=60)
img.raise_for_status()
with open("lighthouse.png", "wb") as f:
f.write(img.content)
Deux habitudes qui évitent la plupart des incidents en production : écrivez toujours en mode binaire ("wb"), jamais en mode texte ; et considérez l'URL de téléchargement comme temporaire — enregistrez immédiatement le fichier dans votre propre stockage, plutôt que de compter sur la validité indéfinie du lien.
Erreurs courantes et solutions
La plupart des échecs se classent en quelques catégories. Voici, pour chacune, la manifestation et la solution.
401 Unauthorized
Clé absente, mal formatée, ou invisible pour le processus qui effectue la requête.
- Vérifiez que l'en-tête est exactement
Authorization: Bearer <key>— le motBearer, un espace, puis la clé. - Confirmez que la variable d'environnement est définie dans le même shell ou processus. Dans les conteneurs et la CI, les variables exportées dans votre shell local ne suivent pas le code.
- Si vous avez récemment fait tourner la clé, assurez-vous que l'ancienne n'est pas encore mise en cache quelque part.
400 Bad Request
Généralement un problème de corps de requête.
- Nom de champ inconnu ou mal orthographié — tenez-vous aux paramètres documentés.
- Valeur de
aspect_rationon acceptée par l'endpoint — utilisez le formatlargeur:hauteurde la documentation. nhors de la plage autorisée.- JSON mal formé — par exemple une virgule superflue, ou des guillemets non échappés dans la chaîne du prompt. Si vous soupçonnez ce problème, formatez et inspectez le corps de la requête avant l'envoi.
404 renvoyé par l'étape de consultation du statut ou de téléchargement
L'ID de tâche est erroné, ou le chemin que vous interrogez ne correspond pas à l'endpoint utilisé pour la soumission. Lors de la première intégration, enregistrez intégralement la réponse de soumission et comparez l'ID caractère par caractère.
Timeout de polling
Si wait_for_job atteint l'échéance :
- Vérifiez que vous contrôlez la bonne valeur de statut ; un état terminal que vous ne reconnaissez pas ressemblera à un blocage.
- Pour les rendus volumineux et complexes, augmentez le timeout global plutôt que de raccourcir l'intervalle de polling.
- Pendant l'intégration, journalisez chaque réponse de statut, afin de voir combien de temps les tâches prennent réellement avec votre combinaison de prompts.
Statut de tâche failed
Lisez le corps de réponse d'erreur renvoyé par l'API — il existe pour une raison. Les tâches échouées proviennent généralement du côté du prompt ou des paramètres ; la correction se fait dans la requête, pas dans le code de polling.
En cas de doute, la documentation HiAPI de ce modèle est la source de référence pour les noms de champs et les valeurs acceptables. Validez un changement à la fois et conservez une requête connue pour fonctionner comme référence pour la prochaine intégration.
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