HiAPI
Blog

Tutorial

Cómo llamar a recraft-v4-styles-pro/text-to-image en la API de hiapi: curl y Python

Oct 31, 2026
hiapi 博客封面:近黑底色上有序排列的薄荷绿数据点阵由疏到密渐变,呈半调网点质感,另有点缀深青色,画面无文字。

Qué hace este endpoint y cuándo usarlo

recraft-v4-styles-pro/text-to-image convierte un prompt de texto en una imagen, y su rasgo distintivo es la conciencia de estilo: puedes guiar el lenguaje visual del resultado mediante referencias de estilo en lugar de depender únicamente de la redacción del prompt. Es una opción práctica cuando la salida necesita mantener una sensación coherente a lo largo de muchas generaciones, y no solo verse bien en una o dos.

Los desarrolladores suelen utilizarlo en los siguientes escenarios:

  • Materiales de coherencia de marca: imágenes principales, tarjetas sociales y variantes publicitarias que deben encajar en un mismo sistema visual.
  • Maquetas de producto y marketing: ajustar repetidamente el prompt manteniendo fijo el estilo para producir un conjunto de variantes alineadas con la marca.
  • Pasos de canalización: la generación como una etapa dentro de una automatización mayor, en la que otro servicio consume la imagen guardada.

Hay una característica que determina cómo se escriben todos los ejemplos de código siguientes: la generación de imágenes es asíncrona. La solicitud envía una tarea y regresa de inmediato; la imagen aparece más tarde. Necesitas escribir el paso de envío y el paso de sondeo, y tratarlos como dos preocupaciones independientes.

Preparar las credenciales de hiapi y la base de la solicitud

Todas las llamadas pasan por la interfaz de endpoint unificada de hiapi, así que antes de la primera solicitud necesitas tres cosas:

  1. Una clave de API, obtenida de tu cuenta de hiapi. Trátala como cualquier otro secreto: cárgala desde una variable de entorno y nunca la codifiques directamente en un script que puedas compartir.
  2. El identificador del modelo, que debe coincidir exactamente con el publicado: recraft-v4-styles-pro/text-to-image.
  3. Una herramienta compatible con HTTP: curl para explorar y una biblioteca HTTP para cualquier escenario persistente.
export HIAPI_API_KEY="your-key-here"

Convenciones que vale la pena interiorizar cuanto antes:

  • Usa Content-Type: application/json al enviar un cuerpo JSON.
  • Autentícate con la cabecera de token bearer.
  • Envía el id del modelo, el prompt y las referencias de estilo como campos independientes del payload, en lugar de meterlo todo en una sola cadena; así el paso de sondeo y los registros serán más fáciles de entender.

Para los nombres exactos de las cabeceras, la URL base y las definiciones actuales de los campos, consulta la documentación de referencia de la API de hiapi para este modelo; considera este tutorial como la forma de la llamada y la referencia como la fuente autorizada de los nombres.

Una solicitud curl que funciona

La siguiente es la llamada de envío. Entiéndela en tres capas: transporte, autenticación y cuerpo de la solicitud.

curl -sS -X POST "$HIAPI_BASE_URL/generate" \
  -H "Authorization: Bearer $HIAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "recraft-v4-styles-pro/text-to-image",
    "prompt": "minimalist product photo of a ceramic mug on a linen surface, soft daylight",
    "style_references": []
  }'

Explicación línea por línea:

  • -X POST: envía una tarea, no obtiene una.
  • Authorization: Bearer ...: el token proviene de una variable de entorno, así que el comando se puede pegar de forma segura en la terminal y también compartir de forma segura tras quitar la variable.
  • -d '{...}': el cuerpo JSON. model es el identificador exacto. prompt es el texto libre que describe la escena. style_references es el punto de enganche para el control de estilo, que se tratará a continuación.
  • -sS: modo silencioso para la barra de progreso, pero aún muestra errores, de modo que las llamadas fallidas sean visibles.

Una respuesta correcta es una confirmación, no una imagen: obtienes el identificador de la tarea y su estado. Anota ese identificador, ya que es el único asa necesaria para el sondeo. Si estás explorando de forma interactiva, pasa la respuesta por un formateador JSON para que el id de la tarea y el estado destaquen.

Pasar referencias de estilo junto con el prompt

El modelo mental es sencillo: el prompt indica qué, y las referencias de estilo indican cómo debería verse. Mantenlos separados en el payload y conservarás flexibilidad: puedes volver a ejecutar el mismo prompt con varios conjuntos de estilos para comparar resultados.

{
  "model": "recraft-v4-styles-pro/text-to-image",
  "prompt": "ceramic mug on a linen surface, soft daylight",
  "style_references": [
    "https://your-bucket.example.com/styles/mug-ref-01.jpg",
    "https://your-bucket.example.com/styles/mug-ref-02.jpg"
  ]
}

Consejos prácticos:

  • Empieza sin referencias. Primero ejecuta el prompt sin nada más. Luego añade una referencia y observa la diferencia, después dos. Cambiar una sola cosa a la vez aporta mucha más información que usar todo un conjunto de estilos en el primer intento.
  • Mantén las referencias accesibles. Alójalas donde el servicio pueda obtenerlas de forma fiable, como un bucket público o una URL firmada con amplia vigencia, y no un enlace que caduque a los pocos minutos.
  • Mantén un conjunto coherente. Las referencias mutuamente coherentes (iluminación, paleta y textura similares) suelen producir resultados más estables que una mezcla heterogénea que obliga al modelo a reconciliar contradicciones.
  • Versiona las referencias. Guárdalas bajo claves estables. Cuando la salida dé problemas el mes que viene, necesitarás saber exactamente qué archivos de referencia se usaron entonces.

Consulta la documentación de referencia de hiapi para este modelo para confirmar si las referencias de estilo se pasan como URL, como recursos subidos o como presets con nombre, y qué límites hay sobre su cantidad y formato.

La misma llamada en Python

La llamada curl se traduce directamente. Envuelvela en pequeñas funciones para reutilizarla como etapa de una canalización.

import os
import requests

HIAPI_BASE_URL = os.environ["HIAPI_BASE_URL"]
HIAPI_API_KEY = os.environ["HIAPI_API_KEY"]


def submit_generation(prompt: str, style_references: list[str] | None = None) -> str:
    """Envía una tarea de texto a imagen y devuelve el id de la tarea."""
    payload = {
        "model": "recraft-v4-styles-pro/text-to-image",
        "prompt": prompt,
        "style_references": style_references or [],
    }
    response = requests.post(
        f"{HIAPI_BASE_URL}/generate",
        headers={
            "Authorization": f"Bearer {HIAPI_API_KEY}",
            "Content-Type": "application/json",
        },
        json=payload,
        timeout=30,
    )
    response.raise_for_status()
    data = response.json()
    return data["job_id"]

Notas de diseño:

  • Establece siempre un timeout. Un envío que se cuelga indefinidamente bloquea tu proceso de trabajo con la misma eficacia que un fallo.
  • raise_for_status() convierte las respuestas que no son 2xx en excepciones que puedes capturar y registrar, en lugar de continuar en silencio con un cuerpo de respuesta mal formado.
  • Devuelve solo el id. El id de la tarea es el contrato entre el envío y el sondeo. Mantener el resto de la respuesta fuera del código que hace la llamada facilita la escritura de la siguiente sección.

Confirma los nombres reales de los campos de respuesta en la documentación de referencia de hiapi y ajusta data["job_id"] en consecuencia; los nombres de los campos son lo más probable que difiera de los ejemplos de este artículo.

Sondear el estado de finalización de la tarea

La generación lleva tiempo. Sondea a intervalos regulares, detente en un estado terminal y abandona en algún momento.

import time


def wait_for_job(job_id: str, timeout: float = 300, interval: float = 3) -> dict:
    deadline = time.monotonic() + timeout
    while time.monotonic() < deadline:
        response = requests.get(
            f"{HIAPI_BASE_URL}/jobs/{job_id}",
            headers={"Authorization": f"Bearer {HIAPI_API_KEY}"},
            timeout=30,
        )
        response.raise_for_status()
        job = response.json()

        status = job["status"]
        if status == "succeeded":
            return job
        if status == "failed":
            raise RuntimeError(f"Job {job_id} failed: {job.get('error')}")

        time.sleep(interval)
    raise TimeoutError(f"Job {job_id} did not finish within {timeout}s")

Las partes menos obvias:

  • Tres resultados, no dos. Pendiente, correcto y fallido. Trata cualquier estado no reconocido como pendiente y registra una línea de log, para que un estado recién añadido no haga fallar el proceso de trabajo.
  • Una sola fecha límite para toda la espera. Una fecha límite basada en time.monotonic() no se ve afectada por ajustes del reloj, a diferencia de la aritmética con la hora del reloj de pared.
  • No consultes con demasiada frecuencia. Para la generación de imágenes, unos pocos segundos entre comprobaciones es suficiente. Si necesitas sondear más rápido, aplica retroceso entre intentos en lugar de acortar el intervalo.
  • Impón un tiempo de espera máximo. Una tarea que nunca termina debe manifestarse como un error que pueda alertar, no como un bucle que se ejecuta hasta que el contenedor es eliminado.

Si ejecutas muchas tareas, envíalas por lotes y sondea de forma concurrente (usa un bucle de eventos o un grupo de hilos con intervalos escalonados) en lugar de generar un sondeador por tarea en un bucle apretado.

Descargar y guardar la salida

Una tarea completada te da una referencia de imagen, normalmente una URL. Descárgala con prontitud, ya que estos enlaces pueden tener límites de tiempo.

def save_image(job: dict, path: str) -> None:
    url = job["output"]["image_url"]
    for attempt in range(3):
        try:
            with requests.get(url, stream=True, timeout=60) as r:
                r.raise_for_status()
                with open(path, "wb") as f:
                    for chunk in r.iter_content(chunk_size=8192):
                        f.write(chunk)
            return
        except requests.RequestException:
            if attempt == 2:
                raise
            time.sleep(2 ** attempt)

Prácticas que vale la pena adoptar en producción:

  • Descarga en streaming. Las imágenes generadas no son pequeñas; cargarlas por completo en memoria sin motivo es un desperdicio.
  • Escribe en una ruta temporal y luego renombra. Un fallo a mitad de escritura no debería dejar un archivo truncado donde la canalización espera una imagen válida.
  • Reintenta la descarga, no la generación. Reintentar una obtención inestable desde un bucket es barato; desperdiciar una generación no lo es. Limita el número de reintentos y usa retroceso exponencial.
  • Persiste el id de la tarea junto con el archivo. Cuando alguien pregunte de dónde vino una imagen, la respuesta debería requerir una sola consulta, no rebuscar en los registros.

Para el almacenamiento de objetos, sustituye open() por la carga en streaming de tu SDK y mantén el mismo envoltorio de reintentos.

Comprobaciones de errores, reintentos y racionalidad de costes

Los modos de fallo que encontrarás primero y cómo manejar cada uno:

  • 401 / errores de autenticación: la clave falta, está mal escrita o no se exportó al shell que ejecuta el script. Comprueba el entorno antes de tocar el payload.
  • Errores de validación 4xx: normalmente un id de modelo mal escrito, falta el prompt o una referencia de estilo mal formada. Registra el cuerpo de la respuesta literalmente; los mensajes de validación son la vía más rápida para corregirlo aquí.
  • 429 / límite de velocidad: usa retroceso con jitter en lugar de reintentar de inmediato. Establecer una cola antes de la función de envío es mejor que una tormenta de reintentos.
  • Tiempo de espera de la tarea: se disparó la fecha límite del sondeo. Decide deliberadamente si reenviar; reenviar a ciegas duplica el gasto sin mejorar la tasa de éxito.
  • Errores de red transitorios: reintenta el envío y la descarga con retroceso exponencial acotado. Reintenta la descarga con libertad; reintenta la generación con cautela.

Disciplina de costes, en términos prácticos:

  • La facturación sigue al trabajo que el modelo realmente ejecuta, así que las tareas fallidas y los lotes abandonados son costes ocultos. Registra cada envío con el hash de su prompt y el id de la tarea para poder auditar el uso más adelante.
  • Itera con los prompts más baratos posibles. Ajusta la redacción y las referencias de estilo en ejecuciones pequeñas y rápidas antes de comprometerte con lotes grandes.
  • Deduplica. Si el mismo prompt y el mismo conjunto de estilos se solicitan dos veces, entrega el resultado de la primera desde tu propia caché.
  • Establece un límite estricto de concurrencia en el proceso de trabajo. Subir el límite es más fácil que explicar una factura inesperada.

Con el envío, el sondeo y el guardado como tres funciones independientes y comprobables, este endpoint se integra limpiamente en cualquier canalización. Para los nombres exactos de los campos, los estados y los precios actuales, consulta la página del modelo recraft-v4-styles-pro/text-to-image en hiapi antes de la integración.

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