Tutorial
Como usar o imagen4-ultra pela API do HiAPI: exemplos em curl e Python
Um exercício prático completo de requisição para geração de imagens de alta qualidade a partir de texto no HiAPI
O que o imagen4-ultra no HiAPI pode oferecer a você
O imagen4-ultra é o modelo de geração de imagens de alta qualidade a partir de texto do HiAPI: você envia um prompt e recebe uma imagem gerada. O que o torna realmente útil para desenvolvedores é que, assim como todos os outros modelos da plataforma, ele roda por trás da interface unificada do HiAPI, então a forma de autenticação, a estrutura de requisição e o padrão de tratamento de tarefas que você aprende aqui podem ser reaproveitados diretamente em outros endpoints.
Este tutorial é um exercício prático executável, e não uma lista de parâmetros. Ao terminar a leitura, você terá:
- uma requisição
curlpronta para copiar e colar, usada para enviar uma tarefa de geração de imagem a partir de texto, - um pequeno cliente em Python reescrito a partir da mesma requisição,
- uma compreensão clara de como a proporção de tela e outras opções afetam a saída,
- e um laço de polling para aguardar a conclusão da tarefa e salvar a imagem em disco.
Uma observação inicial sobre expectativas: a geração de imagens não é instantânea. O imagen4-ultra opera de forma assíncrona — você envia a tarefa, recebe um identificador de tarefa e então faz polling até a renderização terminar. Se você já usou outros endpoints assíncronos do HiAPI, esse fluxo será familiar; se não, a seção de polling cobre todo o ciclo de vida.
Vamos nos manter sempre dentro do escopo da própria API do HiAPI: sem SDK específico de fornecedor e sem console de terceiros. Uma URL base, uma chave, um formato de requisição.
Antes de enviar a primeira requisição
Antes que a primeira chamada funcione, você precisa de três coisas.
1. Uma chave de API
Gere a chave no console da sua conta HiAPI. Trate-a como uma senha: guarde-a em uma variável de ambiente, em vez de colá-la diretamente no arquivo-fonte.
export HIAPI_API_KEY="your-key-here"
2. A URL base
Todas as requisições do HiAPI vão para o mesmo host de API documentado na documentação da plataforma. Centralize isso em um único lugar no código, para não acabar com hardcodes em vários pontos:
export HIAPI_BASE_URL="https://api.hiapi.ai"
Se a sua conta ou região usar outro host, utilize o valor mostrado no console — o caminho da requisição abaixo permanece o mesmo.
3. Como as informações de autenticação são enviadas
O HiAPI usa um token bearer no cabeçalho Authorization. Toda requisição — seja de envio ou de polling — carrega os mesmos dois cabeçalhos:
Authorization: Bearer $HIAPI_API_KEY
Content-Type: application/json
É só isso de autenticação. Não há etapa de assinatura de requisição nem troca de token a cada chamada. Se você consegue definir cabeçalhos, consegue chamar esta API.
Antes de continuar, faça uma verificação básica: confirme que sua chave foi exportada na mesma sessão de shell em que você vai executar o curl. Boa parte dos relatos de “401 Unauthorized” acaba se resumindo a uma chave exportada em uma aba de terminal e usada em outra.
Daqui em diante, vamos sempre assumir que o identificador do modelo é imagen4-ultra. Se quiser confirmar a string exata exposta na sua conta, consulte a lista de modelos na documentação.
A requisição curl executável
Abaixo está uma requisição de envio completa. Ela envia o prompt, define a proporção de tela da saída e solicita a geração de uma única imagem.
curl -sS -X POST "$HIAPI_BASE_URL/v1/images/generations" \
-H "Authorization: Bearer $HIAPI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "imagen4-ultra",
"prompt": "A lone lighthouse on a rocky coast at dusk, long exposure, dramatic clouds, cinematic lighting",
"aspect_ratio": "16:9",
"n": 1
}'
Explicação campo a campo do corpo da requisição:
model—— o identificador do modelo que você está chamando. Ele determina o roteamento da requisição; sem ele, a API não sabe qual modelo executar.prompt—— a descrição em linguagem natural da imagem. É a principal alavanca que afeta a qualidade da saída. Seja específico quanto ao sujeito, à iluminação, ao estilo e à composição; prompts vagos produzem apenas imagens vagas.aspect_ratio—— a forma do canvas de saída, expressa como largura:altura. Mais detalhes adiante.n—— quantas imagens gerar neste envio. Mantenha em1durante os testes, para que o custo de cada execução seja fácil de estimar.
Dependendo da configuração do endpoint, a resposta conterá ou a imagem já concluída ou — o que é mais comum para esse tipo de modelo — um objeto de tarefa com um identificador e um campo de status. Capture esse identificador; a seção de polling depende dele.
# 提交响应的典型结构
{
"id": "job_abc123",
"status": "queued"
}
Passe a resposta por um formatador JSON (se tiver, | jq .), assim você consegue ler os nomes dos campos conforme a resposta da sua conta, em vez de apertar os olhos para uma linha inteira.
Escrevendo a mesma requisição em Python
A versão em Python é uma tradução linha a linha — mesma URL, mesmos cabeçalhos, mesmo corpo de requisição. Usar requests deixa o mapeamento evidente:
import os
import requests
API_KEY = os.environ["HIAPI_API_KEY"]
BASE_URL = os.environ.get("HIAPI_BASE_URL", "https://api.hiapi.ai")
headers = {
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json",
}
payload = {
"model": "imagen4-ultra",
"prompt": "A lone lighthouse on a rocky coast at dusk, long exposure, dramatic clouds, cinematic lighting",
"aspect_ratio": "16:9",
"n": 1,
}
response = requests.post(
f"{BASE_URL}/v1/images/generations",
headers=headers,
json=payload,
timeout=30,
)
response.raise_for_status()
job = response.json()
print(job["id"], job["status"])
Ao levar este código para um serviço real, vale manter alguns pontos:
- Leia a chave da variável de ambiente, nunca de um literal no arquivo. A forma
os.environ[...]falha de forma explícita quando a variável está ausente, e é exatamente isso que você quer. - Defina um timeout explícito para a chamada de envio. A tarefa em si roda de forma assíncrona, então a requisição HTTP deve retornar rápido; um limite de 30 segundos captura problemas de rede em vez de deixar o programa travado.
- Chame
raise_for_status()antes de tocar no JSON. O corpo de uma resposta 4xx não tem a estrutura que você espera; falhar cedo fornece um traceback mais claro do que umKeyErrortrês linhas depois. - Reutilize
requests.Sessionse for enviar muitas tarefas — o pool de conexões importa mais do que parece.
Se você preferir httpx ou aiohttp, a conversão é mecânica: mesmo dicionário de headers, mesmo corpo JSON, mesmo caminho. A requisição em si independe da biblioteca HTTP.
Proporção de tela e opções de requisição
A proporção de tela é a opção que você ajusta com mais frequência, porque altera tanto a composição quanto as dimensões de saída disponíveis para o layout a jusante.
A proporção de tela é passada no corpo da requisição como uma string "width:height" — "1:1", "16:9", "9:16", "4:3", "3:2" e assim por diante. Escolha a proporção que corresponde ao uso final da imagem:
1:1—— avatares, blocos de produto, posts sociais que serão recortados em quadrado.16:9/9:16—— banners de destaque, thumbnails de vídeo, posicionamentos em formato de story vertical.4:3/3:2—— composições fotográficas clássicas, layouts de galeria.
Defina a proporção de forma consciente, em vez de gerar um quadrado e depois recortar. O recorte descarta pixels que você já pagou para gerar e ainda pode cortar o sujeito fora do enquadramento. Se você sabe qual é o posicionamento final, codifique isso na requisição.
Além da proporção de tela, as opções que importam no uso diário são:
prompt—— continua sendo a entrada de maior impacto. Itere aqui antes de iterar em qualquer outro lugar.n—— a quantidade de imagens geradas por envio. Útil quando você quer várias variantes para escolher; mantenha baixo durante a fase de exploração de prompts.model—— o identificador exato da variante do modelo. Se sua conta expõe vários modelos de imagem, é este campo que alterna entre eles.
Atenha-se aos parâmetros documentados para esse endpoint e não adivinhe nomes. Campos desconhecidos são uma causa comum de respostas 400, e opções com erro de digitação passam facilmente despercebidas em corpos de requisição grandes. Em caso de dúvida, envie primeiro um corpo mínimo — model, prompt, aspect_ratio — confirme que funciona e então adicione uma opção por vez.
Fazendo polling de tarefas assíncronas e baixando o resultado
A geração de imagens leva tempo, então a chamada de envio retorna uma tarefa, não uma imagem. O ciclo de vida é: enviar → consultar o status → baixar a saída.
Passo 1: enviar e capturar o ID da tarefa
Reutilize a requisição anterior e extraia o id da resposta:
job = response.json()
job_id = job["id"]
Passo 2: fazer polling até a tarefa chegar a um estado terminal
Consulte o endpoint de status com os mesmos cabeçalhos de autenticação, dormindo entre cada tentativa. Faça backoff progressivo para evitar sobrecarregar a API:
import time
def wait_for_job(job_id, headers, base_url, timeout=300):
deadline = time.time() + timeout
delay = 2
while time.time() < deadline:
r = requests.get(
f"{base_url}/v1/images/generations/{job_id}",
headers=headers,
timeout=30,
)
r.raise_for_status()
data = r.json()
status = data["status"]
if status == "succeeded":
return data
if status == "failed":
raise RuntimeError(f"job failed: {data}")
time.sleep(delay)
delay = min(delay * 2, 15)
raise TimeoutError(f"job {job_id} not finished within {timeout}s")
Detalhes importantes: um prazo final rígido, limite máximo para o intervalo de backoff e um ramo explícito para o estado de falha, de modo que tarefas com problema se manifestem como exceção em vez de ficar penduradas.
Passo 3: baixar a imagem
A resposta de uma tarefa concluída contém a localização da saída — uma URL ou uma referência equivalente ao artefato. Busque-a e grave os bytes em disco:
result = wait_for_job(job_id, headers, BASE_URL)
image_url = result["output"][0]["url"]
img = requests.get(image_url, timeout=60)
img.raise_for_status()
with open("lighthouse.png", "wb") as f:
f.write(img.content)
Dois hábitos que evitam a maioria dos imprevistos em produção: grave sempre em modo binário ("wb"), nunca em modo texto; e trate a URL de download como temporária — salve o arquivo imediatamente no seu próprio armazenamento, em vez de contar com a validade indefinida do link.
Erros comuns e como corrigi-los
A maioria das falhas se enquadra em algumas categorias. Abaixo estão as manifestações de cada uma e como resolver.
401 Unauthorized
Chave ausente, malformada ou invisível para o processo que envia a requisição.
- Verifique se o cabeçalho é exatamente
Authorization: Bearer <key>— a palavraBearer, um espaço e então a chave. - Confirme que a variável de ambiente está definida no mesmo shell ou processo. Em containers e CI, as variáveis exportadas no seu shell local não acompanham o código.
- Se você rotacionou a chave recentemente, verifique se a chave antiga não continua em cache em algum lugar.
400 Bad Request
Normalmente é um problema no corpo da requisição.
- Nome de campo desconhecido ou com erro de digitação — atenha-se aos parâmetros documentados.
- Valor de
aspect_rationão aceito pelo endpoint — use o formatowidth:heightda documentação. nfora do intervalo permitido.- JSON malformado — por exemplo, vírgula sobrando ou aspas não escapadas dentro da string do prompt. Se suspeitar disso, formate e imprima o corpo da requisição antes de enviar.
404 na consulta de status ou no passo de download
O ID da tarefa está errado, ou o caminho que você consulta não corresponde ao endpoint usado no envio. Registre integralmente a resposta de envio na primeira integração e compare o ID caractere por caractere.
Timeout no polling
Se o wait_for_job atingiu o prazo final:
- Confirme que você está verificando o valor de status correto; um estado terminal que você não reconhece parece um travamento.
- Para renderizações grandes e complexas, aumente o timeout total em vez de encurtar o intervalo de polling.
- Durante a integração, registre cada resposta de status, assim você vê quanto tempo a tarefa realmente leva com a sua combinação de prompts.
A tarefa retorna status failed
Leia o corpo de erro devolvido pela API — ele existe por um motivo. Tarefas com falha costumam ter origem no prompt ou nos parâmetros, então a correção está na requisição, não no código de polling.
Quando algo não estiver claro, a documentação do HiAPI para esse modelo é a fonte autoritativa para nomes de campos e valores aceitos. Valide uma alteração por vez e guarde uma requisição sabidamente funcional como referência para a próxima integração.
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