Tutorial
Como usar ideogram-v4.5 via API HiAPI: curl, Python e uma requisição que funciona
O que o ideogram-v4.5 na HiAPI traz para você
Quando o texto na imagem realmente importa, o ideogram-v4.5 é o modelo que você deve escolher. Layouts de pôster, marcas gráficas, mockups de embalagem, cards para redes sociais — qualquer cenário em que um título com erro de ortografia ou uma legenda borrada arruína o material é exatamente onde este modelo agrega valor. Se você vai gerar texturas abstratas ou paisagens fotográficas, nas quais nada precisa estar legível, os modelos de imagem genéricos costumam ser mais baratos e mais rápidos.
Este artigo é um guia de integração, não uma avaliação do modelo. Ao final você terá uma requisição funcional, um cliente Python que faz o mesmo, e uma função auxiliar reutilizável que cobre a parte em que as pessoas costumam errar: o parâmetro de proporção, a consulta (polling) de tarefas assíncronas e a obtenção da saída.
Um ponto que precisa ser internalizado desde cedo: a geração de imagens na HiAPI é uma API de tarefas assíncronas. Você envia a requisição, recebe um identificador e então consulta até a tarefa concluir. Código que assume que a imagem já vem no corpo da resposta não funciona. Cada seção abaixo converge para esse padrão.
Antes de enviar a requisição
Antes da primeira chamada, é preciso ter quatro coisas prontas.
1. Chave de API
Crie uma no console da sua conta HiAPI e mantenha-a longe do controle de versão. Exporte-a como variável de ambiente em vez de colá-la no script:
export HIAPI_API_KEY="your_key_here"
2. URL base
Todas as requisições vão para a URL base da API HiAPI, acrescida do caminho específico do endpoint de geração. A documentação da plataforma lista o caminho atual; se a documentação disser algo diferente, não codifique o caminho que você viu em posts de blog (incluindo este).
3. Identificador do modelo
A string de modelo que você envia no corpo da requisição identifica o ideogram-v4.5. Use a capitalização exata exibida na lista de modelos da plataforma — identificadores de modelo são correspondidos literalmente, e o menor desvio retorna um erro de validação em vez de uma sugestão útil.
4. Referência de parâmetros
A página do modelo ideogram-v4.5 é a fonte autoritativa de quais campos o corpo da requisição aceita: limite de comprimento do prompt, proporções suportadas, formato de saída e qualquer controle de seed ou estilo. Leia antes de escrever código. Parâmetros não listados ali podem ser silenciosamente ignorados ou rejeitados, e adivinhar valores é a forma mais comum de desperdiçar tempo com depuração.
Com essas quatro coisas, você já pode enviar a primeira requisição.
Uma requisição curl que funciona
Abaixo, um exemplo mínimo de envio. Se sua conta exibir valores diferentes, substitua o caminho do endpoint e o identificador do modelo pelos da documentação da plataforma.
curl -X POST "$HIAPI_BASE_URL/<generation-path>" \
-H "Authorization: Bearer $HIAPI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "ideogram-v4.5",
"input": {
"prompt": "A vintage travel poster for the Amalfi Coast, bold serif headline reading \"AMALFI\", warm sunset palette, grainy print texture"
}
}'
O que cada parte faz:
Authorization— autenticação por bearer token. Cabeçalho ausente ou mal formatado é a causa mais comum de 401.Content-Type— deve serapplication/json. Alguns clientes HTTP não o definem automaticamente em POST, gerando erros de parsing confusos no servidor.model— o identificador literal do modelo. Coloque-o no nível superior do corpo, conforme a documentação.input.prompt— sua instrução de geração. Como mostrado acima, coloque entre aspas o texto que você quer renderizado na imagem, para que o modelo o trate como texto literal em vez de descrição.input.*— todos os demais parâmetros de geração (proporção, formato, seed etc.) pertencem a este objeto aninhado, ao lado deprompt.
Um envio bem-sucedido retorna um objeto JSON contendo o identificador da tarefa e um campo de status. Não há imagem nessa resposta — isso é o comportamento esperado. Guarde o identificador; a etapa de consulta vai usá-lo.
A mesma chamada em Python
A versão Python é uma tradução um para um. Usamos requests e compartilhamos o mesmo corpo de requisição, para que você possa compará-los lado a lado.
import os
import json
import requests
API_KEY = os.environ["HIAPI_API_KEY"]
BASE_URL = os.environ["HIAPI_BASE_URL"]
GEN_PATH = "/<generation-path>" # confirm in platform docs
payload = {
"model": "ideogram-v4.5",
"input": {
"prompt": (
"A vintage travel poster for the Amalfi Coast, bold serif "
'headline reading "AMALFI", warm sunset palette, grainy print texture'
)
},
}
response = requests.post(
BASE_URL + GEN_PATH,
headers={
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json",
},
data=json.dumps(payload),
timeout=30,
)
response.raise_for_status()
job = response.json()
print(job)
Duas escolhas intencionais:
json.dumpsem vez dejson=mantém o formato de transporte visivelmente consistente com o exemplo curl. Ambos funcionam; a forma explícita facilita inspecionar o que você realmente envia durante a depuração.timeout=30apenas no envio. O envio é rápido; a geração não. Nunca deixe a chamada de envio herdar um timeout curto destinado à consulta, ou você reportará tarefas saudáveis como falhas.
O dicionário job impresso contém o identificador da tarefa e o status atual. Guarde o identificador em algum lugar — o loop de consulta depende dele.
Controlar proporção e formato de saída
Proporção e formato de saída são parâmetros do corpo, não endpoints separados. Eles ficam no mesmo objeto input do prompt:
{
"model": "ideogram-v4.5",
"input": {
"prompt": "...",
"aspect_ratio": "<ratio from docs>",
"output_format": "<format from docs>"
}
}
A disciplina importante aqui é não adivinhar valores. Cada modelo de geração expõe um conjunto fixo de proporções e formatos, e modelos diferentes aceitam grafias diferentes — 16:9 versus 16x9, png versus PNG, etc. Passar um valor não suportado costuma gerar erro de validação ou, pior, cair silenciosamente no padrão, o que parece um bug no seu prompt.
Então o fluxo é:
- Abra a página do modelo ideogram-v4.5 na plataforma e copie palavra por palavra a lista de proporções suportadas e a de formatos de saída.
- Coloque esses valores em uma pequena lista de permissão no código, para que entradas inválidas falhem no ponto de chamada, não na API.
- Use por padrão a proporção que bate com o layout de destino. Se a imagem vai ocupar um card social de 1200×630, escolha um valor próximo dessa proporção em vez de gerar um quadrado e cortar o conteúdo.
Imagens com muito texto merecem um aviso extra: proporções extremas (banners ultralargos, pôsteres ultraaltos) comprimem o espaço disponível para renderizar texto. Para títulos que você realmente precisa que sejam legíveis, proporções moderadas em paisagem ou retrato são mais seguras do que extremos panorâmicos.
Lidar com a tarefa assíncrona e baixar o resultado
O ciclo de vida de uma geração tem três etapas: enviar → consultar → obter.
Enviar
Você já dominou esta etapa nas seções anteriores. A resposta devolve um identificador de tarefa e um status, como queued ou processing.
Consultar
Consulte o endpoint de status da tarefa com esse identificador até que o status indique conclusão. Duas regras mantêm o processo saudável:
- Durma entre consultas. Comece com cerca de um segundo e aumente progressivamente. Martelar o endpoint de status não faz a tarefa terminar mais rápido e ainda arrisca acionar limites de taxa.
- Limite o tempo de espera. Defina um número máximo de tentativas ou um prazo final e retorne um erro explícito ao ultrapassar, em vez de entrar em loop infinito.
import time
def wait_for_job(job_id, headers, base_url, status_path,
max_attempts=60, initial_delay=1.0, factor=1.5):
delay = initial_delay
for _ in range(max_attempts):
r = requests.get(
f"{base_url}{status_path}/{job_id}",
headers=headers,
timeout=30,
)
r.raise_for_status()
data = r.json()
status = data.get("status")
if status in ("succeeded", "completed", "success"):
return data
if status in ("failed", "error", "cancelled"):
raise RuntimeError(f"job {job_id} ended with status {status}: {data}")
time.sleep(delay)
delay *= factor
raise TimeoutError(f"job {job_id} did not finish in time")
Consulte a documentação da plataforma para obter as strings de status e o caminho de status exatos da sua conta — faça a correspondência com os valores da documentação e trate qualquer status não reconhecido como ainda em execução, não como sucesso.
Obter
Quando a tarefa reporta conclusão, a resposta contém o local da saída (normalmente uma URL). Baixe com um GET comum e grave os bytes em disco. A URL de saída pode ter validade temporária, então baixe o quanto antes em vez de guardar a URL para depois. Tudo o que você precisa saber para escrever esse loop vem da estrutura da resposta de envio — não há uma API separada de "obter imagem" para aprender.
Empacotar em uma função auxiliar reutilizável
Três scripts separados que reimplementam a consulta cada um é um problema de manutenção. Empacote uma vez.
import os, json, time, requests
class IdeogramClient:
def __init__(self, base_url, api_key, gen_path, status_path,
poll_attempts=60, poll_factor=1.5):
self.base_url = base_url.rstrip("/")
self.gen_path = gen_path
self.status_path = status_path
self.poll_attempts = poll_attempts
self.poll_factor = poll_factor
self.headers = {
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json",
}
def generate(self, prompt, **params):
body = {"model": "ideogram-v4.5", "input": {"prompt": prompt, **params}}
r = requests.post(self.base_url + self.gen_path,
headers=self.headers,
data=json.dumps(body), timeout=30)
r.raise_for_status()
job = r.json()
done = self._wait(job["id"])
url = done["output"]["url"] # confirm shape in docs
return self._download(url)
def _wait(self, job_id):
delay = 1.0
for _ in range(self.poll_attempts):
r = requests.get(f"{self.base_url}{self.status_path}/{job_id}",
headers=self.headers, timeout=30)
r.raise_for_status()
data = r.json()
if data.get("status") in ("succeeded", "completed", "success"):
return data
if data.get("status") in ("failed", "error", "cancelled"):
raise RuntimeError(data)
time.sleep(delay)
delay *= self.poll_factor
raise TimeoutError(job_id)
def _download(self, url):
r = requests.get(url, timeout=60)
r.raise_for_status()
return r.content
O uso é uma única chamada: img_bytes = IdeogramClient(...).generate("...", aspect_ratio="<from docs>"). Ajuste o acesso a done["output"]["url"] e as strings de status para bater com a estrutura de resposta da documentação — esses dois pontos são os mais prováveis de precisar de ajuste fino por conta.
Erros comuns e dicas de depuração
A maioria das falhas da primeira semana se enquadra em cinco categorias.
401 / 403 — autenticação. Chave ausente, com espaços em branco por causa de copiar e colar, ou sem o prefixo Bearer . Imprima os quatro primeiros e os quatro últimos caracteres da chave que você está realmente enviando; quebras de linha vindas de arquivos de ambiente são o clássico culpado.
400 — JSON malformado ou campo desconhecido. Se o corpo foi montado por concatenação de strings, aspas não escapadas no prompt quebram o JSON. Construa o corpo como dicionário e serialize com json.dumps. Se o JSON faz parsing, o próximo suspeito é um nome de parâmetro que o modelo não aceita — confira suas chaves caractere por caractere contra a página do modelo.
404 / modelo não encontrado. Normalmente é erro de grafia ou de capitalização no identificador do modelo, ou um caminho de endpoint desatualizado. Copie ambos da documentação da plataforma, não de memória nem de tutoriais antigos.
429 — limite de taxa. Quase sempre é consulta agressiva demais. Aumente o atraso inicial de consulta e o fator de recuo. No lado do envio, adicione retentativas com jitter para respostas 429 e 5xx, mas não repita erros de validação 4xx — eles falham da mesma forma sempre.
Tarefa concluída, mas a imagem não abre. Verifique se você baixou bytes e não uma página JSON de erro; chamar raise_for_status() no GET de download captura a maioria desses casos. Confirme também que você trata a URL de download como de curta duração, em vez de cacheá-la entre sessões.
Em caso de dúvida, registre o corpo completo da resposta e o código de status de cada chamada da cadeia inteira — envio, cada consulta e download. A API normalmente diz exatamente o que deu errado; o bug costuma ser que nunca olhamos.
Com um envio funcional, um loop de consulta e tratamento de erros razoável, o ideogram-v4.5 se integra a um pipeline real como qualquer outra chamada de modelo da HiAPI.
Artigos relacionados
Ver todos os artigos →-
Tutorial
Como chamar hailuo-2.3-fast/image-to-video pela API HiAPI: curl e Python na prática
A primeira requisição executável do nível rápido e econômico de geração de vídeo a partir de imagem — do ID do modelo ao download do MP4
-
Tutorial
Como chamar hailuo-2.3/text-to-video pela API HiAPI: curl, Python e exemplos de requisição executáveis
-
Tutorial
Usar Kandinsky 6.0 Pro text-to-video na HiAPI: tutorial de curl e Python
Demonstração prática com foco na requisição: montar a chamada de prompt para clipe de vídeo, enviar a requisição, consultar o status de conclusão e baixar o resultado