Tutoriel
Comment utiliser flux-1.1-pro via l'API HiAPI : curl, Python et requêtes exécutables
Un guide d'intégration pratique : des requêtes qui fonctionnent réellement, la gestion asynchrone et des recettes de prompts avec sorties réelles
Sur cette page
Ce que flux-1.1-pro peut offrir avant même que vous écriviez du code
flux-1.1-pro est un modèle texte-vers-image, appelé via HiAPI.ai sous forme de point de terminaison hébergé. Vous envoyez un prompt et des paramètres de génération au format JSON, et vous recevez l'image générée en retour. Rien à installer, aucune pondération à héberger vous-même, aucune ressource GPU à gérer. Votre surface d'intégration se résume à un point de terminaison HTTP, plus des identifiants pour l'authentification.
Pour un développeur, cela signifie que trois choses façonnent votre conception avant même que vous n'écriviez la première ligne de code.
Premièrement, la requête est du JSON en entrée, une image en sortie. Votre prompt, votre ratio d'aspect et quelques paramètres de contrôle tiennent dans le corps de la requête. La réponse transporte les données de l'image ou une référence vers celles-ci, selon le mode de livraison de la tâche. Traitez le corps de la requête comme un contrat et centralisez-le à un seul endroit, afin que les deux chemins curl et Python ne divergent jamais.
Deuxièmement, par rapport à un appel d'API ordinaire, la génération d'image est une opération lente. Quelques secondes sont normales ; un prompt complexe en haute résolution peut prendre plus longtemps. Tout appelant en production doit présumer une latence et la planifier, plutôt que de traiter l'appel comme une lecture de base de données.
Troisièmement, la qualité de sortie dépend principalement du prompt, pas du câblage. L'intégration est la partie simple. Le vrai travail consiste à décrire précisément ce que vous voulez et à valider votre recette avec de vraies sorties avant la mise en production.
Gardez ces trois points en tête : le reste de ce guide est un processus mécanique : construire la requête, confirmer qu'elle fonctionne, la porter, puis la durcir et l'affiner. Tout au long, tout passe par l'API HiAPI — un identifiant, une URL de base, une structure JSON à apprendre.
Votre première requête curl
Commencez par curl. Il élimine toutes les couches d'abstraction entre vous et le point de terminaison, donc en cas d'échec, vous savez que le problème vient de votre corps de requête, pas de votre framework.
Un appel minimal comporte trois parties : le point de terminaison, l'en-tête d'authentification et le corps JSON.
curl -X POST "https://api.hiapi.ai/v1/images/generations" \
-H "Authorization: Bearer $HIAPI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "flux-1.1-pro",
"prompt": "a ceramic coffee mug on a weathered wooden table, soft morning window light, shallow depth of field, product photography",
"aspect_ratio": "1:1"
}'
Lisez le corps champ par champ :
modelindique le modèle à utiliser. Écrivez-le explicitement, afin qu'un changement futur de la valeur par défaut ne modifie jamais silencieusement vos sorties.promptest la description en langage naturel. Presque tout votre budget qualité se trouve ici.aspect_ratiocontrôle le cadrage. Choisissez-le délibérément plutôt que de dépendre d'une valeur par défaut que vous n'avez pas vérifiée.
Placez la clé dans une variable d'environnement (HIAPI_API_KEY) plutôt que de la coller directement dans la commande. Cette habitude se transmet directement au Python, ainsi qu'à toute étape CI que vous ajouterez plus tard.
En cas de succès, vous recevez une réponse JSON décrivant l'image terminée. Avant de fermer le terminal, inspectez-la et localisez la référence ou les données de l'image. En cas d'échec, vous recevez un corps d'erreur avec un code de statut et un message ; lisez ce message littéralement, car un champ mal formaté est la cause d'échec initiale la plus courante.
Un avertissement qui vous fera gagner une heure : ne collez pas dans le shell un prompt multiligne contenant des guillemets non échappés. Pour tout ce qui dépasse une phrase courte, utilisez un heredoc ou un fichier.
curl -X POST "https://api.hiapi.ai/v1/images/generations" \
-H "Authorization: Bearer $HIAPI_API_KEY" \
-H "Content-Type: application/json" \
--data @request.json
Ce request.json est l'artefact que vous devez versionner. C'est la source unique de vérité du corps de requête, et la section suivante le réutilise tel quel.
Porter le même appel en Python
L'objectif du portage n'est pas d'écrire une nouvelle logique, mais d'envoyer exactement le même corps JSON. Chargez le même request.json, afin que les deux chemins ne puissent pas diverger.
import json
import os
import requests
API_URL = "https://api.hiapi.ai/v1/images/generations"
with open("request.json") as f:
payload = json.load(f)
response = requests.post(
API_URL,
headers={
"Authorization": f"Bearer {os.environ['HIAPI_API_KEY']}",
"Content-Type": "application/json",
},
json=payload,
timeout=120,
)
if response.status_code != 200:
print(response.status_code)
print(response.text)
response.raise_for_status()
print(response.json())
Trois détails comptent ici.
L'en-tête d'authentification et les en-têtes sont le même ensemble d'en-têtes. Utiliser json=payload fait que requests sérialise le corps et définit le type de contenu à votre place ; écrire l'en-tête explicitement est inoffensif et documente l'intention.
Définissez un délai d'expiration. Ne laissez jamais une requête de génération suspendue à une valeur par défaut non bornée. Un délai explicite et généreux convient — l'essentiel est qu'il soit explicite.
Inspectez le corps d'erreur avant de lever une exception. Si vous appelez d'abord raise_for_status(), il supprime le corps de la réponse de vos journaux. Affichez d'abord le code de statut et le texte, puis levez l'exception. Vous aurez besoin de ce texte lorsqu'un champ est rejeté.
Si vous utilisez uniformément un client HTTP asynchrone, la structure ne change pas : même URL, mêmes en-têtes, même corps, simplement await client.post(...) avec le même délai d'expiration. Le contrat du corps de requête est constant ; le client est un détail d'implémentation.
Gardez le corps de requête en dehors du code source Python. Lorsqu'une recette de prompt fonctionne, elle doit vivre dans un fichier ou une ligne de base de données, et non dans un littéral de chaîne enfoui dans une fonction, afin que vous puissiez la comparer par diff et la réexécuter.
Gérer les tâches asynchrones sans bloquer votre application
Traitez la génération comme une tâche, pas comme un appel de fonction. Que votre chemin de livraison semble synchrone ou renvoie une tâche que vous devez interroger, la conséquence pratique est la même : votre application ne doit jamais immobiliser un thread de requête sans limite en attendant une image.
Un modèle viable comporte quatre étapes.
1. Soumettez depuis un worker, pas depuis la requête utilisateur
Acceptez l'action de génération de l'utilisateur au niveau de la couche Web, persistez un enregistrement de tâche, mettez-la en file d'attente, puis retournez immédiatement. Un worker en arrière-plan effectue l'appel API réel. L'utilisateur interroge votre point de terminaison, pas le modèle.
2. Bornez l'attente
Définissez pour chaque tentative un délai d'expiration que vous avez choisi délibérément. Si la plateforme renvoie une tâche que vous devez interroger, interrogez à intervalle fixe, avec un nombre maximal de tentatives et une échéance calculée depuis le début de la tâche (et non depuis le nombre de tentatives). Préférez un backoff modéré à une boucle serrée.
3. Ne réessayez que les échecs qui le méritent
Réessayez les erreurs de transport, les délais d'expiration et les échecs côté serveur avec un backoff exponentiel et du jitter, en limitant à un petit nombre de tentatives. Ne réessayez pas les erreurs de validation : un champ rejeté ou un prompt vide échouera de la même manière à chaque fois, et réessayer ne fait qu'allonger l'attente de l'utilisateur avant qu'il ne voie le vrai message.
4. Rendez les tâches idempotentes de votre côté
Enregistrez dans la base de données le corps de requête exact et l'ID de tâche. Si votre worker plante après la soumission mais avant d'enregistrer le succès, vous pouvez réexaminer la tâche plutôt que de la resoumettre aveuglément. Lorsque vous devez resoumettre, ajoutez une brève clé de déduplication côté client, afin qu'un incident transitoire ne mette pas trois fois la même génération en file d'attente.
import time
def poll_until_done(fetch_status, job_id, deadline_seconds=180):
start = time.monotonic()
delay = 2.0
while True:
status = fetch_status(job_id)
if status["state"] in ("succeeded", "failed"):
return status
if time.monotonic() - start > deadline_seconds:
raise TimeoutError(f"generation {job_id} exceeded deadline")
time.sleep(delay)
delay = min(delay * 1.5, 10.0)
Cet assistant reste délibérément générique : il reçoit une fonction d'obtention de statut, de sorte que la même boucle s'applique à tout point de terminaison basé sur des tâches que vous intégrerez plus tard. Les propriétés importantes sont l'échéance, le backoff borné et la vérification d'un état terminal — pas le mode de transport concret.
Construire des prompts qui se rendent de façon stable
Un prompt long n'est pas un meilleur prompt. C'est la structure qui compte. Un squelette reproductible vous donne des résultats cohérents et un endroit où ne modifier qu'une variable à la fois en cas de problème.
Utilisez quatre emplacements dans cet ordre :
- Sujet — ce qui figure dans l'image, de manière précise. « une tasse à café en céramique » vaut mieux que « une sorte de chose pour café ».
- Style — le ton visuel : photographie, illustration, aquarelle, rendu 3D, prise de vue produit. Précisez le médium et, si utile, la lumière.
- Composition — cadrage et caméra : ratio d'aspect, distance de prise de vue, angle, profondeur de champ, position du sujet dans l'image.
- Contraintes — ce que vous voulez et ne voulez pas explicitement, en restant bref.
[subject] a single ceramic coffee mug, matte glaze, small handle
[style] product photography, soft diffused window light, muted palette
[composition] 1:1, eye-level, subject centered, shallow depth of field, plain background
[constraints] no text, no logos, no hands
Lors de l'envoi, aplatissez-le en un seul prompt ; les crochets sont pour vous, pas pour le modèle. La valeur d'écrire par emplacements est que, lorsque la sortie est mauvaise, vous savez quel emplacement modifier.
Quelques règles pratiques :
- Placez le sujet en premier. La première proposition a le plus de poids.
- Privilégiez les noms et adjectifs concrets plutôt que les mots d'émotion abstraits. « glaçure mate » change les pixels ; « aspect haut de gamme » ne le fait pratiquement pas.
- Placez le langage de caméra dans l'emplacement composition, pas dans le sujet. Les mélanger produit des instructions contradictoires et empressées.
- Lors d'itérations, ne modifiez qu'un seul emplacement à la fois, et conservez le texte exact du prompt qui a produit la sortie acceptée.
Le ratio d'aspect est une décision de composition, pas un ajustement après coup. Choisissez-le en fonction de l'endroit où l'image apparaîtra — carré dans une grille, plus haut dans une bannière principale — et adaptez le reste du prompt à ce cadre.
Utiliser efficacement les listes de termes négatifs
Une liste de termes négatifs indique au modèle ce qu'il faut éviter. C'est un outil tranchant, utile dans une portée étroite : excellent pour supprimer des défauts récurrents, mais désastreux comme fourre-tout où l'on énumère toutes les imperfections imaginables.
Les termes négatifs doivent être courts et spécifiques. Pour la plupart des prompts, cinq à huit entrées courtes suffisent. Écrivez des choses concrètes :
no text, no watermark, no logos, no extra fingers, no harsh shadows
Cette liste fonctionne parce que chaque entrée nomme quelque chose de visible et de vérifiable. Comparez avec des négations vagues comme « not ugly » ou « bad quality » — elles ne portent pratiquement aucun signal exploitable et diluent les entrées qui comptent vraiment.
Là où les termes négatifs aident réellement :
- Supprimer un défaut que vous voyez de façon récurrente. Si les mains ou le texte reviennent, les nommer explicitement est le correctif le plus direct.
- Hygiène de marque et juridique. Excluez les logos et filigranes avant que l'image n'atteigne une interface destinée aux utilisateurs.
- Imposer un fond propre pour les visuels produit ou les images proches d'une UI.
Là où ils vous desservent :
- Contradiction avec le prompt positif. « pas d'ombre » dans les négatifs contre « éclairage latéral dramatique » dans le sujet est un conflit que le modèle résoudra de façon imprévisible. Corrigez le prompt positif.
- Nier ce qui n'a guère de chance d'apparaître. Une longue liste d'échecs improbables n'ajoute que du bruit sans changer le rendu.
- Utiliser les négatifs pour compenser un sujet flou. Si le sujet n'est pas clair, aucune liste de termes négatifs ne le sauvera.
Un détail pratique : certains clients acceptent les termes négatifs comme champ séparé plutôt que comme texte ajouté. Vérifiez ce que votre requête prend en charge et conservez ce champ dans le corps de requête enregistré, afin que curl et Python se comportent de manière identique.
Recettes de prompts avec sorties réelles
Les recettes ci-dessous sont des points de départ, pas des garanties. Le flux de travail honnête est le suivant : exécutez la recette via votre propre intégration, examinez la sortie, puis ajustez un emplacement. Toute sortie que vous n'avez pas générée vous-même doit être considérée comme non validée.
Recette 1 — visuel produit propre
A single matte-black wireless earbud case on a light concrete surface,
studio product photography, soft key light from the left, 1:1, centered,
shallow depth of field, plain background. No text, no logos, no hands.
Caractéristiques attendues : un sujet net et centré, une atténuation douce et un fond non encombré. Si la surface paraît trop chargée, resserrez « plain background » et retirez tout mot de texture. Si la lumière est trop plate, ajoutez un mot directionnel — rien de plus.
Recette 2 — portrait éditorial
Portrait of a person in a wool coat, natural window light, calm expression,
3:4, chest-up framing, subject slightly off-center, muted film palette.
No text, no watermark.
Caractéristiques attendues : lumière directionnelle douce, couleurs sobres. Si le cadrage est plus large que prévu, avancez « chest-up framing » et retirez les mots de composition concurrents.
Recette 3 — illustration isométrique
Isometric illustration of a small reading nook: armchair, floor lamp, bookshelf,
flat vector style, limited palette of warm neutrals and one accent color,
1:1, centered composition, clean white background. No text, no gradients.
Caractéristiques attendues : géométrie nette et aplats. Si la palette dérive, précisez la couleur d'accent et conservez « clean white background » comme dernière proposition, afin qu'elle l'emporte.
Recette 4 — bannière principale
A wide misty mountain ridge at sunrise, layered depth, minimal detail,
16:9, subject occupying the lower third, generous empty sky for overlaid text.
No text, no watermark.
Caractéristiques attendues : une image calme et peu détaillée, avec de l'espace négatif exploitable. L'expression « overlaid text » réserve l'espace ; elle ne rend pas de lettres, et la liste de termes négatifs garde le texte hors de l'image elle-même.
Pour chaque recette, enregistrez le corps de requête exact, le ratio d'aspect et la date. En y revenant un mois plus tard, vous pourrez réexécuter le corps de requête enregistré et le comparer à la sortie enregistrée, plutôt que de deviner pourquoi le résultat a changé.
Erreurs, limites et ce qu'il faut vérifier en premier
Lorsqu'une génération échoue ou que la sortie est mauvaise, parcourez cette liste avant de modifier le code.
Vérifiez d'abord le corps de requête
- Le corps est-il un JSON valide ? Une virgule finale ou des guillemets non échappés sont la cause d'échec initiale la plus courante. Validez votre
request.jsonenregistré avant l'envoi. - Les noms de champs sont-ils exacts ? Un paramètre mal orthographié est généralement rejeté ou silencieusement ignoré. Référez-vous à la structure de requête de la documentation, pas à votre mémoire.
- Le nom du modèle est-il correct et existe-t-il ? Ne vous fiez pas aux valeurs par défaut.
- Le prompt est-il non vide et dans la longueur prévue par la documentation ? Les limites figurent dans la documentation de la plateforme ; lisez-les là plutôt que de supposer un chiffre.
Vérifiez ensuite l'authentification et le transport
- La clé API existe-t-elle et est-elle valide actuellement ? Un 401 signifie généralement un en-tête manquant, mal formaté, ou une clé qui a été renouvelée.
- L'URL du point de terminaison et la méthode sont-elles correctes ? Envoyer un POST sur un chemin GET échoue d'une manière qui ressemble à un problème de clé.
- Votre délai d'expiration est-il trop serré ? Si votre client abandonne avant la fin de la tâche, le délai d'expiration que vous observez n'a rien à voir avec le modèle.
Vérifiez ensuite la structure de la requête
- La catégorie du code de statut vous indique où regarder. Un 4xx est presque toujours un problème de votre requête ; un 5xx est généralement transitoire et mérite un nombre borné de tentatives.
- Lisez le message d'erreur littéralement. Affichez le corps de la réponse avant de lever une exception. Le champ mentionné dans le message est celui à corriger.
- Une réponse de limitation de débit ou de quota signifie ralentir et réessayer avec un backoff, pas réécrire le prompt.
Enfin, vérifiez le prompt
Si l'appel réussit mais que l'image est mauvaise, vous êtes dans le domaine du prompt, pas de l'erreur :
- Sujet absent ou trop général ? Déplacez-le en première proposition et rendez-le précis.
- Composition incorrecte ? Corrigez à la fois le ratio d'aspect et les mots de cadrage ; ne compensez pas l'un par l'autre.
- Défaut récurrent ? Ajoutez un terme négatif court et spécifique.
- Contradiction ? Identifiez le terme négatif qui combat le prompt positif et supprimez-le.
Le plus important est de garder une habitude : pour chaque génération qui vous importe, enregistrez le corps de requête exact, l'état de la réponse et la référence de l'image générée. La reproductibilité transforme le débogage en comparaison par diff plutôt qu'en devinette. Construisez votre première requête, confirmez la sortie, puis resserrez le prompt avant la mise en production — et conservez le corps de requête utilisé au lancement, afin que la prochaine modification ait une base réelle de comparaison.
Articles similaires
Voir tous les articles →-
Tutoriel
gemini-omni-1.2-flash en pratique : 3 scénarios métier de génération vidéo et une checklist de mise en production
Trois cas d'application : créativité textuelle, animation de première frame et contrainte visuelle par image de référence
-
Tutoriel
Comment appeler gpt-image-2.5-sunburst/text-to-image via l'API HiAPI : curl et Python
Une démonstration d'intégration avec requêtes fonctionnelles, gestion des images de référence et modèles de nouvelles tentatives
-
Tutoriel
Comment appeler gpt-5.6-terra@azure via l'API HiAPI : guide curl et Python
Construire une requête fonctionnelle, ajouter le streaming et l'appel d'outils, et gérer les erreurs sans deviner