HiAPI
Blogue

Tutorial

Como chamar recraft-v4-styles-pro/text-to-image na API hiapi: curl e Python

Oct 31, 2026
hiapi 博客封面:近黑底色上有序排列的薄荷绿数据点阵由疏到密渐变,呈半调网点质感,另有点缀深青色,画面无文字。

O que este endpoint faz e quando usá-lo

recraft-v4-styles-pro/text-to-image converte prompts de texto em imagens, e sua característica marcante é a consciência de estilo: você pode guiar a linguagem visual do resultado por meio de referências de estilo, em vez de depender apenas da formulação do prompt. É uma escolha prática quando a saída precisa manter uma sensação consistente ao longo de muitas gerações, e não apenas ficar bonita em uma ou duas.

Desenvolvedores costumam usá-lo nos seguintes cenários:

  • Materiais de consistência de marca — imagens principais, cards sociais e variações de anúncios, todos precisando cair dentro do mesmo sistema visual.
  • Mockups de produto e marketing — refinando prompts repetidamente e fixando o estilo para produzir um conjunto de variações alinhadas à marca.
  • Etapas de pipeline — a geração como uma fase dentro de uma automação maior, em que outro serviço consome a imagem salva.

Há uma característica que determina como cada exemplo de código abaixo é escrito: a geração de imagens é assíncrona. A requisição envia a tarefa e retorna imediatamente; a imagem só aparece depois. Você precisa escrever a etapa de envio e a etapa de polling, tratando-as como duas preocupações independentes.

Preparando as credenciais da hiapi e a base da requisição

Todas as chamadas passam pela interface unificada de endpoints da hiapi, então antes da primeira requisição você precisa preparar três coisas:

  1. Uma chave de API, obtida na sua conta hiapi. Trate-a como qualquer outro segredo: carregue de uma variável de ambiente e nunca a codifique diretamente em um script que você possa compartilhar.
  2. O identificador do modelo, que deve corresponder exatamente ao publicado: recraft-v4-styles-pro/text-to-image.
  3. Uma ferramenta com suporte a HTTP — curl para exploração e uma biblioteca HTTP para qualquer cenário persistente.
export HIAPI_API_KEY="your-key-here"

Convenções que vale a pena internalizar cedo:

  • Use Content-Type: application/json ao enviar um corpo JSON.
  • Autentique com o cabeçalho de bearer token.
  • Mantenha o id do modelo, o prompt e as referências de estilo como campos separados no payload, em vez de juntar tudo em uma única string — assim a etapa de polling e os logs ficam mais fáceis de entender.

Para os nomes exatos dos cabeçalhos, a URL base e as definições atuais dos campos, consulte a documentação de referência da API hiapi deste modelo; trate este tutorial como a forma da chamada e a referência como a fonte autoritativa dos nomes.

Uma requisição curl funcional

Abaixo está a chamada de envio. Entenda-a em três camadas: transporte, autenticação e corpo da requisição.

curl -sS -X POST "$HIAPI_BASE_URL/generate" \
  -H "Authorization: Bearer $HIAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "recraft-v4-styles-pro/text-to-image",
    "prompt": "minimalist product photo of a ceramic mug on a linen surface, soft daylight",
    "style_references": []
  }'

Explicação linha a linha:

  • -X POST — envia a tarefa, não busca.
  • Authorization: Bearer ... — o token vem da variável de ambiente, então o comando pode ser colado com segurança no terminal e compartilhado com segurança depois de remover a variável.
  • -d '{...}' — o corpo JSON. model é o identificador exato. prompt é o texto livre que descreve a cena. style_references é o ponto de montagem do controle de estilo, discutido a seguir.
  • -sS — modo silencioso para a barra de progresso, mas ainda exibe erros, para que chamadas com falha fiquem visíveis.

Uma resposta bem-sucedida é uma confirmação, não uma imagem: você recebe o identificador da tarefa e o status. Anote esse identificador — é o único handle necessário para o polling. Se estiver explorando interativamente, passe a resposta por um formatador JSON para que o id da tarefa e o status se destaquem.

Passando referências de estilo junto com o prompt

O modelo mental é simples: o prompt diz o quê, as referências de estilo dizem como deve parecer. Mantenha-os separados no payload e você preserva a flexibilidade — pode executar novamente o mesmo prompt com vários conjuntos de estilo para comparar resultados.

{
  "model": "recraft-v4-styles-pro/text-to-image",
  "prompt": "ceramic mug on a linen surface, soft daylight",
  "style_references": [
    "https://your-bucket.example.com/styles/mug-ref-01.jpg",
    "https://your-bucket.example.com/styles/mug-ref-02.jpg"
  ]
}

Conselhos práticos:

  • Comece sem referências. Faça primeiro uma execução nua do prompt. Depois adicione uma referência e observe a diferença, depois duas. Mudar uma coisa de cada vez traz muito mais informação do que usar o conjunto completo de estilos na primeira tentativa.
  • Mantenha as referências acessíveis. Hospede-as onde o serviço possa buscá-las de forma confiável — um bucket público ou URLs assinadas com validade folgada — e não links que expiram em poucos minutos.
  • Mantenha o conjunto coerente. Referências consistentes entre si (iluminação, paleta e textura semelhantes) tendem a produzir resultados mais estáveis do que uma mistura heterogênea, que exige que o modelo reconcilie contradições.
  • Versione as referências. Armazene-as sob chaves estáveis. Quando a saída der problema no mês que vem, você precisa saber exatamente quais arquivos de referência foram usados na época.

Consulte a documentação de referência da hiapi deste modelo para confirmar se as referências de estilo são passadas como URLs, recursos enviados ou presets nomeados, e quais limites existem quanto à quantidade e ao formato.

A mesma chamada em Python

A chamada curl se traduz diretamente. Envolva-a em funções pequenas para reutilizá-la como etapa de pipeline.

import os
import requests

HIAPI_BASE_URL = os.environ["HIAPI_BASE_URL"]
HIAPI_API_KEY = os.environ["HIAPI_API_KEY"]


def submit_generation(prompt: str, style_references: list[str] | None = None) -> str:
    """Envia uma tarefa de texto para imagem e retorna o id da tarefa."""
    payload = {
        "model": "recraft-v4-styles-pro/text-to-image",
        "prompt": prompt,
        "style_references": style_references or [],
    }
    response = requests.post(
        f"{HIAPI_BASE_URL}/generate",
        headers={
            "Authorization": f"Bearer {HIAPI_API_KEY}",
            "Content-Type": "application/json",
        },
        json=payload,
        timeout=30,
    )
    response.raise_for_status()
    data = response.json()
    return data["job_id"]

Notas de design:

  • Sempre defina um timeout. Um envio que trava indefinidamente bloqueia seu worker de forma tão eficaz quanto uma falha.
  • raise_for_status() converte respostas não-2xx em exceções capturáveis e registráveis em log, em vez de continuar silenciosamente com um corpo de resposta malformado.
  • Retorne apenas o id. O id da tarefa é o contrato entre envio e polling. Manter o restante da resposta fora do código chamador torna a próxima seção mais fácil de escrever.

Confirme o nome real do campo de resposta na documentação de referência da hiapi e ajuste data["job_id"] accordingly — a nomenclatura de campos é o ponto mais provável de divergir dos exemplos deste artigo.

Fazendo polling do status de conclusão da tarefa

A geração leva tempo. Faça polling em intervalos fixos, pare em estados terminais e eventualmente desista.

import time


def wait_for_job(job_id: str, timeout: float = 300, interval: float = 3) -> dict:
    deadline = time.monotonic() + timeout
    while time.monotonic() < deadline:
        response = requests.get(
            f"{HIAPI_BASE_URL}/jobs/{job_id}",
            headers={"Authorization": f"Bearer {HIAPI_API_KEY}"},
            timeout=30,
        )
        response.raise_for_status()
        job = response.json()

        status = job["status"]
        if status == "succeeded":
            return job
        if status == "failed":
            raise RuntimeError(f"Job {job_id} failed: {job.get('error')}")

        time.sleep(interval)
    raise TimeoutError(f"Job {job_id} did not finish within {timeout}s")

As partes menos óbvias:

  • Três resultados, não dois. Pendente, sucesso, falha. Trate qualquer status não reconhecido como pendente e registre uma linha de log, para que estados recém-adicionados não derrubem o worker.
  • Um único prazo para toda a espera. O prazo baseado em time.monotonic() não é afetado por ajustes de relógio, ao contrário da aritmética com horário de parede.
  • Não faça requisições com muita frequência. Para geração de imagens, alguns segundos entre verificações é suficiente. Se precisar fazer polling mais rápido, recue entre tentativas em vez de encurtar o intervalo.
  • Force um timeout. Uma tarefa que nunca termina deve se manifestar como um erro que possa gerar alerta, e não como um loop que roda até o contêiner ser morto.

Se você executar muitas tarefas, envie em lote e faça polling de forma concorrente — usando um event loop ou pool de threads com intervalos escalonados — em vez de criar um poller por tarefa em loop apertado.

Baixando e salvando a saída

Uma tarefa concluída fornece uma referência de imagem, normalmente uma URL. Baixe-a prontamente, pois esses links podem ter prazo de validade.

def save_image(job: dict, path: str) -> None:
    url = job["output"]["image_url"]
    for attempt in range(3):
        try:
            with requests.get(url, stream=True, timeout=60) as r:
                r.raise_for_status()
                with open(path, "wb") as f:
                    for chunk in r.iter_content(chunk_size=8192):
                        f.write(chunk)
            return
        except requests.RequestException:
            if attempt == 2:
                raise
            time.sleep(2 ** attempt)

Práticas que valem a pena adotar em produção:

  • Baixe em streaming. As imagens geradas não são pequenas; carregá-las inteiramente em memória sem motivo é desperdício.
  • Grave em um caminho temporário e depois renomeie. Uma falha no meio da escrita não deve deixar um arquivo truncado onde o pipeline espera uma imagem válida.
  • Repita o download, não a geração. Repetir uma busca instável em um bucket é barato; desperdiçar uma geração não é. Limite o número de tentativas e use backoff exponencial.
  • Persista o id da tarefa junto com o arquivo. Quando alguém perguntar de onde veio a imagem, a resposta deve exigir uma única consulta, não uma varredura nos logs.

Para armazenamento de objetos, substitua open() pelo upload em streaming do seu SDK e mantenha a mesma estrutura de retentativas.

Erros, retentativas e verificação de razoabilidade de custos

Os modos de falha que você encontrará primeiro e como tratar cada um:

  • 401 / erro de autenticação — chave ausente, com erro de digitação ou não exportada no shell que executa o script. Verifique o ambiente antes de mexer no payload.
  • Erro de validação 4xx — geralmente id de modelo com erro de digitação, prompt ausente ou referência de estilo malformada. Registre o corpo da resposta literalmente; as mensagens de validação são o caminho mais rápido para a correção aqui.
  • 429 / limite de taxa — use backoff com jitter, não retentativa imediata. Uma fila antes da função de envio é melhor do que uma tempestade de retentativas.
  • Timeout de tarefa — o prazo de polling foi atingido. Decida deliberadamente se deve reenviar; reenviar cegamente dobra o gasto sem aumentar a taxa de sucesso.
  • Erro de rede transitório — repita envios e downloads com backoff exponencial limitado. Repita downloads com liberdade; repita gerações com cautela.

Disciplina de custos, na prática:

  • A cobrança acompanha o trabalho que o modelo realmente executa, portanto tarefas com falha e lotes abandonados são custos ocultos. Registre cada envio com o hash do prompt e o id da tarefa para contabilizar o uso depois.
  • Itere com os prompts mais baratos possíveis. Ajuste a redação e as referências de estilo em execuções pequenas e rápidas, antes de investir em lotes grandes.
  • Desduplique. Se o mesmo prompt e conjunto de estilos for solicitado duas vezes, sirva o resultado da primeira vez a partir do seu próprio cache.
  • Adicione um limite rígido de concorrência no worker. É mais fácil aumentar o limite do que explicar uma fatura inesperada.

Com envio, polling e salvamento como três funções independentes e testáveis, o endpoint se encaixa de forma limpa em qualquer pipeline. Para os nomes exatos de campos, estados e preços atuais, consulte a página do modelo recraft-v4-styles-pro/text-to-image na hiapi antes da integraçã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