Tutorial
Como usar seedream-4.5/image-to-image através da API hiapi: curl, Python e requisições disponíveis
Para editar imagens com o seedream-4.5, basta enviar um POST para a API de tarefas unificada da hiapi, fazer uma breve consulta de status (polling) e então baixar o resultado. Este guia traz requisições curl funcionais e um script Python completo para o seedream-4.5/image-to-image, além de uma descrição precisa dos campos de entrada (verificada contra a API em produção), uso com múltiplas imagens de referência e os erros que você realmente vai encontrar.
O que você vai construir e o que precisa
Objetivo: enviar uma ou mais imagens de origem junto com uma instrução de edição para seedream-4.5/image-to-image e obter de volta a URL da imagem finalizada.
Pré-requisitos:
- Uma chave de API hiapi — obtenha no seu console. Todas as requisições abaixo a utilizam como token Bearer.
- As imagens de origem hospedadas em URLs acessíveis publicamente. A API as busca no lado do servidor; caminhos de arquivo locais ou URLs privadas não funcionam.
O modelo roda em um endpoint de tarefas assíncronas: POST /v1/tasks cria a tarefa, GET /v1/tasks/<taskId> informa o status, e a imagem finalizada aparece em data.output[0].url.
Descrição dos campos de entrada (verificada)
seedream-4.5/image-to-image tem quatro campos de entrada obrigatórios e não aceita nenhum outro — a especificação é estrita e campos desconhecidos são rejeitados com 400:
| Campo | Tipo | Restrição |
|---|---|---|
prompt |
string | Instrução de edição |
image_urls |
array de strings | URLs públicas, até 14 imagens |
aspect_ratio |
string | Um de 1:1, 4:3, 3:4, 16:9, 9:16, 2:3, 3:2, 21:9 |
resolution |
string | Apenas 2K ou 4K |
Dois pontos merecem atenção: não existe parâmetro n (uma saída por tarefa — para múltiplas variantes, crie várias tarefas em paralelo); e, ao contrário do image-to-image do seedream-5.0-pro (que aceita 1K/2K), o 4.5 exige 2K ou 4K. Enviar 1K aqui retorna erro de validação.
Requisição mínima funcional: curl
curl -s -X POST https://api.hiapi.ai/v1/tasks \
-H "Authorization: Bearer sk-<your-key>" \
-H "Content-Type: application/json" \
-d '{
"model": "seedream-4.5/image-to-image",
"input": {
"prompt": "Turn this product shot into a clean studio photo on a seamless white background with soft shadows",
"image_urls": ["https://your-cdn.example.com/source.jpg"],
"aspect_ratio": "1:1",
"resolution": "2K"
}
}'
Uma criação bem-sucedida retorna o ID da tarefa em data.taskId. Consulte-a:
curl -s https://api.hiapi.ai/v1/tasks/<taskId> \
-H "Authorization: Bearer sk-<your-key>"
Quando data.status chega a success, a URL da imagem está em data.output[0].url. Se for fail, o motivo está em data.error.
Script Python completo
Não é necessário SDK — apenas requests e um loop de polling:
import time
import requests
API_BASE = "https://api.hiapi.ai/v1/tasks"
API_KEY = "sk-<your-key>"
HEADERS = {"Authorization": f"Bearer {API_KEY}"}
def edit_image(prompt: str, image_urls: list[str],
aspect_ratio: str = "1:1", resolution: str = "2K") -> bytes:
# 1. Create the task
resp = requests.post(API_BASE, headers=HEADERS, json={
"model": "seedream-4.5/image-to-image",
"input": {
"prompt": prompt,
"image_urls": image_urls, # public URLs, max 14
"aspect_ratio": aspect_ratio,
"resolution": resolution, # "2K" or "4K"
},
}, timeout=60)
resp.raise_for_status()
task_id = resp.json()["data"]["taskId"]
# 2. Poll until terminal state
deadline = time.time() + 600
while time.time() < deadline:
task = requests.get(f"{API_BASE}/{task_id}",
headers=HEADERS, timeout=30).json()["data"]
if task["status"] == "success":
url = task["output"][0]["url"]
# 3. Output URLs expire -- download immediately
return requests.get(url, timeout=120).content
if task["status"] == "fail":
err = task.get("error") or {}
raise RuntimeError(f"task failed: {err.get('code')} {err.get('message')}")
time.sleep(5)
raise TimeoutError(f"task {task_id} did not finish in 600s")
png = edit_image(
"Turn this product shot into a clean studio photo on a seamless white background",
["https://your-cdn.example.com/source.jpg"],
)
with open("edited.png", "wb") as f:
f.write(png)
Observe o comentário do passo 3: a URL de saída carrega um timestamp de expiração. Assim que a tarefa for concluída, persista os bytes no seu próprio armazenamento imediatamente — não guarde apenas a URL retornada e conte com ela ainda funcionando amanhã.
Edição com múltiplas imagens de referência
image_urls aceita até 14 imagens em uma única tarefa. Isso é ótimo para tarefas de transferência de estilo e composição: passe a imagem que você quer editar junto com as imagens de referência e descreva no prompt como combiná-las.
{
"model": "seedream-4.5/image-to-image",
"input": {
"prompt": "Apply the color grading and lighting style of the second image to the first image, keep the subject unchanged",
"image_urls": [
"https://your-cdn.example.com/subject.jpg",
"https://your-cdn.example.com/style-reference.jpg"
],
"aspect_ratio": "3:2",
"resolution": "2K"
}
}
A ordem importa para o prompt, não para a API — refira-se às imagens por posição ("a primeira imagem", "a segunda imagem") para que o modelo saiba qual é qual.
Considerações para produção
Use callback em vez de polling. Para qualquer cenário além de scripts, adicione um objeto callback de nível raiz ao criar a tarefa e pule completamente o loop de polling:
{
"model": "seedream-4.5/image-to-image",
"input": { "...": "..." },
"callback": { "url": "https://yourapp.com/hooks/hiapi", "when": "final" }
}
Quando a tarefa terminar, a hiapi enviará o estado final da tarefa por POST para a sua URL. O polling é adequado para ferramentas CLI e notebooks; para backends Web, o callback é a escolha correta, caso contrário você manterá um worker ocupado pelas dezenas de segundos necessárias para uma edição em 2K.
Idempotência. A criação de tarefas não é idempotente — repetir a criação após um timeout de rede pode gerar (e cobrar) duas tarefas. Armazene o taskId no momento em que o receber e, ao repetir, verifique primeiro se já existe uma tarefa ativa antes de criar uma nova.
Tratamento de erros. Os dois primeiros tipos de falha que você vai encontrar:
- 401
permission_denied— chave incorreta, ou a chave não tem acesso a este modelo. O corpo da resposta é parecido com{"error": {"code": "permission_denied", "message": "This API key cannot use the selected model...", "request_id": "..."}}. Inclua orequest_idao contatar o suporte. - 400
INVALID_REQUEST— violação da especificação de campos, com mensagem precisa: valor incorreto deresolution, mais de 14 itens emimage_urls, campo desconhecido ouimage_urlsque não é um array. Esses são capturados antes da execução da tarefa, portanto não geram custo.
Tarefas com falha reportam status: "fail" na própria tarefa, junto com um objeto error — trate isso como um caso diferente dos erros HTTP, como faz o script Python acima.
Preços
O custo por imagem depende da resolução. Consulte as tarifas atuais na página de preços. Requisições rejeitadas na fase de validação (400) nunca iniciam uma tarefa, então erros de especificação de campos durante a integração não têm custo.
Leitura relacionada
- Página do modelo seedream-4.5/image-to-image — playground, preços e referência completa de parâmetros
- seedream-4.5/text-to-image — mesma família, geração apenas por prompt
- Guia do seedream-5.0-pro image-to-image — camada mais nova, enum de resolução diferente
- Documentação da hiapi — referência da API de tarefas e autenticação
Perguntas frequentes
Posso enviar um arquivo local ou uma imagem base64 em vez de uma URL?
Não. image_urls deve ser um array de URLs acessíveis publicamente — a plataforma as busca e normaliza no lado do servidor. Faça upload para o seu próprio armazenamento (S3, R2, qualquer CDN) primeiro e então passe a URL.
Quantas imagens de referência o seedream-4.5 image-to-image suporta?
Até 14 por tarefa. Exceder retorna 400 com uma mensagem contendo image_urls: maxItems.
Por que recebo 400 quando defino resolution como 1K?
O endpoint 4.5 image-to-image aceita apenas 2K ou 4K. A opção 1K pertence ao image-to-image do seedream-5.0-pro — famílias de camadas diferentes têm enums diferentes.
Posso gerar múltiplas variantes em uma única requisição?
Não — a especificação de campos não tem parâmetro n e rejeita campos desconhecidos. Crie uma tarefa para cada variante e execute-as em paralelo; cada tarefa retorna apenas uma saída.
Quanto tempo a URL do resultado fica válida? As URLs de saída têm assinatura e tempo de expiração. Baixe a imagem e armazene-a você mesmo logo após a conclusão da tarefa, em vez de fazer hotlink da saída da tarefa.
Qual é a diferença entre um erro HTTP e uma tarefa com falha?
Erros HTTP (400/401) significam que a requisição nunca se tornou uma tarefa — corrija o payload ou a chave e reenvie. Uma tarefa que termina com status: "fail" foi aceita mas não pôde ser concluída; o motivo está no objeto error da tarefa e, para falhas transitórias, repetir com as mesmas entradas geralmente é a atitude correta.
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