HiAPI
Blog

Tutorial

Cómo usar el modo imagen a imagen de gpt-image-2 a través de la API de hiapi

Una receta de código lista para ejecutar que te enseña cómo llamar al endpoint de imagen a imagen de gpt-image-2 en hiapi: el sobre de la petición, los parámetros de imagen de referencia y aspect_ratio, la disyuntiva entre sondeo y callback, y ejemplos de curl, Python y Node.js listos para copiar y pegar.

Jun 26, 2026
Cómo usar el modo imagen a imagen de gpt-image-2 a través de la API de hiapi

Esta receta te mostrará paso a paso cómo llamar al modo imagen a imagen de gpt-image-2 mediante la API de tareas unificada de hiapi. Obtendrás un ejemplo de curl listo para ejecutar, un script de Python que puedes incrustar directamente en tu backend, una versión de Node.js para escenarios sin servidor, y los parámetros que realmente importan junto con los detalles que suelen causar problemas en producción.

Al terminar de leer este artículo, tendrás un script que recibe una URL de imagen de referencia y un prompt, y devuelve una URL de imagen generada que puedes descargar directamente o pasar a tu capa de almacenamiento.

Preparación

  • Una cuenta de hiapi y una clave de API. Puedes obtenerlas en la consola de hiapi.
  • Una imagen de referencia alojada en una URL HTTPS pública (o una URL de datos base64 — ambas funcionan).
  • Un prompt de texto que describa lo que quieres que el modelo haga con esa imagen de referencia.

Eso es todo. No necesitas instalar ningún SDK — hiapi es HTTP + JSON, así que cualquier lenguaje que pueda enviar una petición POST sirve.

¿Quieres conocer primero la generación de imágenes solo a partir de texto? Consulta Cómo generar imágenes con la API de hiapi. El patrón que sigue es el mismo flujo de tareas asíncrono, solo que con un campo image adicional.

Llamada mínima funcional

hiapi expone todos los modelos de imagen a través de la misma interfaz de tareas asíncrona:

  1. POST /v1/tasks — envía la tarea y devuelve un taskId.
  2. O bien sondea GET /v1/tasks/{taskId} hasta que status === "success", o bien proporciona callback.url para recibir el resultado final mediante webhook.
  3. Lee la URL de la imagen desde data.output[0].url y descárgala o guárdala.

curl

curl -X POST https://api.hiapi.ai/v1/tasks \
  -H "Authorization: Bearer sk-YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-image-2/image-to-image",
    "input": {
      "prompt": "transform the subject into a watercolor painting, soft pastel palette",
      "image": "https://example.com/reference.jpg",
      "aspect_ratio": "1:1",
      "resolution": "1K"
    }
  }'

La respuesta inmediata te da el id de la tarea:

{ "data": { "taskId": "task_01HXXXX..." } }

Luego sondea el resultado:

curl https://api.hiapi.ai/v1/tasks/task_01HXXXX... \
  -H "Authorization: Bearer sk-YOUR_KEY"

Cuando la tarea está lista, la respuesta es así:

{
  "data": {
    "status": "success",
    "output": [{ "url": "https://cdn.hiapi.ai/...png", "expireAt": "..." }]
  }
}

output[0].url tiene una validez temporal corta (fíjate en expireAt), así que descárgala de inmediato o vuelve a subirla a tu propio almacenamiento — nunca enlaces directamente a ella para tus usuarios finales.

Los parámetros que realmente importan

Campo Tipo Descripción
model string Usa el id sin prefijo gpt-image-2/image-to-image. No añadas el prefijo models/.
input.prompt string La transformación que deseas aplicar a la imagen de referencia.
input.image string Una URL HTTPS o una URL data:image/...;base64,....
input.aspect_ratio string Uno de estos valores: 1:1, 3:2, 2:3, 4:3, 3:4, 5:4, 4:5, 16:9, 9:16, 21:9 o auto.
input.resolution string 1K, 2K o 4K. Por defecto 1K.

Dos comportamientos importantes:

  • Algunos modelos de hiapi solo aceptan aspect_ratio (sin resolution); otros modelos requieren dimensiones en píxeles. gpt-image-2/image-to-image acepta la combinación de aspect_ratio + resolution mostrada arriba — no pases aquí size: "1024x1024".
  • El campo image es la imagen de referencia. Si pasas una URL de datos base64, asegúrate de que el payload esté por debajo del límite de tamaño del cuerpo de la petición de tu plataforma (unos pocos MB están bien; las imágenes de varios megabytes deberían subirse primero y pasarse como URL).

Script de Python de nivel producción

Esta versión sondea con manejo de fecha límite y sale limpiamente en caso de fallo:

import os
import time
import requests

API = "https://api.hiapi.ai/v1/tasks"
TOKEN = os.environ["HIAPI_API_KEY"]
HEADERS = {"Authorization": f"Bearer {TOKEN}", "Content-Type": "application/json"}


def submit(prompt: str, image_url: str, aspect_ratio: str = "1:1") -> str:
    payload = {
        "model": "gpt-image-2/image-to-image",
        "input": {
            "prompt": prompt,
            "image": image_url,
            "aspect_ratio": aspect_ratio,
            "resolution": "1K",
        },
    }
    r = requests.post(API, headers=HEADERS, json=payload, timeout=30)
    r.raise_for_status()
    return r.json()["data"]["taskId"]


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


if __name__ == "__main__":
    task_id = submit(
        prompt="transform the subject into a watercolor painting, soft pastel palette",
        image_url="https://example.com/reference.jpg",
    )
    print("task:", task_id)
    print("url:", wait(task_id))

Ejecútalo con HIAPI_API_KEY=sk-... python recipe.py.

Node.js (fetch, sin dependencias)

const API = "https://api.hiapi.ai/v1/tasks";
const TOKEN = process.env.HIAPI_API_KEY;
const headers = {
  Authorization: `Bearer ${TOKEN}`,
  "Content-Type": "application/json",
};

async function submit(prompt, imageUrl, aspectRatio = "1:1") {
  const r = await fetch(API, {
    method: "POST",
    headers,
    body: JSON.stringify({
      model: "gpt-image-2/image-to-image",
      input: { prompt, image: imageUrl, aspect_ratio: aspectRatio, resolution: "1K" },
    }),
  });
  const data = await r.json();
  if (!r.ok) throw new Error(JSON.stringify(data));
  return data.data.taskId;
}

async function wait(taskId, timeoutMs = 300000, intervalMs = 5000) {
  const deadline = Date.now() + timeoutMs;
  while (Date.now() < deadline) {
    const r = await fetch(`${API}/${taskId}`, { headers });
    const task = (await r.json()).data;
    if (task.status === "success") return task.output[0].url;
    if (task.status === "fail") throw new Error(JSON.stringify(task.error));
    await new Promise((res) => setTimeout(res, intervalMs));
  }
  throw new Error(`task ${taskId} timed out`);
}

(async () => {
  const id = await submit(
    "transform the subject into a watercolor painting, soft pastel palette",
    "https://example.com/reference.jpg",
  );
  console.log("task:", id, "\nurl:", await wait(id));
})();

Sondeo vs. callback

Sondear cada 5 segundos está bien para un script puntual, pero mantiene ocupado a un worker durante toda la tarea. En un backend real, normalmente querrás un webhook:

{
  "model": "gpt-image-2/image-to-image",
  "input": { "prompt": "...", "image": "https://example.com/reference.jpg" },
  "callback": { "url": "https://your-app.example.com/api/hiapi-callback", "when": "final" }
}

Cuando la tarea se liquida (con éxito o con fallo), hiapi hará POST a esa URL con el mismo payload que obtendrías de GET /v1/tasks/{id}. Trata ese manejador como idempotente — los reintentos son posibles — y verifícalo antes de confiar en la petición (incluye tu propio token de firma en la URL, comprueba la cabecera Authorization, etc.).

Un patrón limpio es: enviar la tarea, persistir el taskId con tu propio job id como clave, devolver 202 Accepted al llamador y dejar que el webhook haga el trabajo de almacenamiento y notificación.

Manejo de errores

En la práctica te encontrarás con tres modos de fallo:

  1. 401 permission_denied con "This API key cannot use the selected model." — la clave no está autorizada para usar gpt-image-2/image-to-image. Compruébalo en la consola de hiapi y confirma en la página de precios que el modelo está incluido en tu plan.
  2. 400 con additional properties not allowed — enviaste un campo que ese modelo concreto no acepta (por ejemplo, size en lugar de aspect_ratio). El mensaje de error indicará el nombre de la clave infractora; elimínala y reinténtalo.
  3. status: "fail" durante el sondeo con un objeto data.error — el modelo mismo rechazó la entrada (contenido no seguro, URL de referencia inaccesible, etc.). Registra error.code y error.message en los logs y no reintentes automáticamente a ciegas.

Establece siempre un tiempo de espera para las llamadas a POST /v1/tasks (30 segundos es suficiente — devuelve el taskId rápidamente) y un tiempo de espera independiente y más largo para el bucle de sondeo o la ruta de recepción del webhook.

Enlaces relacionados

Preguntas frecuentes

P: ¿gpt-image-2/image-to-image admite varias imágenes de referencia? R: El contrato mínimo usa un único campo image. Si tu caso de uso requiere varias imágenes de referencia (por ejemplo, una imagen del sujeto + una imagen de estilo), combínalas primero en una sola, o consulta la página del modelo para conocer los campos más recientes admitidos.

P: ¿Puedo pasar un archivo local en lugar de una URL? R: Sí — codifícalo como una URL data:image/png;base64,... y pásalo como input.image. Para archivos de más de unos 3 MB, súbelo primero a tu propio almacenamiento y pasa una URL pública; así es más rápido y evitas los límites del cuerpo de la petición.

P: ¿Cuánto tarda una tarea? R: La mayoría de las tareas de imagen a imagen de gpt-image-2 se completan en 10–30 segundos con resolución 1K. Resoluciones más altas y prompts complejos pueden tardar más — para ir sobre seguro, establece el tiempo de espera del sondeo en 5 minutos.

P: ¿Cómo puedo controlar cuánto difiere la salida de la imagen de referencia? R: Exprésalo claramente en el prompt. "Keep the subject's pose and composition, only restyle to watercolor" produce una consistencia más estricta que "make this a watercolor". El modo imagen a imagen de gpt-image-2 está dirigido por el prompt — no hay un control deslizante de "strength" independiente en el sobre de la petición.

P: ¿output[0].url es permanente? R: No. Lleva una marca de tiempo expireAt (normalmente unas pocas horas). En cuanto la tarea tenga éxito, descarga los bytes lo antes posible y súbelos a tu propio almacenamiento (R2, S3, etc.).

P: ¿Cuánto cuesta cada imagen? R: Depende de tu plan y de la resolución. Consulta el coste actual por llamada en la página de precios.

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