HiAPI
Blog

Tutorial

Cómo usar ideogram-v4 a través de la API de hiapi: curl, Python y una solicitud que funciona

Jul 7, 2026
Cómo usar ideogram-v4 a través de la API de hiapi: curl, Python y una solicitud que funciona

La reputación de los modelos Ideogram se basa en algo que la mayoría de los modelos de imagen todavía no logran resolver: la tipografía. El titular de un póster se escribe correctamente, las letras de un logotipo quedan limpias y el texto de un letrero no se convierte en un amasijo de garabatos. ideogram-v4, como todos los demás modelos de imagen y vídeo, está disponible en hiapi a través de la misma API de tareas unificada, y esta guía recorre la solicitud de principio a fin: una versión curl lista para copiar y pegar, un script completo de Python, los parámetros que el esquema realmente valida (que no son los mismos que expone la API nativa de Ideogram) y los errores que encontrarás en la práctica.

Qué vas a construir y qué necesitas

Objetivo: enviar un prompt de texto a POST /v1/tasks, esperar a que la tarea termine y descargar una imagen cuyo texto se renderice tal como lo pediste.

Solo necesitas una cosa: una clave de API de hiapi, que se crea en la consola. Se usa como Bearer token en cada solicitud. No hay un nivel gratuito sin autenticación; todas las llamadas siguientes asumen Authorization: Bearer sk-....

Como todos los modelos de hiapi, ideogram-v4 es asíncrono: creas una tarea, obtienes un taskId de inmediato y luego consultas el resultado por polling o recibes una devolución de llamada. No existe un modo síncrono de «esperar 40 segundos en una única conexión HTTP», y para la generación de imágenes tampoco lo querrías.

Solicitud mínima: curl

Crear la tarea:

curl -X POST https://api.hiapi.ai/v1/tasks \
  -H "Authorization: Bearer $HIAPI_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "ideogram-v4",
    "input": {
      "prompt": "Un póster de festival de jazz con estilo art déco vintage. El texto del titular \"MIDNIGHT & BRASS\" en una tipografía dorada y gruesa sobre un fondo azul marino profundo, con el subtítulo \"Live at the Riverside, Fridays\" debajo en una tipografía sans serif fina.",
      "rendering_speed": "BALANCED",
      "aspect_ratio": "3:4"
    }
  }'

La respuesta llega de inmediato y el id de la tarea está en data.taskId (con la forma tk-hiapi-...). Consúltalo:

curl https://api.hiapi.ai/v1/tasks/tk-hiapi-XXXXXXXX \
  -H "Authorization: Bearer $HIAPI_KEY"

Durante la generación de la imagen, data.status pasa por queued y handling. Al llegar a un estado terminal se convierte en success o fail. Si tiene éxito, la URL de la imagen está en data.output[0].url:

{
  "code": 200,
  "data": {
    "taskId": "tk-hiapi-XXXXXXXX",
    "status": "success",
    "output": [
      { "url": "https://.../result.png?...expireAt=..." }
    ]
  }
}

Hay algo que tener en cuenta sobre esta URL: es firmada y caduca (expireAt). Descarga los bytes en cuanto la tarea tenga éxito y guárdalos en tu propio almacenamiento. Nunca guardes enlaces directos en una base de datos.

Los parámetros que ideogram-v4 acepta realmente

Esta es la parte que conviene tratar con precisión. Si has leído la documentación propia de Ideogram, sabrás que su API nativa expone ajustes predefinidos de estilo, interruptores de prompt mágico, prompts negativos y cantidad por lotes. El esquema de tarea de ideogram-v4 en hiapi es deliberadamente más pequeño, y el validador rechaza cualquier cosa fuera del esquema. Este es el conjunto completo confirmado contra la API en vivo:

Campo Obligatorio Tipo / valores
prompt Sí string
rendering_speed Sí "TURBO", "BALANCED", "QUALITY"
aspect_ratio No "1:1", "16:9", "4:3", "9:16", "3:4"
seed No entero

Los dos campos obligatorios se validan de forma estricta. Enviar un input vacío devuelve:

invalid input: prompt: missing required field "prompt";
rendering_speed: missing required field "rendering_speed"

Si escribes mal un valor de enumeración, el error te indica los valores válidos:

invalid input: rendering_speed: value must be one of 'TURBO', 'BALANCED', 'QUALITY'

Y cualquier cosa de la interfaz nativa de Ideogram que no esté en la tabla anterior se rechaza como propiedad desconocida: style_type, magic_prompt, negative_prompt, num_images, size y las entradas de imagen devuelven 400, por ejemplo:

invalid input: <root>: additional properties 'style_type' not allowed

Consecuencias prácticas:

  • El control tipográfico depende por completo del prompt. Incluye entre comillas dobles dentro del prompt el texto exacto que quieres renderizar y describe la tipografía («tipografía art déco en negrita», «sans serif geométrica fina», «letras de rótulo dibujadas a mano»). Así se consiguen los efectos de póster/logotipo/rótulo por los que Ideogram es conocido; no hay un parámetro de estilo independiente en el que apoyarse.
  • Una imagen por tarea. No hay n ni num_images. Si quieres cuatro candidatas, envía cuatro tareas y consulta cada taskId por separado.
  • seed es tu palanca de reproducibilidad. El mismo prompt + la misma seed te dan un punto de partida estable para iterar sobre la redacción.
  • Solo texto a imagen. El esquema de este modelo no acepta imágenes de referencia. Si tu flujo de trabajo necesita imagen a imagen, elige un modelo que lo admita; consulta cómo llamar a varios modelos de imagen con una sola clave de API para cambiar de modelo sin tocar el código de integración.

Sobre rendering_speed: TURBO es el nivel rápido, útil para hacer borradores mientras iteras la redacción del prompt; QUALITY es el nivel lento y refinado, para el renderizado final; BALANCED es un valor predeterminado razonable. El precio se cobra por uso, por imagen; consulta los precios actuales en la página de precios.

El script completo de Python

El mismo flujo —crear, consultar, descargar— con tiempo de espera y manejo de estados terminales. La única dependencia es requests (pip install requests).

import os
import time
import requests

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

def create_task(prompt: str, rendering_speed: str = "BALANCED",
                aspect_ratio: str = "1:1", seed: int | None = None) -> str:
    input_obj = {
        "prompt": prompt,
        "rendering_speed": rendering_speed,
        "aspect_ratio": aspect_ratio,
    }
    if seed is not None:
        input_obj["seed"] = seed
    resp = requests.post(API_BASE, headers=HEADERS,
                         json={"model": "ideogram-v4", "input": input_obj},
                         timeout=60)
    data = resp.json()
    task_id = (data.get("data") or {}).get("taskId")
    if not task_id:
        raise RuntimeError(f"create failed: HTTP {resp.status_code} {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:
        resp = requests.get(f"{API_BASE}/{task_id}", headers=HEADERS, timeout=30)
        task = resp.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} not done after {timeout_s}s")

if __name__ == "__main__":
    task_id = create_task(
        prompt=('Diseña un logotipo minimalista para una marca de café llamada "Driftwood", '
                'con la palabra Driftwood como logotipo tipográfico en una serif cálida, monocromático, '
                'sobre un fondo color crema'),
        rendering_speed="QUALITY",
        aspect_ratio="1:1",
        seed=42,
    )
    print("task:", task_id)
    task = wait_task(task_id)
    url = task["output"][0]["url"]
    png = requests.get(url, timeout=120).content   # la URL firmada caduca: descarga de inmediato
    with open("driftwood-logo.png", "wb") as f:
        f.write(png)
    print("saved driftwood-logo.png,", len(png), "bytes")

Consideraciones para producción: devoluciones de llamada, idempotencia y errores

Polling vs. devoluciones de llamada. Para una herramienta interactiva que genera una imagen a la vez, consultar cada pocos segundos es más sencillo y perfectamente suficiente. Para cargas de trabajo por lotes o del lado del servidor, añade una devolución de llamada a la solicitud de creación para que hiapi te envíe por POST el resultado del estado terminal:

{
  "model": "ideogram-v4",
  "input": { "prompt": "...", "rendering_speed": "BALANCED" },
  "callback": { "url": "https://your.domain.example/hiapi/hook", "when": "final" }
}

Hay dos restricciones, ambas aplicadas en el momento de la creación: la URL debe ser https:// y accesible desde la red pública, y when solo acepta "final"; si pruebas otro valor, la API devuelve directamente invalid callback.when: only 'final' is supported. Haz que tu manejador sea idempotente respecto a taskId, responde rápido con 2xx y mantén un mecanismo de polling de respaldo para las tareas cuyas devoluciones de llamada nunca lleguen. Si la devolución de llamada no llega, primero diagnostica siguiendo por qué no se dispara la devolución de llamada de tu tarea de hiapi antes de culpar a la cola.

Idempotencia. Crear una tarea no es idempotente: cada POST /v1/tasks exitoso es una tarea nueva y un cobro nuevo. En cuanto recibas el taskId, guárdalo asociado a tu propio id de tarea; cualquier reintento posterior debe consultar el taskId almacenado en lugar de volver a enviar la solicitud.

Los errores que verás realmente.

  • 401 con "code": "permission_denied": la clave no es válida o no puede usar ese modelo. El mensaje lo indica claramente: «This API key cannot use the selected model. Please check permissions or use another key.» Corrígelo en la consola, no lo reintentes.
  • 400 con "error_code": "INVALID_REQUEST": fallo de validación. El message señala el campo concreto y los valores válidos; léelo y corrige el cuerpo de la solicitud. Reintentar con el mismo cuerpo fallará siempre.
  • 404 "task not found" en GET /v1/tasks/{id}: el id de tarea es incorrecto o la tarea se creó con otra clave.
  • Estado fail en una tarea que ya había sido aceptada: revisa data.error.code / data.error.message en la respuesta de consulta. Es seguro reintentar estos como una tarea nueva.

Lecturas relacionadas

Preguntas frecuentes

¿ideogram-v4 en hiapi admite imagen a imagen o imágenes de referencia? No. El esquema de tareas de este modelo solo acepta prompt, rendering_speed, aspect_ratio y seed; cualquier campo de entrada de imagen se rechaza con un 400. Si necesitas editar o repintar una imagen existente, usa un modelo que admita imagen a imagen (por ejemplo, la familia gpt-image-2).

¿Qué rendering_speed debería usar? Mientras optimizas el prompt y la redacción exacta del texto, itera con TURBO; después vuelve a renderizar la versión ganadora con QUALITY y la misma seed. Si solo vas a renderizar una vez, BALANCED es un buen valor predeterminado.

¿Cómo consigo que ideogram-v4 renderice el texto exacto? Pon el texto literal entre comillas dobles dentro del prompt y describe la tipografía alrededor: texto del titular "SUMMER SALE", en una sans serif condensada y pesada. Las cadenas cortas se renderizan de forma más fiable que las frases completas; si una línea larga sale desordenada, divídela en titular y subtítulo.

¿Se pueden generar varias imágenes en una sola solicitud? No: una tarea genera una imagen. Envía varias tareas en paralelo; cada una tiene su propio taskId y se encola de forma independiente.

¿Por qué mi clave funciona con otros modelos pero recibo 401 permission_denied? El acceso a los modelos se configura por clave. Revisa los permisos de modelo de esa clave en la consola o crea una clave nueva con acceso a ideogram-v4.

¿Cuánto tiempo es válida la URL de salida? Es una URL firmada con una marca de tiempo expireAt. Trátala como algo que dura minutos, no días: descarga la imagen en cuanto la tarea llegue a success y guarda el archivo por tu cuenta.

¿Qué relaciones de aspecto hay disponibles? Exactamente cinco: 1:1, 16:9, 4:3, 9:16 y 3:4. No hay un parámetro size de formato libre; las solicitudes con size se rechazan como propiedad desconocida.

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