HiAPI
Blog

Tutoriel

Tutoriel de l'API recraft-v4-styles/text-to-image : curl, Python et interrogation asynchrone

Exercice complet de requête pour la génération d'images avec référence de style sur HiAPI

Oct 31, 2026
深蓝底色上铜色细分平行线构成几何带状图案,呼应异步轮询主题的博客封面图

Ce que recraft-v4-styles/text-to-image peut faire pour vous

recraft-v4-styles/text-to-image est un point de terminaison de génération d'images par référence de style. Vous lui fournissez un prompt textuel décrivant ce que vous voulez voir, ainsi qu'une ou plusieurs images de référence décrivant l'apparence stylistique. Le modèle fusionne les deux : le prompt porte l'intention de contenu et de composition, les images de référence portent le style visuel.

Cette distinction est importante au moment de choisir un point de terminaison. Lorsque l'apparence peut être entièrement exprimée en mots — par exemple « une illustration vectorielle plate d'une tasse à café, bicolore, avec des contours épais » — la génération d'images à partir d'un simple prompt est le bon outil. En revanche, dans le travail produit réel, la plupart des scénarios impliquent une identité de marque difficile à décrire mais facile à montrer. Un visuel clé existant, un rendu précédemment validé ou un échantillon de design system définit la spécification de style bien plus précisément qu'un paragraphe d'adjectifs. C'est précisément le vide que comble ce point de terminaison.

Du point de vue du développeur, considérez-le comme une transformation à deux entrées : prompt + référence de style -> image. Tout ce qui concerne son intégration découle de cette forme. Vous ne sérialisez pas simplement une chaîne, vous assemblez une petite charge utile composée de plusieurs parties, où les images de référence sont des entrées de premier ordre. Votre code de construction de requête doit les traiter comme telles, et votre couche de validation doit rejeter, avant que la tâche ne quitte votre service, celles qui ne contiennent qu'un prompt sans référence de style exploitable.

Le point de terminaison est asynchrone. Soumettre une requête renvoie une tâche, que vous interrogez ensuite, et l'image finale arrive sous forme d'URL plutôt que de bytes en ligne. C'est un choix délibéré pour les charges de travail d'images : la génération prend suffisamment de temps pour que maintenir une connexion HTTP ouverte soit à la fois inutile et fragile. Une fois que vous avez accepté le cycle « soumettre - interroger - télécharger », le reste de l'intégration n'est que de la plomberie d'API ordinaire.

Anatomie d'une requête fonctionnelle

Avant d'écrire la moindre ligne de code, clarifiez le regroupement des champs. Une requête recraft-v4-styles/text-to-image comporte trois parties logiques.

Le prompt

Le prompt est votre instruction de contenu. Rédigez-le autour de ce que l'image doit contenir — sujet, composition, cadrage, nombre d'objets, traitement du fond. Évitez de dépenser votre budget de prompt sur des adjectifs de style que les images de référence transmettent déjà ; les conflits de signal entre le prompt et les références produisent souvent des résultats flous. Gardez le prompt court, spécifique et testable.

Les entrées de référence de style

C'est ce qui distingue ce point de terminaison d'un appel ordinaire de génération d'images à partir de texte. Les références de style sont des images fournies avec le prompt pour définir le langage visuel. Lors de leur assemblage, traitez-les comme un ensemble soigneusement sélectionné plutôt que comme un tas d'images en désordre :

  • La cohérence prime sur la quantité. Quelques références partageant une même apparence cohérente apprennent davantage au modèle que de nombreuses références aux styles disparates.
  • La résolution et le cadrage comptent. Les références doivent représenter la sortie que vous souhaitez, et non des miniatures ou des fragments fortement recadrés.
  • Elles doivent être accessibles. Si vos références sont transmises sous forme d'URL, ces URL doivent être accessibles publiquement au moment de la requête. Un lien signé qui expire au bout de soixante secondes fera échouer une tâche lente.

Conservez votre jeu de références dans la configuration plutôt que dispersé dans le code, afin de pouvoir le versionner avec vos actifs de marque.

Les options de sortie

Les champs restants décrivent l'artefact que vous voulez recevoir — ce sont des réglages qui influencent l'image renvoyée, et non son contenu. Les noms exacts des paramètres et les valeurs acceptées sont documentés sur la page de référence de ce point de terminaison ; lisez-les là plutôt que de deviner, et centralisez-les à un seul endroit dans le code, afin qu'un changement de spécification n'affecte qu'un seul fichier.

Une habitude utile : construisez le corps JSON sous forme de dictionnaire/objet dans votre langage choisi, journalisez-le une fois au niveau debug lors de la première exécution, et inspectez sa structure à l'œil nu avant de blâmer le modèle pour un mauvais résultat.

Appeler avec curl

Commencez par curl. Il supprime toute couche d'abstraction de bibliothèque entre vous et le format de transmission, de sorte que si la requête est erronée, vous le constatez immédiatement.

La soumission est une requête POST avec un corps JSON et un en-tête d'authentification portant votre clé d'API HiAPI :

curl -sS -X POST "https://api.hiapi.ai/v1/recraft-v4-styles/text-to-image" \
  -H "Authorization: Bearer $HIAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "prompt": "a ceramic coffee cup on a linen tablecloth, soft daylight",
    "style_references": [
      "https://your-cdn.example.com/style/ref-01.png"
    ]
  }'

Quelques remarques sur ce que vous voyez :

  • Conservez la clé dans une variable d'environnement ($HIAPI_API_KEY), jamais en ligne dans l'historique du shell ou dans un script commité.
  • La charge utile de -d est du JSON pur. Les règles de quoting du shell sont une source fréquente d'ennuis — si vous rencontrez une erreur d'analyse, écrivez le corps dans un fichier et utilisez -d @body.json à la place.
  • Les noms de champs indiqués ici suivent l'anatomie de requête de la section précédente ; avant de passer en production, vérifiez les noms exacts et les options de sortie acceptées sur la page de référence de ce point de terminaison.

La réponse n'est pas une image. C'est une confirmation de tâche : un identifiant de la génération que vous venez de mettre en file d'attente, ainsi qu'un champ de statut indiquant qu'elle n'est pas encore terminée. Lisez attentivement le corps de la réponse lors de la première exécution et notez le nom du champ qui stocke l'ID de tâche — cette chaîne est le handle de toutes vos opérations ultérieures. Conservez-la. Si votre première réponse contient un objet d'erreur, arrêtez-vous et corrigez la requête ; interroger un ID que vous n'avez jamais reçu est l'impasse la plus courante.

Implémenter la même requête en Python

Portez l'appel curl en Python une fois, et vous disposez d'une primitive réutilisable. L'exemple ci-dessous utilise requests et reproduit exactement le corps de la requête.

import os
import requests

API_KEY = os.environ["HIAPI_API_KEY"]
BASE_URL = "https://api.hiapi.ai/v1"

HEADERS = {
    "Authorization": f"Bearer {API_KEY}",
    "Content-Type": "application/json",
}

STYLE_REFERENCES = [
    "https://your-cdn.example.com/style/ref-01.png",
]

def submit_generation(prompt: str) -> dict:
    body = {
        "prompt": prompt,
        "style_references": STYLE_REFERENCES,
    }
    resp = requests.post(
        f"{BASE_URL}/recraft-v4-styles/text-to-image",
        headers=HEADERS,
        json=body,
        timeout=30,
    )
    resp.raise_for_status()
    return resp.json()

if __name__ == "__main__":
    job = submit_generation(
        "a ceramic coffee cup on a linen tablecloth, soft daylight"
    )
    print(job)

Deux choix de conception méritent d'être conservés lors de l'adaptation de ce code :

  • Définissez toujours un timeout. La soumission doit revenir rapidement ; si elle bloque, vous voulez une exception, pas un processus figé.
  • Renvoyez le JSON analysé, pas l'objet de réponse. Le code en aval doit dépendre de la charge utile de la tâche et non des internes de requests. Cela rendra le remplacement de la couche de transport trivial plus tard.

Comme indiqué ci-dessus, définissez le jeu de références au niveau du module ou de la configuration. Lorsque l'apparence de la marque évolue, vous ne mettez à jour qu'une seule liste, sans devoir chercher dans les points d'appel. Et gardez la construction du corps dans une seule fonction, afin que tout champ requis par le point de terminaison ne soit ajouté qu'à un seul endroit.

Interroger le résultat asynchrone

La génération est asynchrone, donc la tâche que vous soumettez passe par plusieurs états avant d'être terminée. Votre client a besoin d'une boucle d'attente qui vérifie le statut, recule entre les vérifications et finit par abandonner.

import time

def wait_for_result(job_id: str, timeout_s: int = 300, interval_s: float = 3.0) -> dict:
    deadline = time.monotonic() + timeout_s
    delay = interval_s
    while time.monotonic() < deadline:
        resp = requests.get(
            f"{BASE_URL}/recraft-v4-styles/text-to-image/{job_id}",
            headers=HEADERS,
            timeout=30,
        )
        resp.raise_for_status()
        data = resp.json()
        status = data.get("status")
        if status in ("succeeded", "failed"):
            return data
        time.sleep(delay)
        delay = min(delay * 1.5, 15.0)
    raise TimeoutError(f"job {job_id} did not finish in {timeout_s}s")

Dans cette boucle, les points importants :

  • Traitez les statuts inconnus comme en attente. Comparez à des états terminaux explicites plutôt qu'à une liste autorisée d'états en cours ; si la plateforme ajoute un état intermédiaire, votre boucle continuera d'attendre au lieu de planter.
  • Reculez. Interroger à intervalle fixe d'une fois par seconde pendant cinq minutes, c'est cinq minutes de requêtes gaspillées. Commencez par un petit intervalle, multipliez et plafonnez.
  • Limitez le temps d'attente. Chaque boucle a besoin d'une échéance, et l'échéance doit se manifester sous forme d'exception que l'appelant peut gérer.
  • Branchez sur l'échec. Un état d'échec terminal porte des informations de diagnostic. Journalisez le corps complet de la réponse — c'est la différence entre « c'est cassé » et « l'URL de référence a renvoyé 403 ».

Si vous traitez de grands volumes d'images, ne dormez pas dans le gestionnaire de requêtes web. Soumettez, persistez l'ID de tâche, et laissez un worker en arrière-plan ou une tâche planifiée piloter l'interrogation. La page de référence du point de terminaison documente les valeurs de statut exactes et le chemin d'interrogation ; vérifiez-la chaque fois que vous mettez à jour le client.

Télécharger et stocker la sortie

Lorsque la tâche atteint un état terminal de succès, la réponse contient l'URL de l'image générée. Cette URL est le point de jonction entre l'API et votre couche de stockage.

Récupérez-la sous forme de bytes et écrivez-la là où vous en avez besoin :

def download_image(url: str, dest_path: str) -> None:
    resp = requests.get(url, timeout=60)
    resp.raise_for_status()
    with open(dest_path, "wb") as f:
        f.write(resp.content)

Pour tout scénario au-delà de l'expérimentation locale, ne laissez pas l'artefact uniquement sur l'URL renvoyée. Traitez l'image générée comme un pointeur temporaire et copiez-la dans un stockage que vous contrôlez — bucket d'objets, origine CDN ou pipeline média. Trois raisons :

  1. Cycle de vie. L'URL de sortie générée n'est pas garantie de persister indéfiniment. Retélécharger depuis une URL obsolète lors d'une nouvelle tentative est un échec silencieux potentiel.
  2. Clés stables. Votre application a besoin d'un identifiant déterministe qu'elle peut placer dans une ligne de base de données, pas d'une URL qui change à chaque régénération.
  3. Traçabilité. Stocker le prompt, la version du jeu de références de style et l'ID de tâche avec l'image vous permet de reproduire ou d'auditer n'importe quel actif ultérieurement. Conservez ces métadonnées dans un enregistrement d'accompagnement ou une colonne de base de données.

Lorsque vous téléversez vers un stockage d'objets, diffusez le corps de la réponse en streaming plutôt que de mettre en tampon une grande image entièrement en mémoire, et définissez le type de contenu à partir des en-têtes de réponse. Si vous renvoyez l'image aux clients via votre propre CDN, c'est également à cette étape que vous appliquez les en-têtes de cache.

Dépannage des premières exécutions

La plupart des premières tentatives échouent de quelques manières prévisibles. Vérifiez-les dans l'ordre.

Le corps de la requête est rejeté

Les erreurs de type 400 signifient généralement un JSON mal formé ou un champ obligatoire manquant. Exécutez d'abord la version curl et inspectez le corps exact que vous envoyez. Problèmes courants : le quoting du shell qui casse le JSON, l'envoi sous forme de chaîne d'un champ que l'API attend sous forme de tableau, ou une valeur d'option de sortie hors de la plage acceptée. La page de référence du point de terminaison est la source d'autorité pour les noms et valeurs de champs — comparez votre corps de manière littérale avec elle.

Vous avez un prompt mais aucune référence de style exploitable

Ce point de terminaison est construit autour des références de style. Si votre requête contient un prompt mais que les références sont vides, inaccessibles, ou renvoient une erreur d'authentification lors de la récupération, la tâche sera soit rejetée, soit produira une sortie ignorant l'apparence attendue. Validez chaque URL de référence en la récupérant avec le même client sans identifiants que celui utilisé par la plateforme. Une référence nécessitant un cookie de session ou une chaîne de requête signée est à considérer comme cassée.

Vous n'obtenez jamais d'ID de tâche

La réponse de soumission est une confirmation, pas une image. Si le code que vous avez écrit attend des bytes d'image dans la première réponse, il échouera à chaque exécution. Analysez la réponse, extrayez l'ID de tâche, puis commencez seulement à interroger. Journalisez la réponse complète de soumission lors des premières exécutions, afin de pouvoir en voir la forme.

Vous interrogez trop fréquemment

Des centaines de vérifications de statut par minute ne font pas terminer la tâche plus vite et risquent davantage de déclencher des limitations de débit. Utilisez un intervalle croissant avec plafond, et un seul worker par tâche. Si vous distribuez de nombreuses tâches, ajoutez une petite limite de concurrence pour qu'une rafale de soumissions ne devienne pas une rafale d'interrogations.

La tâche se termine mais le téléchargement échoue

Un 403 ou 404 lors de la récupération de l'URL de sortie signifie généralement que l'URL a expiré, ou que la tâche a échoué après une vérification de statut que vous avez mal lue. Confirmez que l'état terminal est un succès, puis relisez la réponse pour obtenir le champ de sortie réel. Stockez l'artefact dès qu'il est disponible, plutôt que de différer le téléchargement.

En résolvant ces problèmes dans l'ordre d'exécution du pipeline — soumettre, interroger, télécharger — une défaillance de première exécution se résout presque toujours en un correctif évident. La référence du point de terminaison et son schéma de requête constituent le moyen le plus rapide de confirmer toute question au niveau des champs.

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