Tutorial
Genera imágenes de producto a medida exacta mediante API: relaciones de aspecto y especificaciones de plataformas de comercio electrónico
Cada canal de venta exige que tus imágenes de producto tengan un formato distinto: Amazon quiere imágenes cuadradas grandes sobre fondo blanco, Instagram quiere composiciones verticales 4:5, Pinterest quiere Pines 2:3, y el hero de la página de inicio de tu propia tienda necesita una imagen ultraancha. Esta guía explica cómo generar imágenes en todos estos formatos mediante programación con la API de hiapi —usando gpt-image-2 y wan2.7-image— y cómo obtener cada vez exactamente el tamaño en píxeles objetivo.
Requisitos previos: una clave de API de hiapi (créala en la consola) y curl o Python. El coste total depende del modelo y la resolución que elijas; consulta precios.
Cómo funcionan realmente los tamaños de imagen en la API
Primero, lo más confuso: los modelos de imagen de hiapi no aceptan tamaños en píxeles. No hay campos size, width ni height. Si intentas enviarlos, la API te lo dirá claramente:
{
"code": 400,
"error_code": "INVALID_REQUEST",
"message": "invalid input: <root>: additional properties 'size' not allowed"
}
En su lugar, el tamaño se controla con dos campos de input:
aspect_ratio: la forma del encuadre, elegida de una lista fija propia de cada modelo.resolution: el nivel de salida:"1K","2K"o"4K"(el lado largo mide aproximadamente 1024 / 2048 / 4096 píxeles; el número exacto de píxeles varía según la relación de aspecto, así que comprueba siempre el archivo que recibes).
A continuación se muestran los parámetros que aceptan realmente los dos modelos de esta guía (verificado con la API en producción):
gpt-image-2 |
wan2.7-image/text-to-image |
|
|---|---|---|
prompt |
Obligatorio | Obligatorio |
aspect_ratio |
auto, 1:1, 3:2, 2:3, 4:3, 3:4, 5:4, 4:5, 16:9, 9:16, 2:1, 1:2, 3:1, 1:3, 21:9, 9:21: 16 valores en total |
1:1, 16:9, 4:3, 21:9, 3:4, 9:16, 8:1, 1:8: 8 valores en total |
resolution |
1K, 2K, 4K |
1K, 2K, 4K |
| Capacidades adicionales | Variante imagen a imagen (gpt-image-2/image-to-image) |
seed (entero) para reproducibilidad |
size / n en píxeles |
No aceptado | No aceptado |
La diferencia práctica es: gpt-image-2 cubre las relaciones de aspecto necesarias para formatos de redes sociales y comercio electrónico (4:5, 2:3 y 5:4 son exclusivas de gpt-image-2), mientras que wan2.7-image añade banners ultraanchos 8:1/1:8, que ninguna otra lista de relaciones cubre; ideal para banners promocionales estrechos, y además es una opción habitual para imágenes de estudio en 4K.
Por tanto, para controlar el tamaño con precisión, la receta tiene dos pasos:
- Genera con una relación de aspecto que coincida y elige el nivel de resolución más pequeño cuyo lado largo alcance o supere el tamaño objetivo (reduce después, nunca amplíes).
- Ajusta localmente el archivo devuelto al tamaño exacto en píxeles objetivo: una línea de código con Pillow.
Tabla de referencia rápida de especificaciones de plataformas de comercio electrónico
A continuación se muestran los requisitos públicos habituales, asignados a los parámetros de la API:
| Canal | Objetivo típico | aspect_ratio |
resolution |
Notas del modelo |
|---|---|---|---|---|
| Imagen principal de Amazon | Lado largo ≥1000 píxeles (por encima de 1600 píxeles se habilita el zoom), cuadrada, fondo blanco puro | 1:1 |
2K |
Cualquiera de los dos |
| Página de producto de Shopify | Recomendado 2048×2048 | 1:1 |
2K |
Cualquiera de los dos |
| Feed de Instagram (vertical) | 1080×1350 | 4:5 |
2K |
Solo gpt-image-2 |
| Stories / Reels / TikTok | 1080×1920 | 9:16 |
2K |
Cualquiera de los dos |
| Pin de Pinterest | 1000×1500 | 2:3 |
2K |
Solo gpt-image-2 |
| Anuncio de Etsy | Recomendado 2700×2025 | 4:3 |
4K |
Cualquiera de los dos (requiere nivel 4K) |
| Banner hero del sitio web | Por ejemplo, 2560 píxeles de ancho | 21:9 |
4K |
Cualquiera de los dos |
| Banner promocional estrecho | Ultraancho | 8:1 |
2K/4K |
Solo wan2.7-image |
(Las especificaciones de cada plataforma cambian; considera estos objetivos en píxeles como recomendaciones públicas habituales y confírmalos con la documentación vigente de cada plataforma.)
Ejemplo mínimo funcional (curl)
Todo se ejecuta a través del endpoint unificado de tareas asíncronas: se crea con POST /v1/tasks y se consulta con GET /v1/tasks/<id>. Crea una imagen cuadrada al estilo de Amazon usando el nivel 2K:
curl -s -X POST https://api.hiapi.ai/v1/tasks \
-H "Authorization: Bearer sk-YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-image-2/text-to-image",
"input": {
"prompt": "Studio product photo of a stainless steel water bottle on a pure white background, centered, soft shadow, e-commerce catalog style",
"aspect_ratio": "1:1",
"resolution": "2K"
}
}'
El id de la tarea en la respuesta se encuentra en data.taskId. Consúltalo:
curl -s https://api.hiapi.ai/v1/tasks/TASK_ID \
-H "Authorization: Bearer sk-YOUR_KEY"
Consulta hasta que data.status cambie a "success" (o "fail", con los detalles en data.error). La URL de la imagen está en data.output[0].url. Esa URL caduca (el objeto de salida incluye expireAt), así que descárgala de inmediato y vuelve a alojarla en tu propio almacenamiento: nunca enlaces directamente desde el listado de productos.
Script de producción: un producto, todos los canales, píxeles exactos
Este script por lotes crea primero todas las tareas (se ejecutan en paralelo en la plataforma), consulta cada una hasta que termina y después ajusta con Pillow al tamaño exacto en píxeles. ImageOps.fit gestiona la reducción y cualquier recorte menor en una sola llamada.
import os
import time
from io import BytesIO
import requests
from PIL import Image, ImageOps
API = "https://api.hiapi.ai/v1"
HDRS = {
"Authorization": f"Bearer {os.environ['HIAPI_KEY']}",
"Content-Type": "application/json",
}
# canal -> parámetros de generación + objetivo exacto en píxeles
SPECS = {
"amazon-main": {"model": "gpt-image-2/text-to-image", "aspect_ratio": "1:1", "resolution": "2K", "px": (1600, 1600)},
"shopify": {"model": "gpt-image-2/text-to-image", "aspect_ratio": "1:1", "resolution": "2K", "px": (2048, 2048)},
"instagram-feed": {"model": "gpt-image-2/text-to-image", "aspect_ratio": "4:5", "resolution": "2K", "px": (1080, 1350)},
"story-reel": {"model": "gpt-image-2/text-to-image", "aspect_ratio": "9:16", "resolution": "2K", "px": (1080, 1920)},
"pinterest-pin": {"model": "gpt-image-2/text-to-image", "aspect_ratio": "2:3", "resolution": "2K", "px": (1000, 1500)},
"etsy-listing": {"model": "wan2.7-image/text-to-image", "aspect_ratio": "4:3", "resolution": "4K", "px": (2700, 2025)},
"hero-banner": {"model": "wan2.7-image/text-to-image", "aspect_ratio": "21:9", "resolution": "4K", "px": (2560, 1097)},
}
PROMPT = (
"Studio product photo of a stainless steel water bottle on a pure white "
"background, centered, soft shadow, high detail, e-commerce catalog style"
)
def create_task(model: str, prompt: str, aspect_ratio: str, resolution: str) -> str:
body = {
"model": model,
"input": {"prompt": prompt, "aspect_ratio": aspect_ratio, "resolution": resolution},
}
data = requests.post(f"{API}/tasks", json=body, headers=HDRS, timeout=60).json()
task_id = (data.get("data") or {}).get("taskId")
if not task_id:
raise RuntimeError(f"create failed: {data}")
return task_id
def wait_task(task_id: str, timeout_s: int = 600) -> str:
deadline = time.time() + timeout_s
while time.time() < deadline:
data = requests.get(f"{API}/tasks/{task_id}", headers=HDRS, timeout=30).json()
task = data.get("data") or {}
if task.get("status") == "success":
return task["output"][0]["url"]
if task.get("status") == "fail":
err = task.get("error") or {}
raise RuntimeError(f"task {task_id} failed: {err.get('code')} {err.get('message')}")
time.sleep(5)
raise TimeoutError(f"task {task_id} did not finish in {timeout_s}s")
def save_exact(url: str, px: tuple, path: str) -> None:
# La URL de salida caduca: descarga de inmediato y ajusta al tamaño exacto en píxeles.
raw = requests.get(url, timeout=120).content
img = Image.open(BytesIO(raw))
ImageOps.fit(img, px, Image.LANCZOS).save(path)
if __name__ == "__main__":
# Crea todas las tareas primero: las tareas se ejecutan concurrentemente en la plataforma
tasks = {
name: create_task(s["model"], PROMPT, s["aspect_ratio"], s["resolution"])
for name, s in SPECS.items()
}
for name, task_id in tasks.items():
url = wait_task(task_id)
save_exact(url, SPECS[name]["px"], f"{name}.png")
print(f"{name}: {SPECS[name]['px']} -> {name}.png")
Aunque reescribas el resto, hay dos detalles que merece la pena copiar:
- Elige el nivel de resolución de modo que el lado largo sea ≥ el objetivo. El objetivo de 2700 píxeles de Etsy supera los aproximadamente 2048 píxeles del nivel 2K, así que genera en
4Ky reduce después. Reducir con LANCZOS es visualmente imperceptible para uso en catálogo de productos; ampliar no lo es. - Persiste el
taskIdinmediatamente después de crear la tarea. Si tu worker se cae, al recuperarte consulta el id guardado en lugar de volver a crear la tarea: volver a crearla generaría (y facturaría) una segunda imagen.
Alternativa: recomponer una imagen principal ya revisada
Muchas veces no quieres siete imágenes generadas por separado, sino la misma imagen de producto revisada, recompuesta para cada canal. Para eso está gpt-image-2/image-to-image: requiere input_urls (un array de URLs de imágenes accesibles públicamente) y prompt, y acepta los mismos 16 valores de aspect_ratio:
{
"model": "gpt-image-2/image-to-image",
"input": {
"prompt": "Extend the background naturally to fill the new frame; keep the product unchanged and centered",
"input_urls": ["https://your-cdn.com/hero-shot.png"],
"aspect_ratio": "9:16"
}
}
El mismo ciclo de vida de tareas y, al final, el mismo paso de píxeles exactos. Para el recorrido completo, consulta How to Use gpt-image-2 Image-to-Image via the hiapi API.
Consideraciones de producción
Usa callbacks en lugar de consultas periódicas. En el lado del servidor, pasa un callback de nivel superior al crear la tarea y sáltate por completo el bucle de consultas:
{
"model": "gpt-image-2/text-to-image",
"input": {"prompt": "...", "aspect_ratio": "1:1", "resolution": "2K"},
"callback": {"url": "https://yourapp.com/hooks/hiapi", "when": "final"}
}
Recibirás una POST en el estado final. Trata el callback como una señal y no como la fuente de verdad: antes de actuar, vuelve a consultar GET /v1/tasks/<id> y deduplica por taskId. Si el callback nunca llega, consulta Why your hiapi task callback isn't firing.
Gestión de errores. Un fallo de autenticación devuelve 401 permission_denied; revisa primero la cabecera Authorization: Bearer sk-.... Un fallo de validación devuelve 400 con error_code: "INVALID_REQUEST", y su mensaje resulta especialmente útil: enumera los valores exactos permitidos (así se verificó la tabla de relaciones de aspecto anterior). El esquema de entrada varía según el modelo: wan2.7-image acepta seed, gpt-image-2 no; algunos modelos rápidos rechazan resolution por completo; por eso, consulta la página de cada modelo antes de codificar los campos de forma fija.
Control de costes. El precio varía según el modelo y el nivel de resolución. Genera en 1K mientras iteres el prompt y cambia a 2K/4K solo cuando tengas la versión final; los precios actuales por imagen están en la página de precios.
Lecturas relacionadas
- Página del modelo gpt-image-2 text-to-image · Página del modelo wan2.7-image text-to-image
- How to use gpt-image-2/text-to-image via the hiapi API: recorrido completo por los parámetros
- Wan 2.7 Text-to-Image for E-Commerce Product Photos: 4K Studio Shots
- Best AI Image Generation APIs in 2026: comparativa de modelos si aún estás eligiendo
Preguntas frecuentes
¿Puedo enviar en la solicitud un tamaño exacto en píxeles como 1080×1350?
No. size, width y height se rechazan con un 400 (additional properties ... not allowed). Genera con un aspect_ratio que coincida y un nivel de resolution igual o superior al objetivo, y después reduce localmente al tamaño exacto en píxeles: la línea de Pillow indicada arriba.
¿Qué configuración debo usar para la imagen principal de Amazon?
aspect_ratio: "1:1", resolution: "2K", y luego ajusta a tu tamaño objetivo (1600×1600 es un valor predeterminado fiable, por encima del umbral de zoom de 1000 píxeles). La imagen principal de Amazon también exige fondo blanco puro, así que indícalo en el prompt y revisa la salida antes de publicarla.
Mi relación de aspecto objetivo no está en la lista (por ejemplo, el formato de anuncio de enlace 1.91:1). ¿Qué hago?
Genera con la relación más ancha o igual más cercana que cubra por completo el objetivo (para 1.91:1, puedes usar 2:1 o 16:9) y después recorta centrado. ImageOps.fit del script hace exactamente eso: recorta el excedente y ajusta el tamaño en una sola llamada.
¿Cómo obtengo imágenes de producto realmente en 4K?
Establece resolution: "4K" en ambos modelos. wan2.7-image es una opción habitual para imágenes de estilo de estudio en 4K; para patrones de prompt, consulta la guía de comercio electrónico de Wan 2.7.
¿Caducan las URLs de las imágenes generadas?
Sí: cada salida incluye expireAt. Descarga el archivo inmediatamente después de que la tarea termine correctamente y vuelve a alojarlo en tu propio almacenamiento. Nunca pegues la URL de salida de la tarea en un listado de productos.
¿Puedo generar varias variantes en una sola solicitud?
No: estos modelos no tienen un parámetro n. Crea una tarea por imagen; las tareas se ejecutan en paralelo, así que procesarlas por lotes en un bucle (como en el script anterior) es igual de rápido en la práctica. En wan2.7-image, puedes cambiar la seed para obtener variantes controladas del mismo prompt.
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