HiAPI
Blogue

Tutorial

Como usar a API FLUX.1 Fill Pro: inpainting com máscara usando curl e Python

Oct 24, 2026
Como usar a API FLUX.1 Fill Pro: inpainting com máscara usando curl e Python

flux-1-fill-pro é o modelo de inpainting baseado em máscara da hiapi: você envia uma imagem de origem, uma máscara em preto e branco e um prompt, e apenas as áreas brancas são repintadas. Este guia traz requisições curl e Python prontas para uso, o fluxo assíncrono e o que uma execução real mostrou sobre as bordas da máscara e o tamanho da saída. Você precisa obter uma API key no dashboard.

Estrutura da requisição

O modelo roda sobre a API de tarefas unificada. Crie uma tarefa com POST https://api.hiapi.ai/v1/tasks, faça polling em GET /v1/tasks/<taskId> e então leia data.output[0].url. As entradas abaixo vêm da página do modelo e da documentação da API:

Campo Tipo Descrição
input.image URL, obrigatório Imagem de origem. JPEG, PNG, GIF ou WebP.
input.mask URL, obrigatório Preto preserva a imagem de origem, branco é repintado. Deve ter as mesmas dimensões da imagem de origem.
input.prompt string, obrigatório Descreve o novo conteúdo dentro das áreas brancas. No máximo 4.000 caracteres.
input.steps int, 15–50 Padrão 50.
input.guidance number, 1.5–100 Padrão 60.
input.seed int Com as mesmas entradas, um seed fixo gera resultados consistentes.
input.output_format jpg | png Padrão jpg.
input.prompt_upsampling bool Padrão false. Mantenha desativado para preservar sua formulação exata.

image e mask são URLs, não base64 nem upload de arquivo. Hospede-as em um local acessível pela API via http(s).

Requisição curl mínima

curl -s https://api.hiapi.ai/v1/tasks \
  -H "Authorization: Bearer $HIAPI_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "flux-1-fill-pro",
    "input": {
      "image": "https://dev-static.hiapi.ai/model-onboarding/flux-1-fill-pro/2026/10/19/2026/10/19/1792418738578-4e5072a121d7018f-source.jpg",
      "mask": "https://dev-static.hiapi.ai/model-onboarding/flux-1-fill-pro/2026/10/19/2026/10/19/1792418739459-82bb18075f29c864-mask.png",
      "prompt": "Uma grande pintura a óleo de uma paisagem de montanhas e lago nebuloso na névoa da manhã, com uma moldura fina e preta, pendurada na parede; mantenha o sofá, o piso e a iluminação inalterados.",
      "steps": 30,
      "guidance": 60,
      "seed": 42,
      "output_format": "png"
    }
  }'

A resposta é {"code":200,"data":{"taskId":"tk-hiapi-..."},"message":"success"}. Faça polling desse ID até que data.status seja success ou fail.

Python: criar, fazer polling, baixar

import os, time, requests

API = "https://api.hiapi.ai"
HEADERS = {"Authorization": f"Bearer {os.environ['HIAPI_KEY']}"}

def inpaint(image_url, mask_url, prompt, **opts):
    body = {"model": "flux-1-fill-pro",
            "input": {"image": image_url, "mask": mask_url, "prompt": prompt, **opts}}
    r = requests.post(f"{API}/v1/tasks", headers=HEADERS, json=body, timeout=30)
    r.raise_for_status()
    task_id = r.json()["data"]["taskId"]

    while True:
        try:
            d = requests.get(f"{API}/v1/tasks/{task_id}", headers=HEADERS, timeout=20).json()["data"]
        except requests.RequestException:
            time.sleep(5)          # transient network error: poll the same taskId again
            continue
        if d["status"] == "success":
            return d["output"][0]["url"]
        if d["status"] == "fail":
            raise RuntimeError(d.get("error", d))
        time.sleep(5)

url = inpaint(
    "https://example.com/room.jpg",
    "https://example.com/room-mask.png",
    "Uma pintura de paisagem emoldurada, com moldura fina e preta; mantenha o ambiente inalterado.",
    steps=30, seed=42, output_format="png",
)
open("out.png", "wb").write(requests.get(url, timeout=60).content)

Baixe o resultado imediatamente. A URL de saída traz um expireAt e os arquivos ficam em armazenamento temporário, então não salve esse link como endereço permanente.

Considerações para produção

  • Polling ou callback. Para tarefas em lote, adicione "callback": {"url": "https://your-domain.com/hiapi/callback", "when": "final"} ao corpo da tarefa e deduplique as notificações pelo ID da tarefa. Mantenha o polling como plano B.
  • Repita o polling, não a criação. Um novo POST cria e cobra uma nova tarefa. Se uma requisição de polling falhar, faça polling do mesmo taskId novamente.
  • Máscara consistente com a origem. A máscara deve ter exatamente as mesmas dimensões da imagem de origem, então gere-a a partir do mesmo arquivo (ferramenta de polígono, saída de segmentação) em vez de redimensionar um screenshot.
  • Fixe o seed ao ajustar parâmetros. Use o mesmo seed e altere apenas steps ou guidance, para que cada diferença venha desse parâmetro.

O custo por imagem está na página de preços; confira antes de processar grandes volumes.

O que uma execução real mostrou

Executei a requisição curl acima uma vez com a foto de sala de exemplo da própria página (1600×900) e sua máscara retangular (caixa branca em x 840–1240, y 160–580). Configurações: steps: 30, guidance: 60, seed: 42, output_format: png.

  • Tempo. A tarefa ficou em handling por cerca de 25 segundos, depois em archiving, atingindo success em cerca de 38 segundos no total.
  • O tamanho da saída difere do da origem. O PNG retornado tinha 1440×810, não 1600×900. A proporção é a mesma, mas as dimensões em pixels são diferentes. Se você for compor o resultado de volta na imagem original, redimensione uma delas primeiro e não assuma 1:1.
  • Fora da máscara, tudo permanece igual. Após redimensionar a origem para 1440×810 e compará-la com a saída, 81% dos pixels dentro da caixa branca variaram mais de 8 níveis (0–255), enquanto fora da caixa apenas 0,03% dos pixels variaram nessa medida. A mais de 12 px da borda da máscara, a diferença máxima foi de 11 níveis. O sofá, as almofadas, a planta, o piso e a luz da janela não foram repintados.
  • Escopo do prompt. O prompt descrevia apenas a pintura e o que deveria ser preservado; o resultado foi uma cena emoldurada de montanhas e lago preenchendo a caixa branca.
  • URLs inválidas falham no polling, não na criação. Outra requisição, com image e mask definidos como strings que não são URLs, retornou 200 e um taskId, e então a tarefa terminou após cerca de 3 segundos com status: fail e error.code: TASK_FAILED. Um POST bem-sucedido não significa que a entrada é válida, então sempre verifique o status final.

Não testado: máscara com dimensões diferentes da origem, máscara com valores em cinza (bordas suaves), máscara com canal alfa e valores extremos de guidance ou steps. A documentação diz que a máscara deve ter as mesmas dimensões da origem, e testei apenas retângulos binários rígidos. Não executei vários seeds, então não posso dizer o quanto o preenchimento varia entre execuções.

Quando escolher o Fill Pro

Use-o quando a edição precisar parar em limites rígidos que você controla, como rótulos de produto, linhas de parede ou costuras de roupas. Para edições descritas em texto e sem máscara, use um modelo somente de prompt. O guia de inpainting de imagem e remoção de objetos compara os dois. Para apagar algo de uma máscara sem escrever um prompt, veja o guia do Bria Eraser.

Relacionados

Perguntas frequentes

image e mask são ambos obrigatórios?

Sim. A documentação atual lista image, mask e prompt como obrigatórios.

Qual cor o modelo repinta?

Branco. Os pixels pretos preservam a imagem de origem.

A máscara precisa ter o mesmo tamanho da imagem de origem?

A documentação diz que sim. Usei um par compatível na minha execução e não testei casos incompatíveis.

Como fica o tamanho da saída?

Na minha execução, uma origem de 1600×900 retornou um PNG de 1440×810, com a mesma proporção.

Artigos relacionados

Ver todos os artigos →

Comece a criar com artefactos de IA persistentes

Obtenha a sua chave de API e chame modelos de imagem, vídeo e áudio através de uma única API baseada em tasks.

Ler a documentação da API