Tutorial
Como usar gpt-image-2/text-to-image pela API hiapi: parâmetros, código e exemplo executável
Este tutorial mostra o mínimo de código necessário para gerar imagens com gpt-image-2/text-to-image através da API de tarefas unificada da hiapi, e em seguida explica parâmetro por parâmetro, bem como os padrões de nível de produção que você deve adotar depois que o código funcionar (callbacks, idempotência, tratamento de erros).
Pré-requisitos
Você precisa de uma chave de API. Crie-a na página de chaves de API do console hiapi — as chaves começam com sk-. A página do modelo gpt-image-2/text-to-image lista o preço atual por imagem; o detalhamento completo está na página de preços.
Todas as chamadas deste guia vão para o endpoint unificado de tarefas assíncronas:
POST https://api.hiapi.ai/v1/tasks— cria uma tarefa de geraçãoGET https://api.hiapi.ai/v1/tasks/{taskId}— consulta o status da tarefa
A documentação de referência geral da plataforma está em documentação da API hiapi.
Exemplo mínimo executável (curl)
Uma única geração é uma interação em duas etapas: primeiro crie a tarefa e depois aguarde sua conclusão.
# 1. Create the task
curl -s -X POST https://api.hiapi.ai/v1/tasks \
-H "Authorization: Bearer sk-YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-image-2/text-to-image",
"input": {
"prompt": "a calico cat curled up on a sunlit windowsill, soft focus background",
"aspect_ratio": "1:1",
"resolution": "1K"
}
}'
# => {"code":200,"data":{"taskId":"tk-hiapi-01KVY...."},"message":"success"}
# 2. Poll until status == "success"
TASK_ID="tk-hiapi-01KVY...."
curl -s "https://api.hiapi.ai/v1/tasks/$TASK_ID" \
-H "Authorization: Bearer sk-YOUR_KEY"
# => {"code":200,"data":{"status":"success","output":[{"url":"https://..."}], ...}}
A URL da imagem fica em data.output[0].url. Baixe-a imediatamente — output[0].expireAt é curto, portanto essa URL serve apenas para obter a imagem, não para incorporação permanente.
Python: criar + consultar + salvar em disco
import os
import time
import urllib.request
import requests # pip install requests
API_BASE = "https://api.hiapi.ai/v1/tasks"
TOKEN = os.environ["HIAPI_API_KEY"] # sk-...
def create_task(prompt: str, aspect_ratio: str = "1:1", resolution: str = "1K") -> str:
payload = {
"model": "gpt-image-2/text-to-image",
"input": {
"prompt": prompt,
"aspect_ratio": aspect_ratio,
"resolution": resolution,
},
}
r = requests.post(API_BASE, json=payload,
headers={"Authorization": f"Bearer {TOKEN}"},
timeout=60)
r.raise_for_status()
body = r.json()
if body.get("error"):
raise RuntimeError(f"create failed: {body['error']}")
return body["data"]["taskId"]
def wait_task(task_id: str, timeout_s: int = 600, poll_s: int = 5) -> dict:
deadline = time.time() + timeout_s
while time.time() < deadline:
r = requests.get(f"{API_BASE}/{task_id}",
headers={"Authorization": f"Bearer {TOKEN}"},
timeout=30)
r.raise_for_status()
task = r.json().get("data") or {}
status = task.get("status")
if status == "success":
return task
if status == "fail":
raise RuntimeError(f"task failed: {task.get('error')}")
time.sleep(poll_s)
raise TimeoutError(f"task {task_id} did not finish in {timeout_s}s")
if __name__ == "__main__":
task_id = create_task(
"a calico cat curled up on a sunlit windowsill, soft focus background",
aspect_ratio="3:2",
resolution="1K",
)
task = wait_task(task_id)
url = task["output"][0]["url"]
urllib.request.urlretrieve(url, "cat.png")
print(f"saved cat.png from task {task_id}")
Node.js: o mesmo fluxo usando fetch
// Node 18+ has global fetch
const API_BASE = "https://api.hiapi.ai/v1/tasks";
const TOKEN = process.env.HIAPI_API_KEY;
async function createTask(prompt, aspectRatio = "1:1", resolution = "1K") {
const res = await fetch(API_BASE, {
method: "POST",
headers: {
"Authorization": `Bearer ${TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
model: "gpt-image-2/text-to-image",
input: { prompt, aspect_ratio: aspectRatio, resolution },
}),
});
const body = await res.json();
if (body.error) throw new Error(`create failed: ${body.error.code} ${body.error.message}`);
return body.data.taskId;
}
async function waitTask(taskId, { timeoutMs = 600_000, pollMs = 5_000 } = {}) {
const deadline = Date.now() + timeoutMs;
while (Date.now() < deadline) {
const res = await fetch(`${API_BASE}/${taskId}`, {
headers: { "Authorization": `Bearer ${TOKEN}` },
});
const task = (await res.json()).data || {};
if (task.status === "success") return task;
if (task.status === "fail") throw new Error(`task failed: ${JSON.stringify(task.error)}`);
await new Promise(r => setTimeout(r, pollMs));
}
throw new Error(`task ${taskId} timed out`);
}
(async () => {
const id = await createTask(
"a calico cat curled up on a sunlit windowsill, soft focus background",
"16:9",
"1K",
);
const task = await waitTask(id);
const url = task.output[0].url;
const img = await fetch(url).then(r => r.arrayBuffer());
const { writeFileSync } = await import("node:fs");
writeFileSync("cat.png", Buffer.from(img));
console.log(`saved cat.png from task ${id}`);
})();
Referência de parâmetros
O corpo da requisição sempre contém dois campos de nível superior: model (string, o ID de modelo puro gpt-image-2/text-to-image) e input (objeto de parâmetros específico de cada modelo).
Campo de input |
Obrigatório | Tipo | Descrição |
|---|---|---|---|
prompt |
Sim | string | Descrição textual da imagem que você deseja. |
aspect_ratio |
Sim | string | Um dos valores: 1:1, 3:2, 2:3, 4:3, 3:4, 5:4, 4:5, 16:9, 9:16, 21:9 ou auto. |
resolution |
Não | string | 1K (padrão), 2K ou 4K. As dimensões em pixels são escaladas de acordo com a proporção escolhida. |
callback |
Não | object | { "url": "https://yours.example/hook", "when": "final" } — veja a próxima seção. |
Uma criação bem-sucedida retorna {"code":200, "data":{"taskId":"tk-hiapi-..."}, "message":"success"}. O GET /v1/tasks/{taskId} retorna data.status como um de handling, success ou fail; em caso de sucesso, data.output é um array cujo primeiro elemento contém a url da imagem e o carimbo de data/hora expireAt.
Outros modelos de imagem da hiapi (por exemplo,
z-image,qwen-image) usam campos deinputligeiramente diferentes —aspect_ratioé a convenção adotada porgpt-image-2/text-to-image. Ao trocar de modelo, consulte a página do modelo para confirmar a estrutura exata deinput.
Padrões de nível de produção
Usar callbacks em vez de consultas
Consultar a cada 5 segundos é aceitável para prototipagem, mas para tráfego de produção você quer que a hiapi envie a tarefa concluída para você, liberando o worker. Adicione um bloco callback em input:
{
"model": "gpt-image-2/text-to-image",
"input": {
"prompt": "an astronaut sketching the moon",
"aspect_ratio": "3:2",
"resolution": "1K",
"callback": {
"url": "https://your-app.example.com/webhooks/hiapi",
"when": "final"
}
}
}
when: "final" dispara uma vez quando a tarefa atinge um estado terminal (success ou fail). O payload recebido pelo seu endpoint tem a mesma estrutura de GET /v1/tasks/{id}, portanto o handler pode reutilizar a lógica de parsing da consulta. Verifique o taskId contra o taskId que você armazenou ao criar a tarefa, para saber a qual requisição o callback pertence.
Tornar a operação de criação idempotente
Se o worker falhar após o POST /v1/tasks e antes de armazenar o taskId, você pode acabar gerando a mesma imagem duas vezes. A solução de baixo custo é: no momento em que receber a resposta de criação, armazenar (your_request_id → taskId) no banco de dados na mesma transação que envia a requisição. Se o worker tentar novamente, ele encontrará o taskId existente e retomará a consulta, em vez de criar uma nova tarefa.
Tratar corretamente erros de autenticação
Falhas de autenticação da hiapi retornam HTTP 200 com um payload de erro embutido no corpo da resposta:
{"error":{"code":"permission_denied","message":"This API key cannot use the selected model. ...","type":"hiapi_error"}}
Portanto, um código de status 200 sozinho não significa sucesso. Sempre verifique body.error primeiro; se existir, examine error.code (permission_denied, invalid_request, etc.) e error.message. O request_id na mensagem é o que você deve colar em um ticket de suporte caso precise de ajuda.
Baixar imediatamente e rehospedar por conta própria
data.output[0].url é uma URL de curta duração — a resposta inclui expireAt. Não coloque a URL da hiapi diretamente em um <img src> do seu produto; assim que a tarefa for concluída com sucesso, baixe os bytes imediatamente, envie para o seu próprio armazenamento (S3, R2, Supabase Storage, etc.) e sirva a partir de lá.
Definir timeouts razoáveis
Um padrão razoável é: timeout de 60 segundos para o POST (a criação da tarefa é rápida — na prática você está apenas aguardando a confirmação de recebimento da API), orçamento total de 10 minutos para o loop de consulta e intervalo de 5 segundos entre consultas. Tarefas que levam mais de 10 minutos quase sempre significam que a tarefa entrou silenciosamente no estado fail, portanto expirar e registrar o último corpo de resposta da tarefa no log é mais útil do que esperar indefinidamente.
Perguntas frequentes
Qual é a diferença entre gpt-image-2 e gpt-image-2/text-to-image?
gpt-image-2 é a família de modelos; gpt-image-2/text-to-image é o endpoint específico que você chama para converter um prompt de texto em uma nova imagem. Outras variantes da família expõem estruturas de input diferentes (por exemplo, a edição de imagem aceita imagens de referência). Em caso de dúvida, use o ID de modelo puro que você vê na página do modelo.
O que aspect_ratio: auto faz?
auto permite que o modelo decida a proporção com base no prompt. Use isso quando não houver requisitos rígidos de layout; caso contrário, fixe a proporção você mesmo para que o recorte downstream seja previsível.
Por que minha requisição retorna HTTP 200 com permission_denied?
Ou a chave de API está errada (erro de digitação, revogada, faltando o prefixo sk-), ou o plano dessa chave não inclui gpt-image-2/text-to-image. Abra o console de chaves de API, confirme a string da chave e verifique seu plano na página de preços. Sempre verifique body.error.code — nunca confie apenas no código de status HTTP.
Posso gerar várias imagens em uma única requisição?
gpt-image-2/text-to-image gera apenas uma imagem por tarefa — data.output é um array, mas para esse modelo o comprimento é sempre 1. Para gerar N variantes, dispare N tarefas simultaneamente e use o padrão de callback acima, para não deixar N threads de trabalho penduradas.
Como cancelar uma tarefa em execução?
A API de tarefas unificada atualmente não oferece endpoint de cancelamento. A mitigação mais simples é fazer o worker cliente descartar o resultado quando o usuário não precisar mais dele — a geração já executada ainda será cobrada, portanto o lugar correto para impor cancelamento é antes de chamar POST /v1/tasks.
Como trocar para outro modelo de imagem?
Altere model para o novo ID puro (por exemplo, z-image/text-to-image) e ajuste input para corresponder à estrutura desse modelo. As estruturas variam entre modelos — alguns aceitam size, outros aceitam aspect_ratio, e alguns não aceitam resolution. O catálogo de modelos lista todos os modelos disponíveis, e cada página de modelo documenta seus campos de input.
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