HiAPI
Blogue

Tutorial

Tutorial da API recraft-v4-styles/text-to-image: curl, Python e polling assíncrono

Um passo a passo completo de requisição para geração de imagens com referência de estilo no HiAPI

Oct 31, 2026
深蓝底色上铜色细分平行线构成几何带状图案,呼应异步轮询主题的博客封面图

O que o recraft-v4-styles/text-to-image pode fazer por você

recraft-v4-styles/text-to-image é um endpoint de geração de imagens com referência de estilo. Você fornece a ele um prompt de texto descrevendo o que deseja ver, além de uma ou mais imagens de referência que descrevem a aparência do estilo. O modelo combina os dois: o prompt carrega o conteúdo e a intenção de composição, as imagens de referência carregam o estilo visual.

Essa distinção é importante ao escolher o endpoint. Quando a aparência pode ser totalmente expressa em palavras — como "uma ilustração vetorial plana de uma xícara de café, duas cores, contorno grosso" — a geração de imagem apenas com prompt é a ferramenta correta. No entanto, no trabalho real de produto, a maioria dos cenários envolve uma aparência de marca difícil de descrever, mas fácil de mostrar. Um key visual existente, um render previamente aprovado ou uma amostra de design system define a especificação de estilo com muito mais precisão do que um parágrafo de adjetivos. É exatamente essa lacuna que este endpoint preenche.

Do ponto de vista do desenvolvedor, pense nele como uma transformação de duas entradas: prompt + referência de estilo -> imagem. Tudo na integração decorre desse formato. Você não está apenas serializando uma string, mas montando um pequeno payload com várias partes, no qual as imagens de referência são entradas de primeira classe. Seu código de construção de requisição deve tratá-las assim, e sua camada de validação deve rejeitar, antes que a tarefa saia do seu serviço, aquelas que tenham apenas prompt e nenhuma referência de estilo utilizável.

O endpoint é assíncrono. Enviar a requisição retorna uma tarefa, então você faz polling dessa tarefa e, por fim, a imagem chega como uma URL, não como bytes inline. Esse é um design deliberado para cargas de trabalho de imagem: a geração leva tempo suficiente para que manter uma conexão HTTP aberta seja desperdício e frágil. Uma vez que você aceita o ciclo "enviar-consultar-baixar", o restante da integração é trabalho comum de encanamento de API.

Anatomia de uma requisição que funciona

Antes de escrever qualquer código, organize os campos em grupos. Uma requisição recraft-v4-styles/text-to-image tem três partes lógicas.

O prompt

O prompt é sua instrução de conteúdo. Escreva-o em torno do que deve estar na imagem — sujeito, composição, enquadramento, quantidade de objetos, tratamento do fundo. Evite gastar o orçamento do prompt em adjetivos de estilo que as imagens de referência já comunicam; o conflito de sinais entre prompt e referência tende a produzir resultados ambíguos. Mantenha o prompt curto, específico e testável.

As entradas de referência de estilo

Esta é a parte que distingue o endpoint de uma chamada comum de geração de imagem por texto. As referências de estilo são imagens fornecidas junto com o prompt para definir a linguagem visual. Ao montá-las, trate-as como um conjunto curado, não como um monte de imagens desorganizadas:

  • Consistência vale mais que quantidade. Algumas referências que compartilham a mesma aparência coerente ensinam mais ao modelo do que muitas referências com estilos divergentes.
  • Resolução e enquadramento importam. As referências devem representar a saída que você deseja, não miniaturas ou fragmentos severamente cortados.
  • Elas precisam ser acessíveis. Se suas referências forem passadas como URLs, essas URLs precisam ser publicamente acessíveis no momento da requisição. Um link assinado que expira em sessenta segundos fará com que tarefas lentas falhem.

Mantenha seu conjunto de referências em configuração, não espalhado pelo código, para que você possa versioná-lo junto com os ativos de marca.

As opções de saída

Os campos restantes descrevem o artefato que você quer de volta — são botões que afetam a imagem retornada, não seu conteúdo. Os nomes exatos dos parâmetros e os valores aceitos estão listados na página de referência do endpoint; leia lá em vez de adivinhar, e centralize-os em um único lugar no código, para que uma mudança de especificação toque apenas um arquivo.

Um hábito útil: construa o corpo JSON como um dicionário/objeto na linguagem escolhida, registre-o uma vez em nível de debug na primeira execução e inspecione visualmente sua estrutura antes de culpar o modelo por um resultado ruim.

Chamando com curl

Comece com curl. Ele remove toda abstração de biblioteca entre você e o formato de rede, então, se a requisição estiver errada, você descobre imediatamente.

O envio é uma requisição POST com corpo JSON e cabeçalho de autenticação contendo sua chave de API do HiAPI:

curl -sS -X POST "https://api.hiapi.ai/v1/recraft-v4-styles/text-to-image" \
  -H "Authorization: Bearer $HIAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "prompt": "a ceramic coffee cup on a linen tablecloth, soft daylight",
    "style_references": [
      "https://your-cdn.example.com/style/ref-01.png"
    ]
  }'

Algumas observações sobre o que você vê:

  • Mantenha a chave em uma variável de ambiente ($HIAPI_API_KEY), nunca inline no histórico do shell ou em um script commitado.
  • O payload de -d é JSON puro. Regras de aspas no shell são uma fonte comum de problemas — se você encontrar erro de parsing, ecoe o corpo em um arquivo e use -d @body.json.
  • Os nomes de campo mostrados aqui seguem a anatomia da seção anterior; antes de publicar, confirme os nomes exatos e as opções de saída aceitas na página de referência do endpoint.

A resposta não é uma imagem. É uma confirmação de tarefa: um identificador da geração que você acabou de enfileirar e um campo de status informando que ela ainda não terminou. Leia o corpo da resposta com atenção na primeira execução e anote o nome do campo que guarda o ID da tarefa — essa string é o handle para tudo que você fizer depois. Guarde-a. Se sua primeira resposta contiver um objeto de erro, pare e corrija a requisição; consultar um ID que você nunca recebeu é o beco sem saída mais comum.

Implementando a mesma requisição em Python

Porte a chamada curl para Python uma vez e você terá um primitivo reutilizável. O exemplo abaixo usa requests e espelha o corpo da requisição exatamente.

import os
import requests

API_KEY = os.environ["HIAPI_API_KEY"]
BASE_URL = "https://api.hiapi.ai/v1"

HEADERS = {
    "Authorization": f"Bearer {API_KEY}",
    "Content-Type": "application/json",
}

STYLE_REFERENCES = [
    "https://your-cdn.example.com/style/ref-01.png",
]

def submit_generation(prompt: str) -> dict:
    body = {
        "prompt": prompt,
        "style_references": STYLE_REFERENCES,
    }
    resp = requests.post(
        f"{BASE_URL}/recraft-v4-styles/text-to-image",
        headers=HEADERS,
        json=body,
        timeout=30,
    )
    resp.raise_for_status()
    return resp.json()

if __name__ == "__main__":
    job = submit_generation(
        "a ceramic coffee cup on a linen tablecloth, soft daylight"
    )
    print(job)

Ao ajustar este código, vale manter duas escolhas de design:

  • Sempre defina timeout. O envio deve retornar rápido; se ele travar, você quer uma exceção, não um processo preso.
  • Retorne o JSON parseado, não o objeto de resposta. O código downstream deve depender do payload da tarefa, não das entranhas do requests. Isso torna trivial trocar a camada de transporte depois.

Como acima, defina o conjunto de referências no nível de módulo ou de configuração. Quando a aparência da marca evoluir, você atualiza apenas uma lista, sem procurar nos pontos de chamada. E mantenha a construção do corpo dentro de uma única função, para que qualquer campo exigido pelo endpoint seja adicionado em um só lugar.

Consultando o resultado assíncrono

A geração é assíncrona, então a tarefa que você enviou passa por vários estados até terminar. Seu cliente precisa de um laço de espera que verifique o estado, faça backoff entre verificações e, por fim, desista.

import time

def wait_for_result(job_id: str, timeout_s: int = 300, interval_s: float = 3.0) -> dict:
    deadline = time.monotonic() + timeout_s
    delay = interval_s
    while time.monotonic() < deadline:
        resp = requests.get(
            f"{BASE_URL}/recraft-v4-styles/text-to-image/{job_id}",
            headers=HEADERS,
            timeout=30,
        )
        resp.raise_for_status()
        data = resp.json()
        status = data.get("status")
        if status in ("succeeded", "failed"):
            return data
        time.sleep(delay)
        delay = min(delay * 1.5, 15.0)
    raise TimeoutError(f"job {job_id} did not finish in {timeout_s}s")

Neste laço, o que importa:

  • Trate estados desconhecidos como pendentes. Compare com estados terminais explícitos, não com uma allowlist de estados em andamento; se a plataforma adicionar um estado intermediário, seu laço continua esperando em vez de quebrar.
  • Faça backoff. Consultar a cada segundo por cinco minutos é cinco minutos de requisições desperdiçadas. Comece com um intervalo pequeno, multiplique e defina um teto.
  • Limite o tempo de espera. Todo laço precisa de um prazo final, e o prazo final deve se manifestar como uma exceção que o chamador saiba tratar.
  • Ramifique no fracasso. Estados terminais de falha trazem informação de diagnóstico. Registre o corpo completo da resposta — é a diferença entre "quebrou" e "a URL de referência retornou 403".

Se você processa muitas imagens, não fique dormindo dentro do handler de requisição web. Envie, persista o ID da tarefa e deixe um worker em background ou tarefa agendada conduzir o polling. A página de referência do endpoint documenta os valores exatos de status e o caminho de polling; consulte-a sempre que atualizar seu cliente.

Baixando e armazenando a saída

Quando a tarefa chega a um estado terminal de sucesso, a resposta contém a URL da imagem gerada. Essa URL é o ponto de entrega entre a API e sua camada de armazenamento.

Busque-a como bytes e grave onde precisar:

def download_image(url: str, dest_path: str) -> None:
    resp = requests.get(url, timeout=60)
    resp.raise_for_status()
    with open(dest_path, "wb") as f:
        f.write(resp.content)

Para qualquer cenário além de experimentação local, não deixe o artefato apenas na URL retornada. Trate a imagem gerada como um ponteiro temporário e copie-a para armazenamento que você controla — bucket de object storage, origem do seu CDN ou pipeline de mídia. Por três motivos:

  1. Ciclo de vida. As URLs de saída geradas não têm garantia de persistência indefinida. Baixar novamente de uma URL obsoleta durante uma retentativa é uma falha silenciosa em potencial.
  2. Chaves estáveis. Sua aplicação precisa de um identificador determinístico que caiba em uma linha de banco de dados, não de uma URL que muda a cada regeneração.
  3. Procedência. Armazenar o prompt, a versão do conjunto de referências de estilo e o ID da tarefa junto com a imagem permite reproduzir ou auditar qualquer ativo depois. Mantenha esses metadados em um registro companheiro ou coluna de banco de dados.

Ao enviar para object storage, transmita o corpo da resposta em streaming em vez de bufferizar a imagem inteira em memória, e defina o content type a partir dos cabeçalhos da resposta. Se você entrega imagens aos clientes pelo seu próprio CDN, este também é o ponto para aplicar cabeçalhos de cache.

Solução de problemas na primeira execução

A maioria das primeiras tentativas falha de algumas formas previsíveis. Verifique-as em ordem.

O corpo da requisição é rejeitado

Erros da classe 400 geralmente significam JSON malformado ou falta de campos obrigatórios. Execute primeiro a versão curl e inspecione o corpo exato que você está enviando. Problemas comuns: aspas do shell quebrando o JSON, enviar como string um campo que a API espera como array, ou um valor de opção de saída fora do intervalo aceito. A página de referência do endpoint é a fonte autoritativa para nomes e valores de campo — compare seu corpo com ela literalmente.

Você tem prompt, mas nenhuma referência de estilo utilizável

O endpoint é construído em torno da referência de estilo. Se sua requisição contém prompt, mas as referências estão vazias, inacessíveis ou retornam erro de autenticação ao serem buscadas, a tarefa será rejeitada ou produzirá saída que ignora a aparência pretendida. Valide cada URL de referência buscando-a com o mesmo cliente sem credenciais que a plataforma usaria. Referências que exigem cookie de sessão ou query string assinada devem ser consideradas quebradas.

Você nunca recebeu um ID de tarefa

A resposta de envio é uma confirmação, não uma imagem. Se você escreveu código que espera bytes da imagem na primeira resposta, ele falhará em todas as execuções. Faça o parse da resposta, extraia o ID da tarefa e só então comece o polling. Registre a resposta completa de envio nas primeiras execuções para enxergar seu formato.

Você está consultando com muita frequência

Centenas de verificações de status em um minuto não farão a tarefa terminar mais rápido e são mais propensas a disparar limites de taxa. Use intervalos crescentes com teto e um único worker por tarefa. Se você despacha muitas tarefas, adicione um limite modesto de concorrência para que uma rajada de envios não vire uma rajada de polling.

A tarefa termina, mas o download falha

Um 403 ou 404 ao buscar a URL de saída geralmente significa que a URL expirou, ou que a tarefa falhou após uma verificação de status que você interpretou mal. Confirme que o estado terminal é de sucesso e releia a resposta para obter o campo de saída real. Armazene o artefato assim que ele estiver disponível, em vez de adiar o download.

Ao resolver esses problemas na ordem em que o pipeline roda — envio, polling, download — as falhas da primeira execução quase sempre se resolvem em correções óbvias. A referência do endpoint e seu esquema de requisição são a forma mais rápida de confirmar qualquer dúvida em nível de campo.

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