Tutorial
Cómo llamar a gpt-image-2/text-to-image@ext a través de la API de HiAPI: curl y Python
Ejercicio práctico de solicitudes para desarrolladores que integran la generación de imágenes a partir de texto
Qué te ofrece gpt-image-2/text-to-image@ext
gpt-image-2/text-to-image@ext es un modelo de generación de imágenes a partir de texto que se expone a través de la interfaz unificada de HiAPI. Solo tienes que enviar el prompt y los parámetros de generación opcionales al mismo endpoint para obtener los datos de la imagen generada. No hace falta instalar ningún componente específico del modelo, ni integrar el SDK de cada proveedor por separado, ni gestionar cuentas independientes: la misma API key y la misma estructura de solicitud cubren el resto de capacidades de la plataforma.
Elige este modelo cuando tu producto necesite convertir descripciones de texto en imágenes nuevas: copy de marketing en visuales principales, prompts de usuario en miniaturas, herramientas de diseño que renderizan bocetos conceptuales bajo demanda. Como la llamada es una solicitud HTTP normal, se integra fácilmente en servicios backend, workers de cola o scripts, sin necesidad de ninguna biblioteca cliente.
Es la opción adecuada cuando la entrada es texto y la salida es un mapa de bits que vas a almacenar y distribuir por tu cuenta. Si más adelante necesitas cambiar a otra ruta de imagen en la plataforma, la lógica de integración —autenticación, envoltura de la solicitud, procesamiento de la salida— se mantiene igual; solo cambias el identificador del modelo y el bloque de parámetros.
Cómo leer esta guía
Este ejercicio avanza por capas. Primero una solicitud mínima que devuelve una imagen, luego la versión en Python, después la decisión estructural entre llamada única y sondeo asíncrono, y por último el procesamiento de la salida. Cada capa se puede probar de forma independiente, así que cuando algo falle sabrás exactamente qué cambio lo introdujo.
Requisitos previos y autenticación
Antes de enviar la primera solicitud necesitas dos cosas: una cuenta de HiAPI y una API key vinculada a ella. Crea la key en el panel de la cuenta y guárdala como guardarías cualquier secreto: variable de entorno en local, gestor de secretos en producción. No la confirmes en el repositorio ni la pegues en código cliente que se envíe al navegador.
La autenticación se realiza mediante un token bearer en la cabecera. El formato es siempre el mismo:
Authorization: Bearer $HIAPI_API_KEY
Define esa variable una vez en la shell y los ejemplos siguientes podrán referenciarla sin mostrar la clave:
export HIAPI_API_KEY="your-key-here"
Qué confirmar antes de empezar
- La key está activa y tiene permiso de acceso a la generación de imágenes.
- Tu entorno puede realizar solicitudes HTTPS salientes al endpoint de HiAPI.
- Tienes claro dónde se escribirán los archivos generados: un directorio local para pruebas, almacenamiento de objetos en producción.
Si la key falta o tiene un formato incorrecto, el problema se manifiesta de inmediato en la primera llamada como un error de autenticación, que es el momento más temprano y claro para detectarlo.
Una solicitud curl mínima que funciona
Empieza por la solicitud más pequeña que produce una imagen. Todo excepto el prompt es opcional, y mantener la primera llamada escueta significa que cualquier error casi con certeza estará relacionado con la autenticación o la estructura de la solicitud, y no con un conflicto de parámetros.
curl -sS -X POST "$HIAPI_BASE_URL/v1/images/generations" \
-H "Authorization: Bearer $HIAPI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-image-2/text-to-image@ext",
"prompt": "Una brújula de latón desgastada sobre un mapa de papel doblado, luz suave de ventana, profundidad de campo reducida",
"size": "1024x1024",
"n": 1
}'
Explicación campo por campo
model: el identificador del modelo. Es el único valor que vincula la solicitud agpt-image-2/text-to-image@ext; debe ser exacto.prompt: la descripción del contenido. Sé específico sobre el sujeto, el estilo y la iluminación; los prompts vagos producen imágenes vagas y son más difíciles de depurar que un error de parámetros.size: el tamaño de salida. Puede omitirse durante la fase de validación de la canalización y aceptar el valor predeterminado.n: el número de imágenes generadas por llamada. Mantenlo en 1 durante la integración para que un fallo corresponda exactamente a una salida.
Escribe la respuesta en un archivo para poder inspeccionarla sin que los datos binarios ensucien la terminal:
curl -sS -X POST "$HIAPI_BASE_URL/v1/images/generations" \
-H "Authorization: Bearer $HIAPI_API_KEY" \
-H "Content-Type: application/json" \
-d @payload.json -o response.json
En cuanto devuelva una imagen, tendrás una línea base que sabes que funciona. Cada cambio posterior debe ser una edición única y reversible respecto a ella.
Portar la solicitud a Python
La versión en Python es la misma solicitud, solo que con otro medio de transporte. Usa requests: es la opción con menos sorpresas y se corresponde campo por campo con el curl que ya validaste.
import os
import requests
API_KEY = os.environ["HIAPI_API_KEY"]
BASE_URL = os.environ["HIAPI_BASE_URL"]
payload = {
"model": "gpt-image-2/text-to-image@ext",
"prompt": "Una brújula de latón desgastada sobre un mapa de papel doblado, luz suave de ventana",
"size": "1024x1024",
"n": 1,
}
response = requests.post(
f"{BASE_URL}/v1/images/generations",
headers={
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json",
},
json=payload,
timeout=120,
)
response.raise_for_status()
data = response.json()
Lectura de los puntos clave
json=payloadestablece el tipo de contenido y serializa el cuerpo en un solo paso: sin concatenación manual de cadenas ni errores de escape.- En la práctica
timeoutno es opcional. La generación de imágenes es más lenta que una llamada típica a una API JSON; carecer de tiempo de espera significa que el worker se colgará cuando el servicio ascendente vaya lento. raise_for_status()convierte un fallo HTTP en una excepción que puedes capturar y clasificar, en lugar de dejar que un cuerpo de respuesta malformado fluya aguas abajo.
Mantén el payload como un dict, no como una cadena en línea. Cuando añadas parámetros más adelante solo tendrás que agregar claves: la estructura de la solicitud no cambia y nunca tendrás que volver a depurar la capa de transporte.
Si prefieres un cliente de estilo SDK, el mismo endpoint y las mismas cabeceras siguen aplicando; solo cambia la sintaxis de la llamada. Valida primero con curl y luego adopta el cliente que tu aplicación ya tenga estandarizado.
Elegir entre llamada única y sondeo asíncrono
Esta es una decisión de diseño, no de sintaxis, y afecta a la lógica de reintentos y almacenamiento más que cualquier otra elección de la integración.
Llamada única
Usa un ciclo único de solicitud-respuesta cuando:
- Generas bajo demanda y hay un usuario esperando.
- Tu capa HTTP tolera conexiones prolongadas.
- Generas una imagen a la vez en lugar de en lote.
Configura el tiempo de espera con holgura respecto al tiempo de generación más lento que hayas observado, y trátalo como un fallo reintentable, no como un error definitivo.
Sondeo asíncrono
Elige asíncrono en procesamiento por lotes, cuando las solicitudes provienen de un worker de cola o cuando el llamador no debe bloquearse. El patrón es: enviar, obtener un identificador y luego sondear el estado de finalización.
import time
def poll_until_done(fetch_status, handle, interval=2, max_wait=300):
deadline = time.monotonic() + max_wait
while time.monotonic() < deadline:
status = fetch_status(handle)
if status["state"] == "succeeded":
return status
if status["state"] == "failed":
raise RuntimeError(status.get("error", "generation failed"))
time.sleep(interval)
raise TimeoutError("generation did not finish in time")
Reglas para un bucle de sondeo con comportamiento fiable
- Retroceso progresivo. Empieza con un intervalo corto y auméntalo; sondear de forma constante y ajustada desperdicia cuota y presupuesto de tasa.
- Limita la espera. Una fecha límite
max_waitevita que tareas huérfanas ocupen un worker indefinidamente. - Persiste el identificador. Si el worker se reinicia, debes poder reanudar el sondeo en lugar de reenviar y pagar por una generación duplicada.
- Trata el fallo como estado terminal de cada tarea. El estado
faileddebe registrarse, no reintentarse silenciosamente en un bucle ajustado.
Decídelo pronto. Adaptar la semántica asíncrona a una ruta de código síncrona después implica reescribir a la vez el llamador, el almacenamiento y el manejo de errores.
Procesar la salida de imagen
La respuesta contiene la imagen generada, pero son datos dentro de un envoltorio JSON, no una URL enlazable directamente. Trátala como una salida binaria que te pertenece.
Decodificar y persistir
import base64
item = data["data"][0]
image_bytes = base64.b64decode(item["b64_json"])
with open("out.png", "wb") as f:
f.write(image_bytes)
Si la respuesta trae una URL en lugar de datos en línea, descárgala de inmediato y escribe los bytes en tu propio almacenamiento. Las URL generadas son temporales; cualquier contenido que sirvas a tus usuarios debe estar detrás de tu propia infraestructura.
Valida antes de distribuir
- Comprueba los números mágicos. PNG empieza por
\x89PNG; una página de error HTML no. Una verificación de unos pocos bytes captura los problemas de proxy que devuelven HTTP 200 con un cuerpo de respuesta equivocado. - Registra el tamaño. Anota la longitud en bytes para que las descargas truncadas se vean en la monitorización.
- Almacenamiento determinista. Nombra los archivos por el ID de generación en lugar de por el texto del prompt, y guarda el prompt, los parámetros y los metadatos de la respuesta junto con la imagen. Esa combinación te permite reproducir o auditar cualquier salida más adelante.
- Configura correctamente el tipo de contenido, derivándolo del archivo real y no de una suposición.
Conserva los metadatos junto al artefacto
Escribe un pequeño registro asociado: el identificador del modelo, el prompt completo, el tamaño y la cantidad, la marca de tiempo y cualquier ID de solicitud de la respuesta. Dentro de seis meses, cuando alguien pregunte por qué esa imagen se ve así, este registro será tu única respuesta.
Depurar los fallos habituales
La mayoría de los fallos de una primera integración encajan en tres categorías. Revísalas en este orden: el coste de diagnóstico va aproximadamente de menor a mayor.
Errores de autenticación
401 o 403 significan que la key es incorrecta, ha sido revocada o no se está enviando. Revisa la construcción de la cabecera sin la clave para confirmar que el prefijo Bearer y el espacio están intactos, y confirma que la variable de entorno está realmente definida en el proceso que realiza la solicitud; una trampa habitual es haberla definido en la shell pero no en el worker o el contenedor.
Cuerpo de solicitud malformado
400 suele apuntar al cuerpo de la solicitud. Vuelve a la solicitud mínima de la sección curl y añade los campos uno a uno. Culpables habituales:
- La cadena de
modelno coincide exactamente congpt-image-2/text-to-image@ext. - El cuerpo no es JSON válido: comas sobrantes o comillas sin escapar.
- Tipo de parámetro incorrecto;
nes un número, no una cadena. - Falta
Content-Type: application/json, por lo que el servidor no puede analizar el cuerpo.
Tiempos de espera y respuestas lentas
Si la conexión se corta antes de que llegue la imagen, es muy probable que hayas superado el tiempo de espera del cliente y no que hayas encontrado un fallo del modelo. Para un diseño de llamada única, aumenta el tiempo de espera; para cualquier forma de procesamiento por lotes, cambia al sondeo asíncrono. Al reintentar, asegúrate de no duplicar la generación: si es posible que una solicitud ya haya tenido éxito, comprueba si existe un resultado antes de reenviarla.
Cuando nada de lo anterior aplica
Captura la respuesta completa de la solicitud fallida —código de estado, cabeceras y cuerpo— y reprodúcela con el comando curl mínimo. Un fallo que persiste con la solicitud mínima es un problema de integración de tu entorno; un fallo que desaparece apunta a los parámetros que añadiste.
Artículos relacionados
Ver todos los artículos →-
Tutorial
Cómo llamar a hailuo-2.3-fast/image-to-video a través de la API de HiAPI: práctica con curl y Python
La primera solicitud ejecutable del nivel rápido y de bajo coste de imagen a vídeo: del ID del modelo a la descarga del MP4
-
Tutorial
Cómo llamar a hailuo-2.3/text-to-video mediante la API de HiAPI: curl, Python y ejemplos de solicitud ejecutables
-
Tutorial
Uso de Kandinsky 6.0 Pro texto a video en HiAPI: tutorial con curl y Python
Demostración práctica centrada en la solicitud: construir la llamada de prompt a clip de video, enviar la solicitud, sondear el estado de finalización y descargar el resultado