HiAPI
Blogue

Tutorial

Como usar o nano-banana-pro pela API do HiAPI: exemplos com curl e Python

Oct 31, 2026
平面流体形态层叠交错的封面图,墨色底上流动着青瓷绿与石板灰的波纹,呼应教程主题。

O que o nano-banana-pro no HiAPI oferece

O nano-banana-pro é um modelo de geração de imagens que pode ser chamado por meio da API unificada do HiAPI. Em vez de integrar diretamente com o provedor do modelo, basta enviar ao HiAPI uma requisição no formato unificado para obter as imagens geradas — usando a mesma autenticação, as mesmas convenções de endpoint e o mesmo envelope de resposta que os demais modelos da plataforma.

O nano-banana-pro foi projetado para geração de imagens orientada por prompt e permite anexar imagens de referência além do prompt de texto. As imagens de referência permitem guiar a saída com contexto visual (sujeito, estilo, composição), sem precisar descrever tudo em palavras. A saída é entregue em resolução 2K, o que torna o modelo mais adequado para ativos de produção do que para rascunhos rápidos.

Ao concluir este tutorial, você terá uma integração completa e funcional que pode:

  • enviar um prompt ao nano-banana-pro pelo HiAPI com uma requisição curl validada;
  • reproduzir a mesma chamada em Python sem alterar o payload da requisição;
  • anexar imagens de referência à requisição;
  • submeter tarefas assíncronas, fazer polling até a conclusão e tratar tentativas de repetição de forma sensata;
  • baixar a imagem 2K concluída e armazená-la na sua própria infraestrutura.

Cada seção se apoia na anterior, então o caminho mais seguro é seguir em ordem: primeiro confirmar a requisição manualmente, depois movê-la para o código.

Antes de enviar a primeira requisição

Você precisa de três coisas antes da primeira chamada.

Uma chave de API

Crie uma chave de API na sua conta HiAPI e garanta que ela não seja incluída no controle de versão. Trate-a como qualquer outro segredo: carregue-a de uma variável de ambiente (HIAPI_API_KEY) ou de um gerenciador de segredos, e nunca a codifique diretamente em arquivos que você possa commitar. Se a chave vazar, rotacione-a no painel em vez de tentar removê-la do histórico.

Um cliente HTTP

Qualquer ferramenta capaz de enviar requisições HTTPS serve. Para a primeira requisição, o curl na linha de comando é ideal, porque não há framework entre você e a rede — cada cabeçalho e cada byte do corpo da resposta ficam visíveis. Para a parte em Python, a biblioteca padrão urllib.request é suficiente; se você já usa requests ou httpx, o mapeamento é o mesmo. Este tutorial limita o Python à biblioteca padrão, então não é necessário instalar nada extra.

Um local para armazenar a saída

Como as tarefas do nano-banana-pro são assíncronas, planeje desde o início o diretório ou bucket em que as imagens concluídas serão salvas. Durante o desenvolvimento, uma pasta local output/ basta; em produção, mire em armazenamento de objetos.

Você não precisa instalar SDK de fornecedor. O HiAPI é chamado por HTTPS comum, então a requisição que você monta no curl é exatamente a mesma que seu cliente Python enviará depois.

Uma requisição curl funcional, explicada passo a passo

A forma mais rápida de confirmar que a chave, o endpoint e o payload estão corretos é enviar uma requisição manualmente. Antes de digitá-la, decomponha-a em partes.

Endpoint e método

Todas as chamadas de modelo vão para a mesma URL base do HiAPI, e o modelo é identificado no corpo da requisição, não no caminho. Requisições de geração usam POST.

Cabeçalhos

Três cabeçalhos importam em cada chamada:

  • Authorization: Bearer $HIAPI_API_KEY — sua chave, passada como token bearer.
  • Content-Type: application/json — para requisições contendo apenas prompt.
  • Accept: application/json — para receber uma resposta estruturada em vez de uma página de erro HTML.

Corpo da requisição

O corpo JSON carrega o nome do modelo e os parâmetros de geração. No mínimo, envie o identificador do modelo e seu prompt:

curl -sS -X POST "$HIAPI_BASE_URL" \
  -H "Authorization: Bearer $HIAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "model": "nano-banana-pro",
    "input": {
      "prompt": "a glass terrarium on a sunlit windowsill, soft morning light, shallow depth of field"
    }
  }'

Antes de executar este comando, defina HIAPI_BASE_URL e HIAPI_API_KEY no shell. Guardar a URL em uma variável significa que depois você pode apontar o mesmo script para uma URL de staging ou sandbox sem alterar o comando.

Ler a resposta

Uma submissão bem-sucedida retorna um objeto JSON que identifica a tarefa. O campo importante é o identificador da tarefa — você o usará na etapa de polling. Como a geração leva tempo, não espere receber a imagem em si na primeira resposta; o nano-banana-pro opera de forma assíncrona, e esta chamada é apenas a parte de submissão da interação.

Se o comando retornar erro, pare aqui e corrija antes de escrever qualquer código. A requisição curl validada é sua implementação de referência: cada etapa seguinte deve produzir a mesma requisição HTTP.

Portar a requisição para Python

O porte é mecânico: URL, método, cabeçalhos e corpo JSON permanecem iguais. Apenas o cliente muda.

A mesma requisição com urllib

import json
import os
import urllib.request

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

payload = {
    "model": "nano-banana-pro",
    "input": {
        "prompt": "a glass terrarium on a sunlit windowsill, soft morning light, shallow depth of field"
    },
}

request = urllib.request.Request(
    base_url,
    data=json.dumps(payload).encode("utf-8"),
    method="POST",
    headers={
        "Authorization": f"Bearer {api_key}",
        "Content-Type": "application/json",
        "Accept": "application/json",
    },
)

with urllib.request.urlopen(request, timeout=60) as response:
    body = json.loads(response.read().decode("utf-8"))

print(body)

Regras de mapeamento

Ao converter do curl, três detalhes costumam causar erros:

  1. O corpo deve ser bytes. json.dumps gera uma string; ela precisa ser codificada antes de ser passada ao objeto de requisição.
  2. Cabeçalhos são um dicionário, não flags. Cada linha -H vira um par chave/valor. Preserve o prefixo Bearer e o espaço depois dele.
  3. O método deve ser especificado explicitamente. Quando há dados, urllib.request usa POST por padrão, mas definir method="POST" torna a intenção mais clara e evita surpresas se você remover o corpo depois.

Se você usa requests, o equivalente é requests.post(base_url, headers=headers, json=payload, timeout=60) — json= cuida da serialização e do tipo de conteúdo para você. Se você usa httpx, a forma da chamada é a mesma.

Uma pequena função auxiliar que vale a pena ter

Coloque a chamada de submissão em uma função que recebe um prompt e retorna o identificador da tarefa. Cada seção seguinte — imagens de referência, polling, download — se apoia nessa função, e mantê-la em um só lugar significa que mudanças na forma da requisição acontecem apenas uma vez.

Enviar imagens de referência junto com o prompt

Imagens de referência mudam a forma da requisição, então decida cedo qual modo de entrada sua aplicação vai usar.

Duas opções práticas

Entrada baseada em URL. Se a imagem de referência já estiver acessível via HTTPS, você pode incluir a URL dela junto com o prompt no corpo da requisição. Isso mantém a requisição como application/json, que é a forma mais fácil de repetir e registrar.

Upload de arquivo. Se a imagem estiver no cliente ou em armazenamento privado, você pode enviá-la como parte de arquivo em uma requisição multipart/form-data. Nesse caso, o cabeçalho Content-Type: application/json é substituído pelo tipo de conteúdo multipart — deixe seu cliente HTTP gerá-lo para garantir que o boundary esteja correto — e os campos JSON passam a ser campos de formulário na mesma requisição.

Para a maioria das integrações no lado do servidor, a entrada baseada em URL é mais simples: suas imagens já estão no armazenamento de objetos, a requisição permanece JSON e você evita enviar corpos grandes duas vezes ao repetir tentativas.

Mantenha o prompt e a imagem de referência em sincronia

O prompt deve descrever o propósito da imagem de referência, não apenas o conteúdo dela. “Combine a iluminação e a paleta da imagem de referência; troque o sujeito por um vaso de cerâmica” dá ao modelo uma tarefa clara. Um prompt que ignora a imagem de referência desperdiça a entrada.

Valide antes de enviar

Imagens de referência são a fonte mais comum de erros de requisição. Verifique se a URL é acessível publicamente (ou se ambos os lados do seu sistema concordam com o prazo de expiração de URLs assinadas), se o tipo de arquivo é aceito pelo modelo e se a imagem não é grande a ponto de causar timeout de upload. Faça essas verificações no seu próprio código primeiro — depurar uma validação que falha no cliente custa muito menos do que depurar uma requisição rejeitada.

Tratar tarefas assíncronas e fazer polling de resultados

A geração do nano-banana-pro é assíncrona. Estruture seu cliente em torno de três etapas independentes: submeter, fazer polling e baixar. Misturá-las em uma única função torna difícil raciocinar sobre tentativas de repetição e timeouts.

Etapa 1: submeter

Envie a requisição acima e armazene o identificador de tarefa retornado. Persista esse identificador em algum lugar durável — uma linha de banco de dados ou uma mensagem de fila — porque seu processo pode reiniciar entre a submissão e a conclusão.

Etapa 2: polling

Use a mesma URL base e o mesmo cabeçalho Authorization, incluindo o identificador da tarefa na requisição, para consultar o status da tarefa. Faça polling em intervalos em vez de um loop apertado; alguns segundos entre verificações é o típico, e se várias verificações consecutivas retornarem estado pendente, aplique backoff.

import time

TERMINAL = {"succeeded", "failed"}

def wait_for_job(job_id, timeout=300, interval=3):
    deadline = time.monotonic() + timeout
    while time.monotonic() < deadline:
        status = get_job_status(job_id)  # same headers as submit
        if status in TERMINAL:
            return status
        time.sleep(interval)
    raise TimeoutError(f"job {job_id} did not finish in time")

Etapa 3: respeitar os estados

Trate o campo de status como um enum. A tarefa ou ainda está em execução, ou foi concluída com sucesso, ou falhou. Trate explicitamente os três casos: em caso de sucesso, siga para o download; em caso de falha, leia a mensagem de erro e determine se o problema está na entrada ou no prompt; em caso de timeout, pare o polling e exponha o identificador da tarefa para investigação posterior.

Tentativas de repetição pertencem a dois níveis

Tentativas de repetição em nível de rede devem ser aplicadas à chamada de submissão e a cada requisição de polling, com um número limitado de tentativas. Tentativas no nível da tarefa são diferentes: se a tarefa falhou por causa de um prompt ruim ou de uma imagem de referência ruim, reenviar o mesmo payload falhará da mesma forma. Só repita a tarefa em si depois de alterar a entrada.

Um padrão comum em produção é ter um worker responsável pelo loop de polling, para que as requisições web nunca fiquem bloqueadas pela geração. Submeta a partir do seu handler de API, entregue o identificador da tarefa ao worker e notifique o cliente quando o worker terminar.

Baixar e armazenar a saída 2K

A resposta final da tarefa aponta para a imagem gerada em vez de embuti-la, o que significa que o download é uma etapa sob sua responsabilidade.

Obter a imagem

Quando a tarefa reporta sucesso, a resposta contém a localização da saída. Recupere-a com uma requisição GET comum e grave os bytes em um arquivo ou faça streaming para o armazenamento. Durante o desenvolvimento, salve em um diretório local com um nome previsível construído a partir do identificador da tarefa, para associar o arquivo ao registro da tarefa.

import pathlib
import urllib.request

def save_image(url, job_id, out_dir="output"):
    pathlib.Path(out_dir).mkdir(exist_ok=True)
    target = pathlib.Path(out_dir) / f"nano-banana-pro-{job_id}.png"
    with urllib.request.urlopen(url, timeout=60) as response:
        target.write_bytes(response.read())
    return target

Armazenar corretamente

Em produção, faça streaming da resposta diretamente para o armazenamento de objetos em vez de gravar em disco local, para que o comportamento seja consistente independentemente do worker que processa a tarefa. Registre no banco de dados a chave do objeto e o identificador da tarefa, e verifique se o tipo de conteúdo e a extensão do arquivo correspondem ao que o modelo gera. Se a imagem for servida em páginas web, gere miniaturas no mesmo pipeline, para que páginas públicas nunca carreguem o arquivo completo em resolução 2K.

Planeje uma política de retenção

As saídas geradas são seus dados. Decida por quanto tempo retê-las, se precisam de versionamento e se o local final é algo que sua aplicação consegue regenerar se for perdido. Se a resposta for não, armazene também o payload da requisição junto com a imagem, para que um bug futuro ou uma mudança de modelo nunca impeça a reprodução do resultado.

Pontos comuns de falha e como depurar

A maioria das primeiras integrações falha por alguns poucos motivos. Antes de assumir que há um problema no modelo, percorra esta lista.

  • Erros de autorização. Falta o prefixo Bearer , a chave tem uma quebra de linha final por ter sido copiada de um arquivo de ambiente, ou você está usando uma chave de um ambiente diferente daquele da URL base configurada.
  • Incompatibilidade de tipo de conteúdo. Enviar campos JSON com cabeçalho de requisição multipart, ou enviar um arquivo com application/json, é a causa mais comum de rejeição de requisições com imagem de referência. Para corpos multipart, deixe o cliente definir o cabeçalho.
  • Método ou forma de corpo errados. Usar GET em vez de POST, ou usar um prompt no nível superior em vez do objeto aninhado input, produz erros de validação que parecem completamente sem relação. Compare sua requisição byte a byte com a chamada curl validada — curl -v mostra os cabeçalhos realmente enviados.
  • Polling rápido demais ou inexistente. Requisitar o endpoint de status com muita frequência causa limitação de taxa; nunca fazer polling não traz resultado nenhum. Use um intervalo fixo com backoff e um timeout rígido.
  • URL de saída expirada. Se você esperar demais entre a conclusão da tarefa e o download, a URL de saída assinada pode expirar. Baixe imediatamente após o sucesso, ou tenha um caminho de reaquisição para obter uma nova localização.
  • Falhas silenciosas no código. Registre sempre o status HTTP e o corpo da resposta em caso de erro. Mensagens de exceção genéricas lançadas pelo cliente HTTP escondem a parte útil da resposta.

Quando algo não estiver claro, volte para a requisição curl validada da primeira seção. Se ela funciona e sua chamada em Python não, a diferença entre as duas é o bug.

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