Tutorial
Como chamar flux-1-kontext-max na HiAPI: tutorial com curl e Python
O fluxo completo de uma requisição executável: entrada, polling assíncrono e download da saída
Como é uma requisição para flux-1-kontext-max
Antes de escrever qualquer código, ajuda entender o formato da interação. Na HiAPI, uma chamada de edição de imagem para flux-1-kontext-max não é uma requisição/resposta simples que devolve a imagem na mesma chamada HTTP. É uma tarefa em duas fases:
- Envio — você faz POST de um payload JSON descrevendo sua imagem de entrada e a edição desejada. A API aceita a tarefa e devolve um identificador de tarefa.
- Polling — você faz GET do status da tarefa com esse identificador até que ela reporte conclusão e então lê a URL de saída na resposta.
Esse padrão existe porque a edição de imagem é computacionalmente intensiva. Manter uma única conexão HTTP aberta durante todo o processo de renderização é frágil; um handle de tarefa permite desconectar, tentar de novo e voltar depois.
O payload em si se divide conceitualmente em três partes:
- Seletor de modelo — um campo que indica
flux-1-kontext-maxcomo o modelo a executar. - Entrada — normalmente uma imagem (URL ou payload base64, conforme o schema documentado) mais uma instrução de texto descrevendo a edição.
- Controles opcionais — parâmetros que ajustam o comportamento da geração, como proporção de aspecto ou seed, desde que estejam descritos na documentação do modelo.
Todo o resto — cabeçalho de autenticação, endpoint de envio, endpoint de status — é o mesmo pipeline que você usa em cada tarefa da HiAPI. Uma vez internalizado esse ritmo de três passos (envio → polling → download), as versões curl e Python são intercambiáveis, e você pode alternar entre elas sem reaprender o fluxo.
Pré-requisitos e autenticação
Antes de a primeira requisição ter sucesso, você precisa ter algumas coisas prontas.
O que você precisa
- Uma conta HiAPI e uma API key criada no dashboard.
- A URL base da API HiAPI, conforme mostrada na documentação da plataforma.
- Uma imagem de origem acessível pela API — na maioria dos casos, uma URL HTTPS pública. Se sua imagem for privada, faça upload para um local que a API consiga acessar ou, se o schema do modelo aceitar entrada base64, passe-a inline.
curlpara o exercício no shell, e Python 3 com a bibliotecarequestspara o exercício em código.
Autenticação
A HiAPI autentica requisições enviando sua API key no cabeçalho de autorização. A convenção é bearer token:
Authorization: Bearer $HIAPI_API_KEY
E toda requisição JSON deve declarar seu tipo de conteúdo:
Content-Type: application/json
Mantenha a chave fora do código-fonte
Guarde a chave em uma variável de ambiente em vez de colá-la no script:
export HIAPI_API_KEY="your_key_here"
Em Python, leia-a com os.environ["HIAPI_API_KEY"]. No curl, referencie-a como $HIAPI_API_KEY. Esse único hábito evita a causa mais comum de vazamento de credenciais — a chave ser commitada em um repositório e depois ter que ser rotacionada sob pressão.
Se a requisição retornar erro de autenticação, verifique três coisas em ordem: a chave existe e é válida, o cabeçalho está escrito exatamente como na documentação, e não há espaços ou quebras de linha extras na variável de ambiente.
Enviando a requisição com curl
Abaixo está a chamada de envio. Substitua pela sua própria URL de imagem e instrução de edição.
curl -X POST "$HIAPI_BASE_URL/jobs" \
-H "Authorization: Bearer $HIAPI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "flux-1-kontext-max",
"input": {
"image": "https://example.com/input.jpg",
"prompt": "Replace the sky with a dramatic sunset, keep the buildings unchanged"
}
}'
O que cada parte faz
-X POST— o envio é uma operação de criação, então use POST.- Endpoint — o endpoint de jobs aceita novas tarefas. A URL base vem do seu ambiente, então o comando é portável entre ambientes.
Authorization— seu bearer token, lido da variável de ambiente em vez de inline.Content-Type: application/json— obrigatório; sem ele, o servidor pode recusar ou interpretar mal o corpo da requisição.-d— o payload JSON.modelselecionaflux-1-kontext-max,input.imageaponta para sua imagem de origem,input.promptdescreve a edição.
Lendo a resposta
Um envio bem-sucedido devolve um corpo JSON contendo o identificador da tarefa — normalmente um campo como id ou job_id — e um status indicando que a tarefa foi enfileirada ou está em processamento. Guarde esse identificador; o polling depende dele.
curl -s -X POST "$HIAPI_BASE_URL/jobs" \
-H "Authorization: Bearer $HIAPI_API_KEY" \
-H "Content-Type: application/json" \
-d @payload.json | python -m json.tool
Passar a saída por python -m json.tool formata a resposta de forma legível, facilitando encontrar o ID da tarefa. Colocar o corpo da requisição em payload.json mantém o comando legível mesmo quando o prompt fica mais longo.
Neste ponto você enviou a tarefa, mas ainda não recebeu a imagem. A imagem só vem depois do polling.
A mesma requisição em Python
A versão em Python carrega a mesma lógica, com uma ergonomia mais confortável para qualquer coisa que você pretenda manter a longo prazo.
import os
import requests
BASE_URL = os.environ["HIAPI_BASE_URL"]
API_KEY = os.environ["HIAPI_API_KEY"]
headers = {
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json",
}
payload = {
"model": "flux-1-kontext-max",
"input": {
"image": "https://example.com/input.jpg",
"prompt": "Replace the sky with a dramatic sunset, keep the buildings unchanged",
},
}
response = requests.post(
f"{BASE_URL}/jobs",
headers=headers,
json=payload,
timeout=30,
)
response.raise_for_status()
job = response.json()
print("job id:", job["id"])
Por que isso espelha a chamada curl
O parâmetro json=payload serializa o dicionário e define o tipo de conteúdo para você — os bytes enviados são os mesmos que no curl. timeout=30 limita a requisição de envio, fazendo conexões penduradas falharem ruidosamente em vez de travar seu processo. raise_for_status() transforma 4xx ou 5xx em uma exceção que você pode capturar, em vez de devolver silenciosamente um documento de erro.
Pequenas diferenças que importam
- Dicionário em vez de string — você constrói o payload como objeto Python, o que facilita montar prompts dinâmicos ou injetar variáveis.
- Tratamento de exceções — envolva a chamada em
try/except requests.HTTPErrorpara registrar o corpo da resposta; payloads de erro geralmente explicam o que havia de errado na entrada. - Sem escape de shell — prompts longos com aspas não precisam mais de escape, o que elimina toda uma classe de erros.
O ID de tarefa retornado aqui vai direto para a etapa de polling abaixo. A tarefa não muda em nada por ter sido enviada de Python em vez de curl.
Tratando tarefas assíncronas e fazendo polling do resultado
O envio retorna rápido; a renderização, não. Você espera fazendo polling do endpoint de status do ID da tarefa.
Loop de polling
import time
def wait_for_job(job_id, headers, interval=3, max_attempts=100):
url = f"{BASE_URL}/jobs/{job_id}"
for attempt in range(max_attempts):
r = requests.get(url, headers=headers, timeout=30)
r.raise_for_status()
data = r.json()
status = data.get("status")
if status == "succeeded" or status == "completed":
return data
if status == "failed" or status == "error":
raise RuntimeError(f"Job failed: {data}")
time.sleep(interval)
raise TimeoutError(f"Job {job_id} did not finish in time")
Interpretando os status da tarefa
Espere um vocabulário pequeno: um status queued/pending antes de o trabalho começar, um status processing/running durante a renderização do modelo, e um status terminal — sucesso ou falha. Algumas APIs usam grafias ligeiramente diferentes; examine a resposta que você realmente recebe e mapeie essas strings, sem presumir. Regra fundamental: só considere a tarefa concluída quando o status for terminal de sucesso e houver uma URL de saída. O endpoint de status retornar 200 não significa que a imagem está pronta.
Etiqueta de polling
- Espaçe suas requisições. Para tarefas de imagem, alguns segundos entre cada polling são suficientes. Consultar a cada 100 ms desperdiça limite de taxa sem nenhum ganho.
- Limite o tempo de espera.
max_attemptslimita o loop, fazendo uma tarefa travada derrubar seu código em vez de pendurar para sempre. - Faça backoff em 429. Se atingir o limite de taxa, espere mais antes de tentar de novo, em vez de insistir.
- Prefira webhook, se disponível. Se a documentação da plataforma descrever um mecanismo de callback, ele elimina completamente o polling e escala melhor.
Para um teste rápido no shell, um loop simples funciona do mesmo jeito:
JOB_ID="your_job_id"
while true; do
BODY=$(curl -s "$HIAPI_BASE_URL/jobs/$JOB_ID" -H "Authorization: Bearer $HIAPI_API_KEY")
echo "$BODY"
echo "$BODY" | grep -q '"succeeded"' && break
sleep 3
done
Assim que você sair do loop, a resposta terminal contém a referência de saída. Esse é o próximo passo.
Baixando e salvando a saída
A resposta da tarefa concluída aponta para a imagem renderizada, normalmente uma URL (às vezes uma lista). Faça uma segunda requisição para obtê-la e grave os bytes em disco.
import pathlib
def download_output(job_data, path="edit.png"):
out = job_data.get("output")
if isinstance(out, list):
out = out[0]
url = out["url"] if isinstance(out, dict) else out
r = requests.get(url, timeout=60)
r.raise_for_status()
pathlib.Path(path).write_bytes(r.content)
return path
Pontos de atenção
- Não hardcode o formato. O campo de saída varia conforme o modelo — às vezes é uma URL em string, às vezes um objeto com chave
url, às vezes uma lista. Examine a resposta real e normalize antes de baixar. - A URL de saída pode expirar. Trate a URL como de vida curta: baixe imediatamente ou copie logo para o seu próprio armazenamento. Não guarde a URL como registro permanente da imagem.
- Valide os bytes. Verifique se o
Content-Typecomeça comimage/e se o tamanho do arquivo é razoável; uma página de erro salva como.pngé uma falha silenciosa. - Tente de novo em erros transitórios de download. Envolva o GET em tentativas com backoff curto — URLs assinadas às vezes retornam 403 por desvio de relógio, e a rede também oscila.
Para uma verificação manual rápida, curl basta:
curl -L -o edit.png "$OUTPUT_URL"
A flag -L segue redirecionamentos, comuns em saídas hospedadas em CDN. Depois que o arquivo estiver em disco, abra-o e confirme que a edição corresponde ao prompt — essa é sua verificação de ponta a ponta, e em pipelines em que a imagem precisa ser regenerada em caso de falha, vale automatizar uma checagem visual ou de hash.
Falhas comuns e correções
A maioria das falhas de primeira integração acontece de algumas poucas maneiras.
Autenticação e cabeçalhos
- 401/403 — chave errada, expirada ou com espaços extras. Reexporte a variável de ambiente e confirme que o formato do cabeçalho confere com a documentação.
- Content-Type ausente — enviar JSON sem esse cabeçalho pode gerar erros 4xx confusos. Inclua-o ou use
json=em Python.
Problemas de entrada
- Imagem inacessível — a API busca sua imagem no servidor. URLs de
localhostou links que exigem autenticação vão falhar. Use uma URL HTTPS pública ou base64 inline quando houver suporte. - Prompt ignorado ou rejeitado — instruções vagas geram resultados vagos. Descreva o que deve mudar e o que deve ser mantido, como no exemplo do pôr do sol. Prompts muito longos podem ser truncados.
- Parâmetros não suportados — passar campos que o modelo não aceita pode causar erro de validação. Comece com o payload mínimo e depois adicione os controles documentados um a um.
Erros de processamento assíncrono
- Ler a imagem na resposta de envio — a chamada de envio retorna um handle de tarefa, não pixels. Faça polling primeiro.
- Tratar qualquer 200 como conclusão — o endpoint de status também retorna 200 para tarefas ainda em execução. Verifique o campo de status e a existência da URL de saída.
- Polling rápido demais ou eterno — adicione intervalo e um limite superior, ou você esgotará o limite de taxa e pendurará seu worker.
Problemas de download
- Salvar HTML como imagem — sempre verifique o tipo de conteúdo e o tamanho.
- URL de saída expirada — baixe logo após a conclusão; não deixe a URL na fila para depois.
Erros estruturais
- IDs de tarefa trocados — se você enviar várias tarefas, marque cada ID com seu próprio request ID, para que os resultados de polling não se misturem.
- Sem timeout — toda requisição deve ter um. Sem isso, uma chamada pendurada pode travar um lote inteiro.
Transformando o exercício em uma função auxiliar reutilizável
Os três passos — envio, polling, download — pertencem a uma única função, para que quem chama não precise repetir a orquestração.
def edit_image(image_url, prompt, model="flux-1-kontext-max",
headers=None, poll_interval=3, max_attempts=100):
payload = {"model": model,
"input": {"image": image_url, "prompt": prompt}}
r = requests.post(f"{BASE_URL}/jobs", headers=headers,
json=payload, timeout=30)
r.raise_for_status()
job_id = r.json()["id"]
data = wait_for_job(job_id, headers,
interval=poll_interval,
max_attempts=max_attempts)
return download_output(data, path=f"{job_id}.png")
O que a torna pronta para produção
- Ponto de entrada único. Quem chama passa a imagem e o prompt e recebe um caminho de arquivo ou uma exceção. Os detalhes do fluxo ficam ocultos.
- Falha explícita. Toda requisição lança exceção em erro HTTP, e o poller lança em falha de tarefa ou timeout, para que sua fila ou quem chama possa tentar de novo.
- Temporização configurável.
poll_intervalemax_attemptssão parâmetros, então você pode afrouxá-los para edições mais pesadas sem tocar na lógica. - Nomeação previsível da saída. Usar o ID da tarefa como nome de arquivo facilita correlacionar arquivos com logs.
Para onde ir em seguida
Envolva a chamada com preocupações de camada de aplicação: registre o ID da tarefa e a latência, tente de novo envios que falharam com jitter, e envie os bytes baixados direto para o armazenamento de objetos em vez de para o disco local. Se você processa muitas edições, envie um lote de tarefas primeiro e faça polling de todas juntas — o envio é barato, e a concorrência está na espera, não no upload.
A página de flux-1-kontext-max na documentação da HiAPI é a referência para os campos aceitos e os parâmetros atuais. Mantenha a função auxiliar enxuta e deixe a documentação conduzir o schema; assim a mesma função cobre tanto scripts exploratórios quanto pipelines reais.
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