Tutorial
Cómo usar grok-imagine-quality/image-to-image a través de la API de hiapi: curl, Python y solicitudes funcionales
Esta guía te muestra cómo transformar imágenes existentes con grok-imagine-quality/image-to-image (el nivel de mayor fidelidad de la familia Grok Imagine) a través de la API de tareas unificada de hiapi. Enviarás una imagen de origen y un prompt de texto, consultarás el resultado de forma periódica y descargarás la imagen generada. Cada estructura de solicitud y respuesta que aparece a continuación está verificada contra la API en vivo.
Lo que necesitas
- Una clave de API de hiapi — créala en el panel de control.
- De uno a tres URL de imágenes de acceso público para usar como origen. La plataforma obtiene y normaliza tu medio de entrada en el servidor, por lo que las rutas de archivos locales y las cargas base64 no funcionan — aloja primero tus imágenes en una ubicación accesible para la API.
Eso es todo. No se necesita SDK; la API de tareas es simple HTTPS + JSON.
Modo de solicitud
grok-imagine-quality/image-to-image se ejecuta en el endpoint de tareas asíncronas: creas una tarea con POST /v1/tasks y luego consultas GET /v1/tasks/<taskId> (o registras un callback) hasta que termine.
El esquema de entrada es estricto — los campos desconocidos se rechazan con 400:
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
prompt |
string | ✅ | Qué hacer con la imagen de origen |
image_urls |
string[] | ✅ | URL públicas de 1–3 imágenes de origen/referencia |
aspect_ratio |
string | – | Uno de: auto, 2:1, 20:9, 19.5:9, 16:9, 4:3, 3:2, 1:1, 2:3, 3:4, 9:16, 9:19.5, 9:20, 1:2 |
resolution |
string | – | 1k o 2k — minúsculas (1K devuelve 400) |
output_format |
string | – | jpeg, png o webp |
Fíjate en lo que no hay: sin size, sin n, sin seed, sin perillas de strength ni consistency. Cuánto sigue la salida a la imagen de origen lo controlan tu prompt y las imágenes de referencia que pasas — consulta las Preguntas frecuentes a continuación.
Ejemplo mínimo funcional (curl)
Crear la tarea:
curl -X POST https://api.hiapi.ai/v1/tasks \
-H "Authorization: Bearer sk-<your-key>" \
-H "Content-Type: application/json" \
-d '{
"model": "grok-imagine-quality/image-to-image",
"input": {
"prompt": "Turn this product photo into a clean studio shot on a light gray background with soft shadows",
"image_urls": ["https://your-cdn.example.com/source.jpg"],
"aspect_ratio": "1:1",
"resolution": "2k",
"output_format": "png"
}
}'
Una creación exitosa devuelve un ID de tarea:
{
"code": 200,
"data": {
"taskId": "task_xxxxxxxxxxxx"
}
}
Consulta hasta que la tarea alcance un estado terminal:
curl https://api.hiapi.ai/v1/tasks/task_xxxxxxxxxxxx \
-H "Authorization: Bearer sk-<your-key>"
Mientras se ejecuta, data.status está en curso; cuando termina pasa a success y la imagen está en data.output:
{
"code": 200,
"data": {
"taskId": "task_xxxxxxxxxxxx",
"status": "success",
"output": [
{
"url": "https://.../result.png?...&expireAt=...",
"expireAt": 1760000000
}
]
}
}
⚠️ La URL de salida es temporal (fíjate en expireAt). Descarga los bytes inmediatamente después de que la tarea tenga éxito y guárdalos en tu propio almacenamiento — no enlaces en caliente la URL del resultado.
Si la tarea falla, data.status es fail y data.error lleva code y message.
Python: crear, consultar, descargar
Un script completo que solo usa requests:
import time
import requests
API_BASE = "https://api.hiapi.ai/v1/tasks"
API_KEY = "sk-<your-key>"
HEADERS = {
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json",
}
def create_task(prompt: str, image_urls: list[str]) -> str:
payload = {
"model": "grok-imagine-quality/image-to-image",
"input": {
"prompt": prompt,
"image_urls": image_urls, # 1-3 public URLs
"aspect_ratio": "1:1",
"resolution": "2k", # lowercase: "1k" or "2k"
"output_format": "png",
},
}
r = requests.post(API_BASE, headers=HEADERS, json=payload, timeout=60)
data = r.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, poll_interval: int = 5) -> dict:
deadline = time.time() + timeout_s
while time.time() < deadline:
r = requests.get(f"{API_BASE}/{task_id}", headers=HEADERS, timeout=30)
task = r.json().get("data") or {}
status = task.get("status")
if status == "success":
return task
if status == "fail":
err = task.get("error") or {}
raise RuntimeError(f"task failed: {err.get('code')} {err.get('message')}")
time.sleep(poll_interval)
raise TimeoutError(f"task {task_id} still running after {timeout_s}s")
if __name__ == "__main__":
task_id = create_task(
prompt="Turn this product photo into a clean studio shot on a light gray background",
image_urls=["https://your-cdn.example.com/source.jpg"],
)
print("task:", task_id)
task = wait_task(task_id)
url = task["output"][0]["url"]
# The output URL expires -- download immediately and persist yourself
img = requests.get(url, timeout=120).content
with open("result.png", "wb") as f:
f.write(img)
print(f"saved result.png ({len(img)} bytes)")
Consideraciones para producción
Usa callbacks en lugar de polling
Para cualquier escenario más allá de un script de un solo uso, registra un callback y omite el bucle de polling. Añade un objeto callback de nivel superior (al mismo nivel que model e input):
{
"model": "grok-imagine-quality/image-to-image",
"input": { "...": "..." },
"callback": {
"url": "https://your-app.example.com/hooks/hiapi",
"when": "final"
}
}
when solo admite "final" — recibirás exactamente un POST cuando la tarea alcance un estado terminal (success o fail). Regla general:
- Polling funciona para CLI, notebooks y trabajos por lotes, donde el proceso se mantiene vivo de todos modos. Consulta cada 3–5 segundos; no martilles con intervalos inferiores al segundo.
- Callbacks son mejores para backends web: sin conexiones colgadas, sin hilos de trabajo ocupados durante la generación. Vuelve a obtener
GET /v1/tasks/<taskId>en el servidor para verificar la carga útil, en lugar de confiar ciegamente en el cuerpo del webhook.
Idempotencia
La creación de tareas no es idempotente por sí misma — si tu proceso se cae después de POST /v1/tasks pero antes de persistir el taskId, el reintento creará (y cobrará) una segunda tarea. Persiste el taskId en tu propio almacenamiento, indexado por tu ID de trabajo interno, antes de empezar a esperar, y al reiniciar recupera consultando el taskId almacenado en lugar de crear uno nuevo.
Manejo de errores
Los errores que encontrarás en la práctica:
401permission_denied— la clave de API no es válida o no tiene acceso a este modelo. El cuerpo de la respuesta incluye unrequest_idque puedes enviar al soporte:{ "error": { "code": "permission_denied", "message": "This API key cannot use the selected model. ...", "request_id": "2026...", "type": "hiapi_error" } }400INVALID_REQUEST— violación del esquema, con un mensaje preciso. Ejemplos reales de este modelo:prompt: missing required field "prompt"— olvidaste un campo obligatorio.image_urls: maxItems: got 12, want 3— demasiadas imágenes de referencia (máximo 3).resolution: value must be one of '1k', '2k'— enviaste1K/4K.additional properties 'seed' not allowed— pasaste un campo que este modelo no acepta.
Estado terminal
fail— la tarea se aceptó pero la generación falló (por ejemplo, no se pudo obtener la URL de origen). Revisadata.error.message, corrige la entrada y crea una nueva tarea.
Usa reintentos con retroceso exponencial para 5xx y errores de red; no reintentes 400 — fallarán de la misma manera hasta que corrijas la carga útil.
Elegir el nivel de calidad (y ¿qué pasa con la «consistencia»?)
La familia Grok Imagine en hiapi se divide en IDs de modelo separados por nivel y modalidad. Para imagen a imagen, puedes elegir:
grok-imagine-quality/image-to-image— el nivel de alta fidelidad que trata este artículo; más lento, mejor conservación de detalles.grok-imagine/image-to-image— el nivel estándar; mismo esquema de solicitud, más rápido y más económico por imagen.
El nivel es el ID de modelo — no hay ningún parámetro quality dentro de input (enviarlo devuelve 400 additional properties 'quality' not allowed). El precio por imagen de ambos niveles está en la página de precios.
Lecturas relacionadas
- Página del modelo grok-imagine-quality/image-to-image — playground y precios
- Cómo usar grok-imagine/text-to-image — genera primero una imagen de origen desde cero
- Cómo usar grok-imagine/image-to-video — da movimiento a tus resultados
- Documentación de hiapi — autenticación, API de tareas y el resto de la plataforma
Preguntas frecuentes
¿Hay un parámetro de consistencia o de intensidad?
No. El esquema de entrada solo acepta prompt, image_urls, aspect_ratio, resolution y output_format; cualquier otra cosa se rechaza con 400. Para controlar cuánto sigue la salida a la imagen de origen, indica explícitamente en el prompt qué debe conservarse («mantén el producto y la etiqueta idénticos, cambia solo el fondo») y pasa hasta 3 imágenes de referencia mediante image_urls.
¿Puedo subir un archivo local o enviar base64?
No directamente — image_urls acepta URL y la plataforma las obtiene en el servidor. Sube el archivo a cualquier almacenamiento de acceso público (S3, R2, CDN) y pasa esa URL.
¿Cuántas imágenes de origen puedo pasar?
De 1 a 3. Un array vacío falla con minItems: got 0, want 1; más de 3 falla con maxItems.
¿Qué resoluciones y relaciones de aspecto se admiten?
resolution es 1k o 2k (solo minúsculas). aspect_ratio admite 14 valores desde 2:1 hasta 1:2, incluidos auto, 16:9, 1:1, 9:16 y los aptos para móvil 9:19.5/9:20.
¿Cuánto dura la URL de salida?
Cada salida lleva una marca de tiempo expireAt. Trata los resultados como efímeros: descarga los bytes inmediatamente después de que la tarea tenga éxito y guárdalos tú mismo.
¿Cómo genero múltiples variantes?
No hay parámetro n — crea una tarea por variante. Las tareas se ejecutan de forma independiente, así que puedes enviar varias en paralelo.
Si mi clave es correcta, ¿qué significa 401 permission_denied?
La clave existe pero no puede usar este modelo (por plan o por alcance de permisos). Revisa los permisos de modelos de la clave en el panel de control, o contacta con soporte usando el request_id del cuerpo de la respuesta de error.
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