HiAPI
Blogue

Tutorial

Como usar o ideogram-v4 pela API hiapi: curl, Python e uma requisição que funciona

Jul 7, 2026
Como usar o ideogram-v4 pela API hiapi: curl, Python e uma requisição que funciona

A reputação dos modelos Ideogram se construiu sobre uma coisa que a maioria dos modelos de imagem ainda não consegue fazer: tipografia. Os títulos dos pôsteres saem com a grafia correta, as letras dos logotipos ficam limpas e o texto das placas não vira um borrão ilegível. O ideogram-v4, como todos os outros modelos de imagem e vídeo, está disponível no hiapi pela mesma API unificada de tarefas, e este guia percorre a requisição completa: a versão curl pronta para copiar e colar, o script Python completo, os parâmetros que o schema de fato valida (que não são os mesmos que a API nativa do Ideogram expõe) e os erros que você vai encontrar na prática.

O que você vai construir e o que precisa preparar

Objetivo: enviar um prompt de texto para POST /v1/tasks, aguardar a conclusão da tarefa e então baixar uma imagem com o texto renderizado exatamente como você pediu.

Você precisa de apenas uma coisa: uma chave de API do hiapi — crie uma no console. Ela é usada como Bearer token em cada requisição. Não há nível gratuito sem autenticação; todas as chamadas abaixo pressupõem Authorization: Bearer sk-....

Como todos os modelos no hiapi, o ideogram-v4 é assíncrono: você cria uma tarefa, recebe imediatamente um taskId e depois faz polling do resultado ou recebe um callback. Não existe um modo síncrono de "esperar 40 segundos em uma única conexão HTTP" — e, para geração de imagens, você não iria querer isso mesmo.

Requisição mínima: curl

Criar a tarefa:

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": "Um pôster de festival de jazz em estilo art déco retrô. O texto do título principal \"MIDNIGHT & BRASS\" em fonte dourada em negrito sobre fundo azul-marinho profundo, com o subtítulo \"Live at the Riverside, Fridays\" abaixo em uma fonte sans-serif fina.",
      "rendering_speed": "BALANCED",
      "aspect_ratio": "3:4"
    }
  }'

A resposta retorna imediatamente, com o id da tarefa em data.taskId (no formato tk-hiapi-...). Faça polling dele:

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

Durante a geração da imagem, data.status passa por queued e handling. Ao chegar ao estado terminal, ele vira success ou fail. Em caso de sucesso, a URL da imagem fica em data.output[0].url:

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

Um detalhe importante sobre essa URL: ela é assinada e expira (expireAt). Baixe os bytes imediatamente após a tarefa ter sucesso e salve no seu próprio armazenamento. Nunca guarde hotlinks no banco de dados.

Os parâmetros que o ideogram-v4 realmente aceita

Esta é a parte que merece precisão. Se você leu a documentação do próprio Ideogram, sabe que a API nativa dele expõe presets de estilo, chave de magic prompt, negative prompt e quantidade em lote. O schema de tarefa do ideogram-v4 no hiapi é deliberadamente menor, e o validador rejeita qualquer coisa fora do schema. A seguir está a lista completa, confirmada na API em tempo real:

Campo Obrigatório Tipo / valores
prompt Sim string
rendering_speed Sim "TURBO", "BALANCED", "QUALITY"
aspect_ratio Não "1:1", "16:9", "4:3", "9:16", "3:4"
seed Não inteiro

Os dois campos obrigatórios são validados de forma estrita. Enviar um input vazio retorna:

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

Se você errar a grafia de um valor de enum, o erro informa os valores válidos:

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

E qualquer coisa da interface nativa do Ideogram que não esteja na tabela acima será rejeitada como propriedade desconhecida — style_type, magic_prompt, negative_prompt, num_images, size e entradas de imagem retornam 400, por exemplo:

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

Implicações práticas:

  • O controle de tipografia depende inteiramente do prompt. Coloque o texto exato que você quer renderizar entre aspas duplas no prompt e descreva a fonte ("fonte art déco em negrito", "sans-serif geométrica fina", "letreiro pintado à mão"). É assim que se obtêm os efeitos de pôster/logotipo/placa pelos quais o Ideogram é famoso — não há um parâmetro separado de estilo para usar.
  • Uma imagem por tarefa. Não existe n nem num_images. Se você quiser quatro candidatos, envie quatro tarefas e faça polling de cada taskId separadamente.
  • seed é o seu botão de reprodutibilidade. O mesmo prompt + o mesmo seed dão a você um ponto de partida estável, útil para iterar no texto do prompt.
  • Somente texto para imagem. O schema do modelo não aceita imagens de referência. Se seu fluxo de trabalho precisa de imagem para imagem, escolha um modelo que suporte isso — veja como chamar vários modelos de imagem com uma única chave de API para trocar de modelo sem mudar o código de integração.

Sobre rendering_speed: TURBO é o nível rápido, bom para rascunhar enquanto você itera no texto do prompt; QUALITY é o nível lento e refinado, para a renderização final; BALANCED é um padrão razoável. A cobrança é por uso, por imagem — consulte a página de preços para os valores atuais.

O script Python completo

O mesmo fluxo — criar, fazer polling, baixar — com timeout e tratamento de estado terminal. A única dependência é 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=('Crie um logotipo minimalista para uma marca de café chamada "Driftwood", '
                'com a palavra Driftwood como letreiro em fonte serifada acolhedora, monocromático, '
                'sobre fundo creme'),
        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   # a URL assinada expira - baixe imediatamente
    with open("driftwood-logo.png", "wb") as f:
        f.write(png)
    print("saved driftwood-logo.png,", len(png), "bytes")

Considerações para produção: callbacks, idempotência e erros

Polling vs. callback. Para ferramentas interativas que geram uma imagem por vez, o polling a cada poucos segundos é mais simples e perfeitamente suficiente. Para cargas de trabalho em lote ou no servidor, adicione um callback à requisição de criação para que o hiapi faça POST do resultado terminal para você:

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

Há duas restrições, ambas aplicadas no momento da criação: a URL precisa ser https:// e acessível publicamente, e when só aceita "final" — se você tentar outro valor, a API retorna diretamente invalid callback.when: only 'final' is supported. Faça seu handler ser idempotente em relação ao taskId, retorne 2xx rapidamente e mantenha um polling de fallback para tarefas cujo callback nunca chegue. Se o callback não chegar, primeiro investigue seguindo por que o callback da sua tarefa hiapi não dispara antes de culpar a fila.

Idempotência. A criação de tarefas não é idempotente — cada POST /v1/tasks bem-sucedido é uma nova tarefa e uma nova cobrança. Assim que receber o taskId, armazene-o imediatamente associado ao seu próprio id de tarefa; qualquer nova tentativa depois disso deve fazer polling do taskId armazenado em vez de reenviar.

Erros que você realmente vai ver.

  • 401 com "code": "permission_denied" — chave inválida ou sem acesso a esse modelo. A mensagem é explícita: "This API key cannot use the selected model. Please check permissions or use another key." Corrija no console, não tente de novo.
  • 400 com "error_code": "INVALID_REQUEST" — falha de validação. O message indica o campo específico e os valores válidos; leia e corrija o corpo da requisição. Repetir com o mesmo corpo vai falhar para sempre.
  • 404 "task not found" em GET /v1/tasks/{id} — id de tarefa errado, ou a tarefa foi criada com outra chave.
  • Status fail em uma tarefa que já havia sido aceita — verifique data.error.code / data.error.message na resposta de polling. Esses erros podem ser repetidos com segurança como uma nova tarefa.

Leitura relacionada

Perguntas frequentes

O ideogram-v4 no hiapi suporta imagem para imagem ou imagens de referência? Não. O schema de tarefa desse modelo aceita apenas prompt, rendering_speed, aspect_ratio e seed — qualquer campo de entrada de imagem é rejeitado com 400. Se você precisa editar ou repintar uma imagem existente, use um modelo que suporte imagem para imagem (por exemplo, a série gpt-image-2).

Qual rendering_speed devo usar? Use TURBO para iterar enquanto você ajusta o prompt e o texto exato, depois renderize de novo a versão vencedora com QUALITY e o mesmo seed. Se você só vai renderizar uma vez, BALANCED é um bom padrão.

Como faço o ideogram-v4 renderizar o texto exato? Coloque o texto literal entre aspas duplas no prompt e descreva a tipografia ao redor: texto do título principal "SUMMER SALE", em sans-serif condensada e pesada. Strings mais curtas renderizam de forma mais confiável do que frases completas; se uma linha longa sair embaralhada, divida-a em título e subtítulo.

É possível gerar várias imagens em uma única requisição? Não — uma tarefa gera uma imagem. Em vez disso, envie várias tarefas em paralelo; cada tarefa tem seu próprio taskId e entra na fila de forma independente.

Por que minha chave funciona para outros modelos, mas recebo 401 permission_denied? O acesso aos modelos é configurado por chave. Verifique as permissões de modelo dessa chave no console ou crie uma nova chave com acesso ao ideogram-v4.

Quanto tempo a URL de saída fica válida? Ela é uma URL assinada com um timestamp expireAt. Trate-a como algo em escala de minutos, não de dias: baixe a imagem assim que a tarefa chegar a success e salve o arquivo você mesmo.

Quais proporções de tela estão disponíveis? Exatamente cinco: 1:1, 16:9, 4:3, 9:16 e 3:4. Não há parâmetro size de formato livre — uma requisição com size é rejeitada como propriedade desconhecida.

Artigos relacionados

Ver todos os artigos →

Comece a criar com artefactos de IA persistentes

Obtenha a sua chave de API e chame modelos de imagem, vídeo e áudio através de uma única API baseada em tasks.

Ler a documentação da API