HiAPI
Blog

Tutorial

Cómo mejorar la resolución de imágenes con la API de hiapi: un flujo de trabajo de escalado a 4K

Una solución de imagen a imagen ejecutable para escalado generativo a 2K/4K, con Python, callbacks y manejo de errores.

Sep 8, 2026
Cómo mejorar la resolución de imágenes con la API de hiapi: un flujo de trabajo de escalado a 4K

Si tienes una imagen de producto de baja resolución, una pequeña miniatura generada por IA o un escaneo antiguo y necesitas una versión nítida en 2K/4K, no necesitas montar un servicio dedicado de superresolución. El endpoint unificado /v1/tasks de hiapi te permite lanzar la misma solicitud contra varios modelos de imagen que aceptan una imagen existente y la redibujan en un nivel de resolución superior. Esta guía muestra el flujo completo y ejecutable: enviar la tarea, consultar su estado (o recibir un callback) para obtener el resultado y, después, descargar el archivo ampliado.

Una aclaración honesta antes de empezar: hiapi todavía no ofrece un modelo dedicado de superresolución que preserve los píxeles. Lo que obtienes aquí es escalado generativo: el modelo redibuja tu imagen de origen a una resolución objetivo superior siguiendo un prompt que le pide mantener la composición y añadir detalle. En fotografías e ilustraciones, esto suele ser lo que la gente entiende por «mejorar la resolución de una imagen», pero no es una interpolación sin pérdidas, así que si necesitas un escalado de píxeles bit a bit exacto, por ejemplo en una captura de pantalla con texto pequeño, esto no es lo indicado.

Qué vas a construir y qué necesitas antes de empezar

Vas a construir un pequeño script que:

  1. Envía una referencia a tu imagen existente (cualquier URL pública sirve: tu propio CDN, R2, S3, etc.)
  2. Envía una tarea de imagen a imagen que solicita un redibujado a 4K
  3. Consulta el estado hasta que la tarea termina y descarga el resultado de mayor resolución

Antes de empezar:

  • Una cuenta de hiapi y una clave de API, creada en la página API Keys del panel. Cada solicitud de abajo requiere Authorization: Bearer sk-<your-key>; sin la clave no puedes llamar a estos endpoints.
  • Una URL accesible públicamente que apunte a la imagen que quieres ampliar. El worker de tareas de hiapi descarga la imagen en el servidor, así que una ruta localhost o un bucket privado no sirven: primero súbela a cualquier host público.
  • Python 3.8+ con requests instalado (pip install requests), o bien curl directamente si prefieres probar desde la shell.

Ejemplo mínimo ejecutable

La opción más limpia es seedream-5.0-lite/image-to-image. Su esquema de entrada requiere exactamente cuatro campos — prompt, image_urls, aspect_ratio y resolution — y resolution solo acepta 2K o 4K (en esta ruta no hay nivel 1K, lo que precisamente significa que no puedes reducir tu imagen por accidente).

import time
import requests

API_KEY = "sk-your-hiapi-key"  # from https://www.hiapi.ai/en/dashboard/api-keys
BASE = "https://api.hiapi.ai/v1/tasks"
HEADERS = {"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"}

def create_upscale_task(source_image_url: str) -> str:
    payload = {
        "model": "seedream-5.0-lite/image-to-image",
        "input": {
            "prompt": "Same image, preserved composition and colors, sharp fine detail, no artifacts",
            "image_urls": [source_image_url],
            "aspect_ratio": "1:1",   # match your source image's ratio
            "resolution": "4K",
        },
    }
    resp = requests.post(BASE, headers=HEADERS, json=payload, timeout=60)
    resp.raise_for_status()
    body = resp.json()
    task_id = body["data"]["taskId"]
    return task_id

def wait_for_result(task_id: str, timeout_s: int = 300, poll_every: int = 5) -> str:
    deadline = time.time() + timeout_s
    while time.time() < deadline:
        resp = requests.get(f"{BASE}/{task_id}", headers=HEADERS, timeout=30)
        resp.raise_for_status()
        task = resp.json()["data"]
        if task["status"] == "success":
            return task["output"][0]["url"]
        if task["status"] == "fail":
            err = task.get("error", {})
            raise RuntimeError(f"task failed: {err.get('code')} {err.get('message')}")
        time.sleep(poll_every)
    raise TimeoutError(f"task {task_id} did not finish in {timeout_s}s")

if __name__ == "__main__":
    task_id = create_upscale_task("https://your-cdn.example.com/product-photo-small.jpg")
    result_url = wait_for_result(task_id)
    print("4K result:", result_url)

Si solo quieres ver cómo es la solicitud, aquí tienes la llamada equivalente para crear la tarea con curl:

curl -s -X POST https://api.hiapi.ai/v1/tasks \
  -H "Authorization: Bearer sk-your-hiapi-key" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "seedream-5.0-lite/image-to-image",
    "input": {
      "prompt": "Same image, preserved composition and colors, sharp fine detail, no artifacts",
      "image_urls": ["https://your-cdn.example.com/product-photo-small.jpg"],
      "aspect_ratio": "1:1",
      "resolution": "4K"
    }
  }'

Hay varios detalles que merece la pena señalar sobre esta solicitud:

  • image_urls es un array, incluso aunque este modelo solo lea el primer elemento. Pasar una cadena simple en lugar de una lista es una causa habitual de errores 400.
  • Las URL de salida caducan. En cuanto wait_for_result() devuelva, descarga los bytes de inmediato y guárdalos por tu cuenta; no uses los enlaces alojados por hiapi como URL permanente de tus recursos.
  • Si tu imagen de origen no es cuadrada, ajusta aspect_ratio para que coincida (4:3, 16:9, 9:16, 3:2, 2:3 o 21:9) para que el modelo no recorte ni rellene tu sujeto.

Cómo hacerlo en producción

En escala, prioriza los callbacks frente al polling. Si vas a ampliar más de unas pocas imágenes, no bombardees con GET /v1/tasks/<id> en bucle por cada tarea: pasa un objeto callback para que hiapi te envíe el resultado:

payload = {
    "model": "seedream-5.0-lite/image-to-image",
    "input": {...},
    "callback": {
        "url": "https://your-service.example.com/hooks/hiapi-task",
        "when": "final",
    },
}

Tu webhook recibirá el mismo objeto de tarea que en el polling (status, output, error). Valida su estructura de forma defensiva, porque los reintentos de red pueden entregarlo más de una vez.

Prepara en tu lado una clave que favorezca la idempotencia por tarea. La API de tareas no acepta actualmente una clave de idempotencia proporcionada por el cliente, así que si tu ejecutor de tareas puede reintentar llamadas HTTP fallidas, comprueba si ya guardaste un taskId para esa imagen de origen antes de enviar una tarea duplicada; de lo contrario, un breve timeout en tu lado puede convertirse en un escalado facturado dos veces para el mismo archivo.

Gestiona dos formas de error completamente distintas. Un cuerpo de solicitud mal formado devuelve HTTP 400 con un {"code": 400, "error_code": "INVALID_REQUEST", "message": "..."} plano. Una clave de API ausente o incorrecta devuelve HTTP 401 con un {"error": {"code": "permission_denied", "message": "..."}} anidado. Comprueba primero el código de estado y luego bifurca según el caso:

if resp.status_code == 401:
    raise RuntimeError(f"auth error: {resp.json()['error']['message']}")
if resp.status_code == 400:
    raise RuntimeError(f"bad request: {resp.json()['message']}")
resp.raise_for_status()

Elige el modelo según la entrada de la que dispongas. Las tres rutas de abajo comparten el mismo endpoint /v1/tasks; solo cambian la cadena model y los campos de input:

Qué tienes Modelo Campos de entrada obligatorios
Una imagen existente y quieres un redibujado limpio a 2K/4K seedream-5.0-lite/image-to-image prompt, image_urls, aspect_ratio, resolution (2K|4K)
Una imagen existente y quieres equilibrar calidad y coste gpt-image-2/image-to-image@ext prompt, image_urls, quality (low|medium|high), resolution (1K|2K|4K)
No tienes imagen de origen: generar un recurso de alta resolución totalmente nuevo a partir de una descripción textual wan2.7-image/text-to-image prompt (además de resolution y aspect_ratio opcionales)

Fíjate en el sufijo @ext de la segunda fila: es una variante de ruta sobre el modelo base gpt-image-2 (hiapi expone algunos modelos bajo más de una ruta con niveles de calidad/precio ligeramente distintos), no una familia de modelos independiente. El coste exacto por solicitud de cada uno depende del nivel de resolución y calidad que elijas, así que consulta las cifras actuales en la página de precios en lugar de codificar valores fijos en tu lógica de presupuesto.

Valida antes de enviar. Los tres modelos rechazan directamente los campos de entrada desconocidos (additional properties 'x' not allowed) en lugar de ignorarlos en silencio, y los campos de enumeración como resolution y aspect_ratio distinguen mayúsculas y son sensibles al valor. Si estás construyendo una capa de envoltura, valida en el cliente con los valores de enumeración exactos indicados arriba, para que las erratas fallen rápido en lugar de consumir una solicitud en vano.

Lecturas relacionadas

Preguntas frecuentes

¿hiapi tiene un modelo dedicado de ampliación o superresolución de imágenes? No hay un modelo dedicado que preserve los píxeles. El flujo de trabajo de arriba usa modelos genéricos de imagen a imagen para regenerar tu imagen en un nivel de resolución superior, lo que funciona bien con fotografías e ilustraciones, pero no es una ampliación sin pérdidas.

¿Puedo mejorar la resolución sin cambiar el contenido de la imagen? Puedes acercarte mucho pidiendo al modelo que preserve exactamente la composición, los colores y el sujeto («la misma imagen, no cambies la composición, no añadas ni quites elementos, solo añade detalle y nitidez»), pero como se trata de un redibujado generativo y no de una interpolación, en texturas finas seguirá habiendo diferencias sutiles frente a un ampliador realmente sin pérdidas.

¿Cuál es la máxima resolución que puedo generar? Los tres modelos de arriba tienen como límite el nivel de resolución 4K. Si necesitas un tamaño mayor, tendrás que dividir la imagen de origen en bloques, ampliar cada bloque por separado o añadir un paso de escalado en el cliente después de la llamada a la API.

¿Hace falta una clave de API para probar esto? Sí: cada llamada a /v1/tasks requiere Authorization: Bearer sk-<your-key>. No hay un sandbox sin clave para crear tareas; obtén primero una clave desde el panel.

¿Puedo ampliar por lotes una carpeta entera de imágenes? Sí: recorre las URL de tus imágenes, envía una tarea por imagen y luego consulta cada taskId o, mejor cuando el volumen es alto, registra una URL de callback que asocie los resultados a tu tarea mediante el taskId guardado al crear cada tarea.

¿Por qué falla mi solicitud con «additional properties not allowed»? Has enviado un campo que el esquema del modelo no reconoce, por ejemplo size en lugar de resolution + aspect_ratio, o un parámetro sobrante copiado de un ejemplo de otro modelo. Consulta la tabla de campos obligatorios de arriba para conocer los nombres exactos que acepta cada modelo.

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