Tutorial
Como usar gpt-6.1-terra pela API HiAPI: curl, Python e uma requisição funcional
O que uma requisição gpt-6.1-terra realmente exige
Cada chamada a gpt-6.1-terra na HiAPI se resume a quatro coisas: uma URL, um cabeçalho de autenticação, o identificador do modelo e o corpo da requisição. Acerte esses pontos e o restante deste artigo será apenas encanamento.
O endpoint
Todas as chamadas de modelo partem da mesma URL base na HiAPI. Você não precisa alternar de host para cada modelo — é o nome do modelo no corpo da requisição que roteia a chamada. Aponte seu cliente para a URL base da HiAPI e guarde-a em uma variável, assim você só precisa alterá-la em um lugar.
O cabeçalho de autenticação
A autenticação é feita passando um bearer token no cabeçalho Authorization. Esse token é a chave de API emitida na sua conta HiAPI. Nunca a codifique diretamente nos arquivos-fonte; leia-a de uma variável de ambiente (por exemplo, HIAPI_API_KEY), assim o mesmo código funciona no local, no CI e em produção.
O identificador do modelo
O corpo da requisição deve especificar o modelo explicitamente: "model": "gpt-6.1-terra". Essa string diferencia maiúsculas de minúsculas e precisa corresponder exatamente. Um nome de modelo errado ou truncado é uma das causas mais comuns de requisições rejeitadas, portanto trate-o como uma constante no código, e não como uma string escrita de qualquer jeito.
Os campos do corpo da requisição
Uma requisição carrega no mínimo o modelo e o conteúdo de entrada — o prompt ou as mensagens que você quer que o modelo processe. Sobre esse núcleo, você pode adicionar quaisquer parâmetros opcionais suportados pelo modelo (dicas de formato de saída, controle de comprimento etc.), mas comece pelo corpo mínimo que já produz uma resposta válida. Um corpo mínimo é mais fácil de depurar do que um corpo completo e ajuda a determinar se a falha está no seu corpo ou no encanamento.
Há um ponto estrutural que vale internalizar desde já: algumas respostas são retornadas inline, outras voltam como tarefas que você precisa consultar. Veremos mais adiante como distinguir as duas, mas desde já projete sua camada de requisição para que o tratamento de resposta possa alternar entre os dois modos sem reescrita.
Uma requisição curl funcional, linha por linha
A seguir está um exemplo completo de chamada que pode ser colado no terminal após exportar a chave. Ele usa a URL base da HiAPI e um corpo JSON mínimo.
curl -sS -X POST "$HIAPI_BASE_URL/v1/chat/completions" \
-H "Authorization: Bearer $HIAPI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-6.1-terra",
"messages": [
{"role": "user", "content": "Resuma o ciclo da água em três frases."}
]
}'
O que cada flag faz
-X POST define o método HTTP. As chamadas de modelo são POST porque carregam um corpo.
-sS faz o curl ocultar informações de progresso, mas ainda exibir erros reais. Sem -S, uma requisição falha pode parecer apenas silêncio.
-H "Authorization: Bearer $HIAPI_API_KEY" anexa suas credenciais. O prefixo Bearer e o único espaço que o segue fazem parte do esquema de autenticação; omitir qualquer um dos dois causa falha de autenticação que parece não ter relação com o cabeçalho.
-H "Content-Type: application/json" informa ao servidor que o corpo é JSON. Alguns gateways toleram a ausência do content type, mas não dependa disso.
-d '...' é o corpo da requisição. As aspas simples impedem que o shell interpole o JSON. Se preferir usar um arquivo, substitua -d '...' por -d @payload.json e coloque o JSON em um arquivo que possa passar por lint e diff.
Dois hábitos que economizam tempo
Primeiro, quando ocorrer uma falha, adicione -i para imprimir a linha de status e os cabeçalhos da resposta. Uma resposta com status 200 mas corpo anômalo se lê de forma completamente diferente de um 401 ou 422, e você vai querer ver essa distinção imediatamente. Segundo, passe a saída por um formatador JSON (curl ... | python -m json.tool) para que os campos aninhados da resposta fiquem legíveis. Essas duas flags não têm efeitos colaterais e você as usará com frequência ao ajustar chamadas.
Portando a chamada para Python
A versão em Python deve preservar a semântica exata da chamada curl: mesma URL, mesmos cabeçalhos, mesmo corpo, mesma forma de parse. Usar a biblioteca padrão mantém as dependências em zero e torna o porte transparente.
import json
import os
import urllib.request
HIAPI_BASE_URL = os.environ["HIAPI_BASE_URL"].rstrip("/")
HIAPI_API_KEY = os.environ["HIAPI_API_KEY"]
def call_terra(prompt: str, model: str = "gpt-6.1-terra") -> dict:
body = {
"model": model,
"messages": [{"role": "user", "content": prompt}],
}
req = urllib.request.Request(
f"{HIAPI_BASE_URL}/v1/chat/completions",
data=json.dumps(body).encode("utf-8"),
headers={
"Authorization": f"Bearer {HIAPI_API_KEY}",
"Content-Type": "application/json",
},
method="POST",
)
with urllib.request.urlopen(req, timeout=120) as resp:
return json.loads(resp.read().decode("utf-8"))
result = call_terra("Resuma o ciclo da água em três frases.")
print(json.dumps(result, indent=2))
Notas sobre o porte
Os cabeçalhos são construídos de uma vez dentro do objeto de requisição, correspondendo às duas flags -H. O corpo é um dict Python, serializado com json.dumps, o que é programaticamente equivalente ao corpo curl entre aspas simples — e elimina problemas de aspas no shell do Windows.
A função recebe o modelo como parâmetro com valor padrão, em vez de repetir o literal em todo lugar. Assim o nome do modelo tem uma única fonte de verdade, ao mesmo tempo que permite sobrescrevê-lo deliberadamente.
O tratamento de erros foi deliberadamente omitido aqui para manter o caminho feliz legível. Em código real, envolva a chamada urlopen e capture exceções de erro HTTP, lendo .read() do objeto de erro para ver a mensagem do servidor. O timeout é definido explicitamente; um bloqueio indefinido acabará travando um worker.
Se você preferir httpx ou requests, o mapeamento é um para um: requests.post(url, headers=..., json=body, timeout=120). O parâmetro json= serializa o dict para você. A semântica não muda em nada, e esse é justamente o ponto — a chamada curl é o contrato, e o Python é apenas a segunda forma de apresentá-lo.
Decidindo entre uma chamada única e uma tarefa assíncrona
Nem toda requisição é adequada para espera. A decisão depende de quanto tempo o trabalho leva e se o chamador pode arcar com o bloqueio.
Quando a chamada única é adequada
Requisições interativas curtas — resumos, classificações, reescritas pequenas — devem ser chamadas síncronas comuns. A resposta volta inline, você a interpreta e retorna. É o caminho de código mais simples e o mais fácil de raciocinar em testes. Se um usuário está esperando na UI, a forma síncrona é a esperada.
Quando tratar como tarefa
Quando o trabalho é longo ou gera muitos artefatos, e uma conexão interrompida significa refazer trabalho caro, trate a chamada como assíncrona. Nesses casos, você envia a requisição, recebe um identificador de tarefa e consulta até que ela atinja um estado terminal. O envio em si retorna rápido, de modo que seu worker ou handler HTTP não fica ocupado durante todo o processo.
Uma regra prática: se você se pegar definindo um timeout de cliente excepcionalmente longo para “fazer a chamada funcionar”, isso é sinal de que deve mudar para tarefas. Timeout não é mecanismo de agendamento.
Tornando a troca barata
Não divida a base de código em dois clientes não relacionados. Encapsule os dois caminhos atrás de uma única função que retorna um resultado imediato ou um handle de tarefa, e deixe o chamador pedir o modo que preferir. Assim, a construção da requisição — modelo, autenticação, corpo — permanece compartilhada, e só a estratégia de espera difere. Isso também significa que a depuração é consistente: com um corpo pequeno, você pode reproduzir uma falha assíncrona de forma síncrona.
Seja honesto quanto à sua carga de trabalho em vez de adivinhar o comportamento da plataforma. Se suas requisições normalmente terminam em segundos, mantenha o modo síncrono e evite a complexidade. O caminho assíncrono agrega valor em requisições realmente lentas, não em todas.
Consultando a conclusão sem bombardear a API
Um loop de polling tem três responsabilidades: esperar o suficiente para ser educado, parar eventualmente e apresentar estados terminais com clareza. A seguir, uma versão compacta.
import time
def poll_until_done(fetch_status, job_id, interval=3.0, timeout=600.0):
deadline = time.monotonic() + timeout
while True:
status = fetch_status(job_id)
state = status.get("status")
if state in ("succeeded", "failed", "cancelled"):
return status
if time.monotonic() > deadline:
raise TimeoutError(f"job {job_id} not finished after {timeout}s")
time.sleep(interval)
Por que essa estrutura
fetch_status é injetado, então o mesmo loop funciona quer você consulte via HTTP, quer contra uma fila interna. Isso também torna trivial testá-lo com um objeto falso que retorna running duas vezes e depois succeeded.
A verificação de estado é uma lista explícita de estados terminais, em vez de checar uma única string "done". Estados terminais variam — sucesso, falha, cancelamento — e você quer parar em qualquer um deles, não girar até o timeout por ter procurado apenas um.
O prazo usa time.monotonic(), para que ajustes no relógio de parede não estendam nem encurtem a espera por acidente.
Escolhendo o intervalo de polling
Comece com alguns segundos e resista ao impulso de fazer polling em loop apertado. Intervalos abaixo de um segundo consomem orçamento de requisições e aumentam a carga sem fazer a tarefa terminar mais rápido. Se você espera tarefas longas, considere um backoff suave — por exemplo, aumentar o intervalo a cada verificação até um teto. Mantenha o teto moderado; o objetivo é reduzir requisições, não criar pontos cegos de vários minutos.
Timeout não é opcional
Defina sempre um timeout, generoso em relação ao trabalho mas finito. Quando ele disparar, não retorne silenciosamente um resultado vazio. Lance uma exceção, registre o identificador da tarefa e deixe o chamador decidir se tenta novamente — uma tarefa que estourou o timeout de polling pode ainda estar rodando, e reenviar às cegas pode duplicar trabalho.
Baixando e armazenando a saída
Se a resposta contiver referências a artefatos — URLs, identificadores de arquivo ou chaves de armazenamento — trate-as como transitórias. Elas podem expirar, podem ser limitadas à sua conta e podem não sobreviver a novas tentativas. A cópia durável é a que você mesmo salva.
O padrão obter e persistir
Quando a tarefa termina, leia a referência ao artefato do estado terminal, obtenha-o uma vez e grave em um destino que você controla: um caminho local para scripts, um bucket de object storage para qualquer coisa próxima de produção. Registre o identificador da tarefa junto com o arquivo armazenado, para que você possa rastrear o artefato até a requisição que o gerou.
def save_output(fetch_bytes, artifact_url, dest_path):
data = fetch_bytes(artifact_url)
with open(dest_path, "wb") as f:
f.write(data)
return dest_path
Práticas que evitam perda silenciosa de dados
Grave em um caminho temporário e renomeie em caso de sucesso, para que um download falho nunca deixe um arquivo pela metade que pareça válido. Se a resposta expuser contagem de bytes ou checksum, verifique. Para arquivos grandes, faça streaming para o disco em vez de carregar a carga inteira na memória.
Guarde também a resposta bruta da chamada de estado final. Armazenar JSON é barato, e quando alguém perguntar por que o arquivo parece errado, o documento de estado com nome do modelo, timestamp e id da tarefa é a forma mais rápida de reconstruir o que aconteceu.
Por fim, separe recuperação de processamento. Baixe, armazene e só então transforme. Se você fizer parse enquanto baixa, um breve erro de rede parecerá um bug de formatação, e você passará a tarde resolvendo o problema errado.
Depurando falhas comuns
A maioria das falhas cai em quatro categorias. Cada uma tem um teste de isolamento rápido.
Erros de autenticação
Sintoma: 401 ou 403 antes que qualquer conteúdo do seu corpo importe. Verifique se a chave foi realmente carregada — imprima se a variável de ambiente está definida, não o valor dela. Valide o prefixo Bearer e o espaço que o segue. Confirme que o nome do cabeçalho está escrito corretamente e que nenhum proxy o está removendo. Se a mesma chave funciona no curl mas não na sua aplicação, sua aplicação está construindo o cabeçalho de forma diferente; compare o dict literal de cabeçalhos com as flags do curl.
Corpo da requisição malformado
Sintoma: 400 ou 422 com uma mensagem sobre o corpo. Valide seu JSON antes de enviar — json.dumps serializa quase qualquer coisa, incluindo dicts que você não pretendia construir. Verifique vírgulas finais coladas de arquivos de configuração, conteúdo que deveria ser string mas foi enviado como lista e campos obrigatórios ausentes. Reduza ao corpo mínimo da primeira seção e adicione campos de volta um por um até que ele falhe.
Nome de modelo errado
Sintoma: rejeição que parece erro de requisição malformada ou mensagem de modelo não encontrado. A string do modelo precisa ser exatamente gpt-6.1-terra. Causas comuns: valor padrão desatualizado em uma função auxiliar, variável de ambiente com valor diferente ou erro de digitação por redigitar em vez de copiar e colar. Mantenha-a como constante de módulo e faça grep para encontrar duplicatas.
Timeout de polling
Sintoma: seu loop sai por timeout enquanto a tarefa continua viva. Primeiro, confirme que o identificador de tarefa que você consulta é o mesmo que você enviou — imprimir os dois no momento do envio é a verificação mais simples. Depois, reveja sua lista de estados terminais: um estado que você não previu fará o loop rodar para sempre. Por fim, verifique se seu intervalo e prazo correspondem à duração real das tarefas; um prazo calibrado para requisições curtas sempre disparará em requisições longas. Ao dar timeout, registre a última carga de status, para que você saiba em que estado a tarefa estava quando você desistiu.
Trate esses pontos em ordem — autenticação, corpo, modelo, polling — porque cada camada mascara a de baixo. Um cabeçalho quebrado faz todo corpo parecer errado.
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