Tutorial
Cómo usar seedream-4.5/image-to-image a través de la API de hiapi: curl, Python y solicitudes disponibles
Para editar imágenes con seedream-4.5, solo tienes que enviar un POST a la API de tareas unificada de hiapi, hacer un breve sondeo y descargar el resultado. Esta guía ofrece solicitudes curl funcionales y un script completo de Python para seedream-4.5/image-to-image, junto con una descripción precisa de los campos de entrada (verificada contra la API en línea), el uso con múltiples imágenes de referencia y los errores que realmente encontrarás.
Qué vas a construir y qué necesitas
Objetivo: enviar una o varias imágenes de origen junto con instrucciones de edición a seedream-4.5/image-to-image y recuperar la URL de la imagen terminada.
Requisitos previos:
- Una clave de API de hiapi, obtenida desde tu consola. Cada solicitud a continuación la usa como token Bearer.
- Las imágenes de origen deben estar alojadas en URLs de acceso público. La API las descarga en el servidor; las rutas de archivos locales o las URLs privadas no funcionan.
El modelo se ejecuta en el endpoint de tareas asíncronas: POST /v1/tasks crea la tarea, GET /v1/tasks/<taskId> informa del estado y la imagen terminada aparece en data.output[0].url.
Descripción de los campos de entrada (verificada)
seedream-4.5/image-to-image tiene cuatro campos de entrada obligatorios y no acepta otros; la especificación de campos es estricta y los campos desconocidos se rechazan con un 400:
| Campo | Tipo | Restricción |
|---|---|---|
prompt |
string | Instrucciones de edición |
image_urls |
array de strings | URLs públicas, hasta 14 imágenes |
aspect_ratio |
string | Uno de 1:1, 4:3, 3:4, 16:9, 9:16, 2:3, 3:2, 21:9 |
resolution |
string | Solo 2K o 4K |
Hay dos puntos que conviene destacar: no existe un parámetro n (una salida por tarea; si necesitas varias variantes, crea varias tareas en paralelo); y a diferencia de image-to-image de seedream-5.0-pro (que acepta 1K/2K), la versión 4.5 exige 2K o 4K. Enviar 1K aquí devuelve un error de validación.
Solicitud mínima funcional: curl
curl -s -X POST https://api.hiapi.ai/v1/tasks \
-H "Authorization: Bearer sk-<your-key>" \
-H "Content-Type: application/json" \
-d '{
"model": "seedream-4.5/image-to-image",
"input": {
"prompt": "Turn this product shot into a clean studio photo on a seamless white background with soft shadows",
"image_urls": ["https://your-cdn.example.com/source.jpg"],
"aspect_ratio": "1:1",
"resolution": "2K"
}
}'
Una creación exitosa devuelve el ID de tarea en data.taskId. Consúltalo:
curl -s https://api.hiapi.ai/v1/tasks/<taskId> \
-H "Authorization: Bearer sk-<your-key>"
Cuando data.status alcanza success, la URL de la imagen está en data.output[0].url. Si es fail, el motivo está en data.error.
Script completo de Python
No se necesita SDK, solo requests y un bucle de sondeo:
import time
import requests
API_BASE = "https://api.hiapi.ai/v1/tasks"
API_KEY = "sk-<your-key>"
HEADERS = {"Authorization": f"Bearer {API_KEY}"}
def edit_image(prompt: str, image_urls: list[str],
aspect_ratio: str = "1:1", resolution: str = "2K") -> bytes:
# 1. Create the task
resp = requests.post(API_BASE, headers=HEADERS, json={
"model": "seedream-4.5/image-to-image",
"input": {
"prompt": prompt,
"image_urls": image_urls, # public URLs, max 14
"aspect_ratio": aspect_ratio,
"resolution": resolution, # "2K" or "4K"
},
}, timeout=60)
resp.raise_for_status()
task_id = resp.json()["data"]["taskId"]
# 2. Poll until terminal state
deadline = time.time() + 600
while time.time() < deadline:
task = requests.get(f"{API_BASE}/{task_id}",
headers=HEADERS, timeout=30).json()["data"]
if task["status"] == "success":
url = task["output"][0]["url"]
# 3. Output URLs expire -- download immediately
return requests.get(url, timeout=120).content
if task["status"] == "fail":
err = task.get("error") or {}
raise RuntimeError(f"task failed: {err.get('code')} {err.get('message')}")
time.sleep(5)
raise TimeoutError(f"task {task_id} did not finish in 600s")
png = edit_image(
"Turn this product shot into a clean studio photo on a seamless white background",
["https://your-cdn.example.com/source.jpg"],
)
with open("edited.png", "wb") as f:
f.write(png)
Fíjate en el comentario del paso 3: las URLs de salida llevan una marca de tiempo de caducidad. En cuanto la tarea finaliza con éxito, debes persistir los bytes en tu propio almacenamiento; no guardes solo la URL devuelta y confíes en que seguirá funcionando mañana.
Edición con múltiples imágenes de referencia
image_urls acepta hasta 14 imágenes en una sola tarea. Es una herramienta muy útil para tareas de transferencia de estilo y composición: pasa la imagen que quieres editar junto con las imágenes de referencia y describe en el prompt cómo combinarlas.
{
"model": "seedream-4.5/image-to-image",
"input": {
"prompt": "Apply the color grading and lighting style of the second image to the first image, keep the subject unchanged",
"image_urls": [
"https://your-cdn.example.com/subject.jpg",
"https://your-cdn.example.com/style-reference.jpg"
],
"aspect_ratio": "3:2",
"resolution": "2K"
}
}
El orden importa para el prompt, no para la API: haz referencia a las imágenes por su posición ("la primera imagen", "la segunda imagen") para que el modelo sepa cuál es cuál.
Consideraciones para producción
Usa callbacks en lugar de sondeo. Para cualquier escenario que vaya más allá de un script, añade un objeto callback de nivel raíz al crear la tarea y omite por completo el bucle de sondeo:
{
"model": "seedream-4.5/image-to-image",
"input": { "...": "..." },
"callback": { "url": "https://yourapp.com/hooks/hiapi", "when": "final" }
}
Cuando la tarea termina, hiapi envía por POST el estado final de la tarea a tu URL. El sondeo es adecuado para herramientas CLI y notebooks; para un backend web, lo correcto es usar callbacks; de lo contrario, mantendrás ocupado un proceso de trabajo durante las decenas de segundos que requiere una edición en 2K.
Idempotencia. La creación de tareas no es idempotente: reintentar la creación tras un tiempo de espera de red puede generar (y facturar) dos tareas. Guarda el taskId en el momento en que lo recibas y, antes de crear una nueva tarea al reintentar, comprueba si ya existe una tarea activa.
Manejo de errores. Los dos tipos de fallo que encontrarás primero:
- 401
permission_denied: la clave es incorrecta o esa clave no tiene acceso a este modelo. El cuerpo de la respuesta se parece a{"error": {"code": "permission_denied", "message": "This API key cannot use the selected model...", "request_id": "..."}}. Incluye elrequest_idcuando contactes con soporte. - 400
INVALID_REQUEST: incumplimiento de la especificación de campos, con un mensaje preciso: valor deresolutionincorrecto, más de 14 elementos enimage_urls, un campo desconocido oimage_urlsque no es un array. Todos estos se detectan antes de que la tarea se ejecute, por lo que no generan coste.
Las tareas fallidas informan status: "fail" en la propia tarea, junto con un objeto error; trátalo como un caso distinto de los errores HTTP, tal como hace el script de Python anterior.
Precios
El coste por imagen depende de la resolución. Consulta las tarifas actuales en la página de precios. Las solicitudes rechazadas en la fase de validación (400) nunca inician una tarea, por lo que los errores de especificación de campos durante la integración son gratuitos.
Lecturas relacionadas
- Página del modelo seedream-4.5/image-to-image: zona de pruebas, precios y referencia completa de parámetros
- seedream-4.5/text-to-image: misma serie, generación solo a partir de prompt
- Guía de seedream-5.0-pro image-to-image: un nivel más reciente, con una enumeración de resolución diferente
- Documentación de hiapi: referencia de la API de tareas y autenticación
Preguntas frecuentes
¿Puedo pasar un archivo local o una imagen en base64 en lugar de una URL?
No. image_urls debe ser un array de URLs de acceso público; la plataforma las descarga y normaliza en el servidor. Sube primero a tu propio almacenamiento (S3, R2, cualquier CDN) y luego pasa la URL.
¿Cuántas imágenes de referencia admite seedream-4.5 image-to-image?
Hasta 14 por tarea. Si se supera, se devuelve un 400 con un mensaje que incluye image_urls: maxItems.
¿Por qué recibo un 400 cuando configuro resolution en 1K?
El endpoint image-to-image de la versión 4.5 solo acepta 2K o 4K. La opción 1K pertenece a image-to-image de seedream-5.0-pro; las enumeraciones difieren entre series de distintos niveles.
¿Puedo generar varias variantes en una sola solicitud?
No; la especificación de campos no incluye un parámetro n y rechaza los campos desconocidos. Crea una tarea por variante y ejecútalas en paralelo; cada tarea devuelve una sola salida.
¿Cuánto tiempo es válida la URL del resultado? Las URLs de salida llevan firma y tiempo de caducidad. Descarga la imagen en cuanto la tarea finalice con éxito y guárdala por tu cuenta, en lugar de enlazar directamente la salida de la tarea.
¿Cuál es la diferencia entre un error HTTP y una tarea fallida?
Un error HTTP (400/401) significa que la solicitud nunca llegó a ser una tarea: corrige el payload o la clave y vuelve a enviarla. Una tarea que termina con status: "fail" fue aceptada pero no pudo completarse; el motivo está en el objeto error de la tarea y, para fallos transitorios, normalmente lo correcto es reintentar con las mismas entradas.
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