HiAPI
Blog

Tutoriel

Optimisation des coûts de l'API Seedream : comment réduire le coût de génération d'images sur hiapi

Oct 8, 2026
Optimisation des coûts de l'API Seedream : comment réduire le coût de génération d'images sur hiapi

Seedream est proposé sur hiapi en quatre niveaux distincts — seedream-5.0-flash, seedream-5.0-lite, seedream-5.0-pro et l'ancien seedream-4.5 — et chacun est facturé différemment. Choisir le mauvais niveau ou la mauvaise résolution peut vous coûter 2 à 4 fois plus cher par image sans aucune amélioration visible de la qualité. Ce guide présente la structure tarifaire réelle de chaque niveau et fournit un modèle de code exécutable pour appeler le modèle le moins coûteux qui réponde à vos exigences.

Ce que vous allez construire, et les prérequis

Vous allez construire un petit client Python qui crée des tâches d'image Seedream via l'API de tâches unifiée de hiapi, attend le résultat, et choisit délibérément une combinaison résolution/modèle au lieu de copier-coller les valeurs par défaut des tutoriels. D'abord, récupérez une clé API depuis votre console hiapi — chaque requête ci-dessous l'envoie sous la forme Authorization: Bearer sk-....

La structure tarifaire que vous allez optimiser

Tarifs actuels par image (vérifiez toujours la page de tarification en temps réel avant la mise en production, car les tarifs changent) :

  • seedream-5.0-flash —— forfait de 0,025 $/image, même prix pour la génération texte-vers-image et image-vers-image. Le niveau le moins cher de la plateforme ; idéal pour les brouillons, les vignettes et tout ce que vous régénérez plusieurs fois avant de choisir le résultat final.
  • seedream-5.0-lite —— forfait de 0,035 $/image, et surtout, le prix est identique que vous rendiez en 2K ou en 4K. À ce niveau, il n'y a jamais de raison de demander du 2K d'un point de vue coût — le 4K est une mise à niveau gratuite.
  • seedream-4.5 (ancien) —— forfait de 0,045 $/image sur les deux points de terminaison.
  • seedream-5.0-pro —— tarification par paliers de résolution plutôt que forfaitaire : texte-vers-image à 0,05 $ en 1K, 0,10 $ en 2K ; image-vers-image à 0,06 $ en 1K, 0,10 $ en 2K. À ce niveau, la résolution est là où votre budget part réellement — un brouillon en 1K coûte environ la moitié d'un rendu final en 2K.

Cette asymétrie est tout l'intérêt de l'optimisation : lite récompense les requêtes à résolution plus élevée (gratuit), pro pénalise les résolutions plus élevées (coût environ doublé). Traitez-les différemment dans votre code d'appel, au lieu de coder en dur la même résolution partout.

Exemple minimal exécutable

Chaque appel Seedream passe par le même point de terminaison asynchrone de tâche : créez avec POST /v1/tasks, puis interrogez GET /v1/tasks/{taskId} ou recevez un rappel webhook. Les identifiants de modèle sont bruts — sans préfixe models/ ni préfixe de fournisseur.

import os
import time
import requests

API_KEY = os.environ["HIAPI_API_KEY"]  # starts with sk-
BASE_URL = "https://api.hiapi.ai/v1"
HEADERS = {"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"}


def create_task(model: str, input_payload: dict) -> str:
    resp = requests.post(f"{BASE_URL}/tasks", headers=HEADERS,
                          json={"model": model, "input": input_payload}, timeout=30)
    resp.raise_for_status()
    return resp.json()["data"]["taskId"]


def wait_task(task_id: str, interval: float = 3.0, timeout: float = 180.0) -> dict:
    deadline = time.time() + timeout
    while time.time() < deadline:
        resp = requests.get(f"{BASE_URL}/tasks/{task_id}", headers=HEADERS, timeout=30)
        resp.raise_for_status()
        data = resp.json()["data"]
        if data["status"] == "success":
            return data
        if data["status"] == "fail":
            raise RuntimeError(data["error"])
        time.sleep(interval)
    raise TimeoutError(f"task {task_id} did not finish within {timeout}s")


# seedream-5.0-lite: 4K costs the same $0.035 as 2K, so always ask for 4K here.
task_id = create_task(
    "seedream-5.0-lite/text-to-image",
    {"prompt": "a minimalist product photo of a ceramic mug on a wooden table", "resolution": "4K"},
)
result = wait_task(task_id)
image_url = result["output"][0]["url"]
print(image_url)

Sur seedream-5.0-lite, resolution n'accepte que 2K ou 4K (pas de 1K). seedream-5.0-pro accepte 1K/2K et exige en plus aspect_ratio (l'une des valeurs 1:1, 4:3, 3:4, 16:9, 9:16, 2:3, 3:2, 21:9) — le schéma d'entrée de chaque niveau Seedream diffère légèrement, donc ne partez pas du principe qu'un champ accepté par un modèle s'applique à un autre.

Modèle de production

Choisissez le niveau par programmation, pas par habitude. Maintenez une petite table de coûts à côté du point d'appel, routez selon les besoins de budget/qualité au lieu de coder en dur le même modèle partout — traitez les chiffres comme un cache de la page de tarification, pas comme la source de vérité :

SEEDREAM_COST_USD = {
    ("seedream-5.0-flash", None): 0.025,
    ("seedream-5.0-lite", "2K"): 0.035,
    ("seedream-5.0-lite", "4K"): 0.035,   # same price — always prefer 4K
    ("seedream-5.0-pro", "1K"): 0.05,      # text-to-image; i2i 1K is $0.06
    ("seedream-5.0-pro", "2K"): 0.10,
}

def pick_model_for_draft_vs_final(is_final: bool) -> tuple[str, dict]:
    if not is_final:
        return "seedream-5.0-flash", {}  # $0.025, iterate freely
    return "seedream-5.0-pro", {"resolution": "2K"}  # $0.10, one shot at the end

Privilégiez les rappels au polling serré. Dans les pipelines à haut débit, au lieu d'appeler wait_task en boucle toutes les quelques secondes, ajoutez callback à la requête de création :

task_id_resp = requests.post(
    f"{BASE_URL}/tasks", headers=HEADERS,
    json={
        "model": "seedream-5.0-lite/text-to-image",
        "input": {"prompt": "...", "resolution": "4K"},
        "callback": {"url": "https://yourapp.example.com/webhooks/hiapi", "when": "final"},
    },
    timeout=30,
)

Lorsque la tâche atteint un état terminal (success ou fail), votre gestionnaire de webhook reçoit un POST, au lieu de laisser votre worker consommer des requêtes dans une boucle de polling. Si vous ne pouvez pas exposer de point de terminaison HTTPS public (développement local, outils internes), le polling reste le choix le plus simple — passez aux rappels dès que vous tournez à une échelle réelle.

Dédupliquez avant de créer la tâche, pas après. L'API de tâches facture à la création, donc une requête réessayée (timeout, crash du worker, redéploiement d'un consommateur de file) qui soumet à nouveau la même tâche est facturée deux fois. Avant d'appeler create_task, vérifiez dans votre propre stockage s'il existe déjà une tâche existante indexée par (model, input_hash), et si cette tâche est déjà en cours d'exécution ou a réussi, ignorez la création — le point de terminaison de tâche hiapi n'a pas de déduplication intégrée, donc cela doit être fait dans votre code.

Gérez explicitement les échecs d'authentification. Une clé invalide ou révoquée renvoie un HTTP 401 avec un corps de réponse structuré, et non une page d'erreur générique :

{"error": {"code": "permission_denied", "type": "hiapi_error", "request_id": "..."}}

Vérifiez spécifiquement error.code == "permission_denied", afin qu'une mauvaise clé échoue rapidement au lieu de réessayer jusqu'au timeout.

Ressources hiapi associées

Questions fréquentes

Quel modèle Seedream est le moins cher pour des brouillons rapides ou des icônes ? seedream-5.0-flash, forfait de 0,025 $/image — le niveau le moins cher de la plateforme, même prix pour texte-vers-image et image-vers-image.

Demander du 4K plutôt que du 2K sur Seedream 5.0 Lite coûte-t-il plus cher ? Non. seedream-5.0-lite est à forfait de 0,035 $/image, que resolution vaille 2K ou 4K, donc à ce niveau, demandez 4K par défaut.

Combien coûte Seedream 5.0 Pro par image ? Tarification par paliers de résolution : texte-vers-image à 0,05 $ en 1K, 0,10 $ en 2K ; image-vers-image à 0,06 $ en 1K, 0,10 $ en 2K. Contrairement à lite, la résolution change réellement votre facture ici.

Si ma tâche est réessayée, comment éviter d'être facturé deux fois ? L'API de tâches n'a pas de clé d'idempotence côté serveur, donc dédupliquez côté client : stockez une clé pour (model, input_hash) avant d'appeler create_task, et si cette clé est déjà en cours d'exécution ou a réussi, ignorez la création.

Dois-je utiliser le polling ou un rappel webhook ? Si vous ne pouvez pas exposer de point de terminaison HTTPS public (développement local, scripts), interrogez GET /v1/tasks/{taskId}. Dès que vous tournez à une échelle réelle, passez à callback.url + when: "final" — cela remplace la boucle de polling par une notification push par tâche.

Que renvoie une clé API invalide ? HTTP 401 et {"error": {"code": "permission_denied", "type": "hiapi_error", "request_id": "..."}}. Vérifiez explicitement ce code d'erreur au lieu de réessayer avec une mauvaise clé jusqu'au timeout.

Puis-je utiliser ces tarifs sans clé API au préalable ? Non — chaque appel /v1/tasks nécessite un en-tête Authorization: Bearer sk-... valide avec une vraie clé créée dans votre console ; la génération en production n'a pas de voie sans clé ni d'essai sans inscription.

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