HiAPI
Blog

Tutorial

Cómo llamar a flux-2-klein-4b/text-to-image mediante la API de HiAPI: curl, Python y una solicitud que funciona

Un tutorial práctico para integrar el nivel de imágenes económico en tu pipeline

Oct 31, 2026
平面玻璃风格封面图:数层半透明玻璃斜向叠压,把浅灰底场折射成冷蓝色带,构图安静克制。

Por qué flux-2-klein-4b/text-to-image encaja en cargas de trabajo sensibles al costo

No todos los pipelines de imágenes necesitan el modelo más pesado del catálogo. Una parte considerable del tráfico en producción es repetitivo: imágenes de productos, vistas previas de variantes, miniaturas de listados de productos, tarjetas sociales generadas a partir de la misma plantilla. Para estos escenarios, flux-2-klein-4b/text-to-image está diseñado como un nivel deliberadamente más ligero: cambias un poco de la máxima fidelidad por rendimiento y previsibilidad, y cuando generas miles de recursos en lotes programados, esa suele ser la decisión correcta.

Dos tipos de cargas de trabajo se benefician más:

  • Imágenes de productos de comercio electrónico. Normalmente tienes una descripción base limpia («taza de cerámica mate, 350 ml, gris cálido, sobre fondo blanco sin costuras») y necesitas generar una gran cantidad de variantes renderizadas que cubran colores, ángulos y composiciones. La consistencia importa más que la expresividad artística.
  • Generación por lotes para interfaces internas o de cola larga. Banners de categorías, creatividades de pruebas A/B, imágenes de marcador de posición para listados en borrador: en estos recursos, la mejora marginal de calidad no justifica el costo de ejecución de un modelo más pesado.

Cuando lo que produces es la imagen principal, las texturas finas y la composición en sí son el producto, elige un nivel más pesado. Cuando el volumen de generación, la latencia y el costo por imagen dominan la decisión, elige flux-2-klein-4b/text-to-image. El resto de este tutorial utiliza este nivel de principio a fin: estructura de la solicitud, llamada con curl, función auxiliar en Python, estrategia de relación de aspecto y ciclo de vida asíncrono.

Preparación antes de enviar la solicitud

Antes de la primera llamada, hay que determinar tres cosas.

1. La clave de API de HiAPI

Crea la clave en la consola de HiAPI. Todas las solicitudes descritas aquí se autentican con esa clave, y la clave es la única credencial que necesitas: no hay un proceso de registro separado por modelo.

2. Mantener la clave fuera del control de versiones

Trata la clave como cualquier otro secreto. Una práctica que funciona bien:

export HIAPI_API_KEY="your-key-here"

Luego léela desde el entorno en el shell y en Python. Nunca la confirmes en el repositorio; si usas un cargador de dotfiles, añade .env a .gitignore. Si la clave se filtra, rótala en la consola en lugar de intentar limpiar el historial.

3. Confirmar el identificador del modelo

La cadena del identificador se usa tal cual en el cuerpo de la solicitud y, en algunas configuraciones, también aparece en la URL:

flux-2-klein-4b/text-to-image

Cópiala exactamente: tanto 4b como el sufijo /text-to-image forman parte del nombre. Un error tipográfico aquí es la causa más común de errores 404 o «unknown model». Una vez que tengas la clave en el entorno y hayas confirmado el identificador, puedes construir la carga útil.

Composición de una solicitud a flux-2-klein-4b/text-to-image

Las solicitudes de texto a imagen en HiAPI se mantienen deliberadamente compactas. Proporcionas el identificador del modelo y un conjunto de parámetros de generación; lo que se devuelve es el resultado o un identificador de trabajo, según cómo esté configurado el endpoint de ese modelo.

Los campos más importantes

  • model: el identificador exacto, flux-2-klein-4b/text-to-image.
  • prompt: una cadena que describe la imagen. Es el campo que más influye en la calidad de la salida; dedica esfuerzo aquí antes de cambiar cualquier otra cosa.
  • Tamaño o relación de aspecto: cómo especificas el encuadre de la salida. Prefiere especificaciones en forma de relación de aspecto en lugar de pares de píxeles codificados, porque se mantiene estable incluso si cambia el comportamiento de resolución subyacente.

Cómo es la respuesta

La respuesta adopta dos formas, y tu cliente debe manejar ambas:

  1. Carga útil síncrona: la respuesta contiene directamente la ubicación de la imagen generada (una URL).
  2. Carga útil de trabajo asíncrono: la respuesta contiene un identificador de trabajo y un estado (pending, processing, succeeded, failed son estados típicos). Luego consultas el endpoint de estado con ese identificador hasta que alcance un estado terminal y la carga útil incluya la ubicación de la salida.

No inventes parámetros que no puedas verificar. Si un campo no forma parte del contenido de solicitud documentado de ese modelo, no lo incluyas: los campos desconocidos son la segunda causa más común de errores 400 confusos. Empieza con model, prompt y la relación de aspecto, obtén primero una imagen funcional y luego añade parámetros opcionales uno por uno, comprobando la salida tras cada cambio.

Tu primera llamada curl que funciona

A continuación tienes una solicitud completa que puedes pegar en la terminal. Supone que HIAPI_API_KEY ya se exportó como se indicó anteriormente.

curl -sS -X POST "https://api.hiapi.ai/v1/images/generations" \
  -H "Authorization: Bearer $HIAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "flux-2-klein-4b/text-to-image",
    "prompt": "Studio product photo of a matte ceramic mug, warm grey, soft diffused light, seamless white background, centered composition",
    "aspect_ratio": "1:1"
  }'

Pásala por un formateador JSON (| jq .) para leer la respuesta. Verás directamente la URL de la imagen o un objeto de trabajo con id y status.

Interpretar el resultado

  • Si obtienes una URL de imagen, ábrela en el navegador. Esto confirma que la clave, el identificador del modelo y el prompt funcionan correctamente.
  • Si obtienes un objeto de trabajo, anota el id: lo consultarás en la sección posterior.

Diagnosticar fallos comunes

  • 401 / 403: la clave falta, tiene un formato incorrecto o no se pasó mediante la cabecera Authorization: Bearer. Comprueba que la variable de entorno esté realmente exportada en el shell donde ejecutas curl.
  • 404 o «unknown model»: el identificador es incorrecto. Debe ser exactamente flux-2-klein-4b/text-to-image.
  • 400 con un mensaje de validación: normalmente falta prompt, hay un nombre de parámetro no admitido o la relación de aspecto no está en el conjunto aceptado. Reduce la carga útil a los tres campos principales y vuelve a intentarlo.
  • 429: estás enviando solicitudes más rápido de lo que permite tu nivel. Añade retroceso en lugar de reintentar en un bucle ajustado.

Una vez que curl funciona, tienes una solicitud que sabes que funciona y contra la cual comparar si la versión en Python falla.

Portar la misma solicitud a Python

La versión en Python es un envoltorio fino alrededor de la misma carga útil. Organízala como funciones para que el resto del pipeline pueda llamarla sin repetir la lógica HTTP.

import os
import time
import requests

API_BASE = "https://api.hiapi.ai/v1"
MODEL = "flux-2-klein-4b/text-to-image"

def generate_image(prompt: str, aspect_ratio: str = "1:1") -> dict:
    """Submit a text-to-image job and return the parsed response."""
    api_key = os.environ["HIAPI_API_KEY"]
    payload = {
        "model": MODEL,
        "prompt": prompt,
        "aspect_ratio": aspect_ratio,
    }
    response = requests.post(
        f"{API_BASE}/images/generations",
        headers={
            "Authorization": f"Bearer {api_key}",
            "Content-Type": "application/json",
        },
        json=payload,
        timeout=60,
    )
    if response.status_code >= 400:
        # Surface the server's message rather than a bare status code.
        raise RuntimeError(f"HiAPI error {response.status_code}: {response.text}")
    return response.json()

Algunos hábitos que dan resultados de inmediato:

  • Lee la clave desde el entorno dentro de la función, no en el momento de la importación, para que el mismo módulo sirva en notebooks, scripts y tareas programadas.
  • Comprueba explícitamente el código de estado e incluye el cuerpo de la respuesta en la excepción. Los mensajes de validación de HiAPI te dicen qué campo está mal; un raise_for_status() desnudo oculta esa información.
  • Establece un tiempo de espera. Sin él, una conexión atascada puede dejar colgado un proceso de trabajo indefinidamente.
  • Mantén la carga útil como un dict, para poder registrarla, comparar diferencias y ampliar parámetros opcionales sin reescribir el formato de la cadena.

Ahora un controlador mínimo:

result = generate_image(
    "Studio product photo of a matte ceramic mug, warm grey, "
    "soft diffused light, seamless white background, centered composition"
)
print(result)

Elegir relaciones de aspecto que resistan la producción

La relación de aspecto es el parámetro que más probablemente cause retrabajo más adelante, porque los sistemas posteriores asumen el encuadre. Decídela por interfaz, no por solicitud.

Una asignación práctica

  • Cuadrada (1:1): listados de marketplaces, cuadrículas de productos, avatares y posiciones de miniaturas. Es el valor predeterminado seguro para comercio electrónico, porque la mayoría de las tarjetas de producto son cuadradas y el recorte se ve mal.
  • Vertical (3:4 o 4:5): posiciones de feed social e imágenes de producto estilo lookbook. Da espacio a productos verticales como botellas y ropa sin añadir barras negras.
  • Horizontal (16:9): banners, franjas de imagen principal, encabezados de correo electrónico y miniaturas de vídeo.

Por qué fijar la proporción aguas arriba

Si la proporción la elige en el momento del renderizado el código que casualmente llama a la API, obtendrás un catálogo con la mitad de las tarjetas cuadradas y la otra mitad verticales, y tendrás que pagar una regeneración para arreglarlo. En su lugar, codifica la proporción en tu modelo de contenido: un campo surface o placement que se asigna de forma determinista a una proporción, y genera a partir de ese campo. Usa 1:1 en posiciones que toleran el recorte; usa la proporción que exija el diseño en posiciones con maquetación fija.

La misma disciplina se aplica al prompt: incluye las indicaciones de encuadre («composición centrada», «producto completo dentro del encuadre», «espacio libre a la izquierda para texto») en la plantilla del prompt, no en cadenas puntuales por llamada. Las plantillas hacen que mil imágenes generadas parezcan provenir del mismo pipeline, que es exactamente lo que necesita un catálogo de productos.

Una advertencia: no todos los modelos aceptan todas las proporciones. Envía la proporción que elijas una vez, confirma que tiene éxito y solo entonces extiéndela a todo el lote.

Sondear trabajos asíncronos hasta que finalicen

Cuando flux-2-klein-4b/text-to-image devuelve un identificador de trabajo en lugar de una imagen, trátalo como una máquina de estados. El flujo es: enviar → recibir el ID del trabajo → sondear el estado → estado terminal → leer la salida.

def wait_for_job(job_id: str, timeout_s: int = 300, interval_s: int = 2) -> dict:
    api_key = os.environ["HIAPI_API_KEY"]
    deadline = time.time() + timeout_s
    while time.time() < deadline:
        response = requests.get(
            f"{API_BASE}/jobs/{job_id}",
            headers={"Authorization": f"Bearer {api_key}"},
            timeout=30,
        )
        response.raise_for_status()
        job = response.json()
        status = job.get("status")
        if status == "succeeded":
            return job
        if status == "failed":
            raise RuntimeError(f"Job {job_id} failed: {job.get('error')}")
        time.sleep(interval_s)
    raise TimeoutError(f"Job {job_id} did not finish in {timeout_s}s")

Manejar cada estado

  • pending / processing: sigue esperando. Empieza con un intervalo corto y considera un retroceso suave (por ejemplo, aumentar el tiempo de espera hasta un límite) para no golpear con frecuencia el endpoint de estado durante colas largas.
  • succeeded: la carga útil contiene ahora la ubicación de la salida. Detén el sondeo de inmediato.
  • failed: no reintentes a ciegas. Registra el mensaje de error; si es un problema de prompt o de parámetros, reenviar la misma solicitud fallará de la misma manera.

Saber cuándo parar

Limita siempre el bucle con una fecha límite de reloj de pared. Un proceso de trabajo que sondea para siempre es un proceso de trabajo que se filtra. Al agotarse el tiempo, expón el ID del trabajo para inspeccionarlo manualmente: si el trabajo tiene éxito más tarde, aún puedes recuperar la salida. Para lotes, ejecuta varios trabajos de forma concurrente y sóndealos juntos, en lugar de serializar el envío y la espera para cada imagen.

Descargar y almacenar la salida

La imagen generada aparece en la respuesta de generación o del trabajo como una ubicación recuperable. Obténla en el servidor y luego persístela por tu cuenta: no enlaces en caliente la URL devuelta dentro de páginas de producto, porque es un artefacto de entrega, no tu capa de almacenamiento.

def download_image(url: str, path: str) -> str:
    response = requests.get(url, timeout=120)
    response.raise_for_status()
    with open(path, "wb") as f:
        f.write(response.content)
    return path

Usar un esquema de nombres predecible

Una ruta como images/{surface}/{sku}/{variant}-{ratio}.png te da tres cosas: los recursos se agrupan naturalmente por producto, la interfaz te dice qué encuadre se solicitó y la proporción en el nombre del archivo hace evidentes los duplicados accidentales. Si regeneras una variante del mismo SKU, incluye un hash corto del prompt en el nombre del archivo; así, una nueva ejecución no sobrescribe silenciosamente intentos anteriores que quizá quieras comparar.

Cerrar el ciclo

Registra el ID del trabajo junto con el archivo almacenado, en un manifiesto, una fila de base de datos o un archivo auxiliar. Cuando un sistema posterior informe de una imagen deficiente, el ID del trabajo es lo que te permite recuperar el prompt y los parámetros originales. Combinado con nombres de archivo basados en contenido, esto te da una pista de auditoría reproducible desde el recurso almacenado hasta la solicitud exacta que lo produjo.

Con el envío, el sondeo y la descarga conectados, flux-2-klein-4b/text-to-image se convierte en un paso más de tu pipeline: encolar trabajo, sondear con fecha límite, almacenar con nombres estables. A partir de ahí, escalar es solo una cuestión de concurrencia y plantillas, no de código nuevo.

Artículos relacionados

Ver todos los artículos →

Empieza a crear con artefactos de IA persistentes

Consigue tu API key y llama a modelos de imagen, vídeo y audio a través de una única API basada en tasks.

Leer la documentación de la API