HiAPI
Blogue

Tutorial

Como usar o grok-4.7 pela API do HiAPI: curl, Python e uma requisição que funciona

Guia prático da primeira requisição até a validação da resposta

Nov 3, 2026
HiAPI 博客教程封面图:多层半透明玻璃平面在浅色背景上折射出克制的冷蓝色带。

O que você precisa preparar antes da primeira requisição

Antes de enviar qualquer coisa para a API, garanta que quatro itens estão prontos. Pular qualquer um deles é a causa mais comum de falha na primeira chamada, e a falha muitas vezes não tem nenhuma relação com o modelo em si.

Uma conta HiAPI

Você precisa de uma conta válida no HiAPI.ai. Faça login no painel para gerenciar projetos, chaves e uso. Todas as operações deste tutorial são feitas pela mesma interface de API unificada, então a chave que você criar aqui serve para os diversos modelos oferecidos pela plataforma.

Uma chave de API

Crie uma chave de API no painel e guarde-a em local seguro — uma variável de ambiente do shell durante os testes, e um gerenciador de segredos para qualquer coisa que vá para produção. Nunca faça commit da chave em um repositório de código nem a cole em aplicativos clientes.

Para testes locais, basta exportá-la uma vez por sessão de shell:

export HIAPI_API_KEY="your-api-key-here"

A URL base

A URL base é o endereço raiz da API do HiAPI. Todas as requisições deste tutorial são relativas a ela. Consulte seu painel para confirmar a URL base exata que sua conta deve usar e guarde-a em uma variável, para que scripts e código da aplicação referenciem o mesmo valor:

export HIAPI_BASE_URL="https://api.hiapi.ai"

O identificador do modelo

O identificador de modelo usado neste tutorial é grok-4.7. Ele é passado como uma string simples no corpo da requisição. Se o identificador estiver errado, você normalmente recebe um erro explícito em vez de um fallback silencioso, então erros de digitação são fáceis de detectar.

Com esses quatro itens — conta, chave, URL base e ID do modelo — você tem tudo o que é necessário para o formato da requisição. O curl não exige a instalação de nenhum SDK, e o Python só precisa do cliente HTTP que você provavelmente já tem.

Verificação rápida do ambiente

Confirme que a chave e a URL base estão visíveis para o shell que você vai usar:

[ -n "$HIAPI_API_KEY" ] && echo "key set"
[ -n "$HIAPI_BASE_URL" ] && echo "base url set"

Se as duas linhas forem impressas, você pode passar para a próxima seção.

O formato de uma requisição ao grok-4.7 no HiAPI

Todas as requisições deste tutorial compartilham os mesmos quatro elementos: o endpoint, o cabeçalho de autenticação, o campo model e o array messages. Entendê-los separadamente torna muito mais fácil compreender depois o streaming e a chamada de ferramentas, pois esses recursos alteram apenas parte desse formato.

O endpoint

A chamada é uma requisição POST para o endpoint de chat completions sob a URL base. Neste tutorial, representamos assim:

POST {HIAPI_BASE_URL}/v1/chat/completions

Se o seu painel mostrar um caminho diferente, use o caminho do painel; de qualquer forma, o corpo da requisição é o mesmo.

O cabeçalho de autenticação

A autenticação é feita com um bearer token no cabeçalho Authorization:

Authorization: Bearer $HIAPI_API_KEY

Como é um cabeçalho e não um parâmetro de consulta, a chave nunca aparece em URLs, logs de acesso ou histórico do navegador.

O tipo de conteúdo

O corpo da requisição é JSON, então envie Content-Type: application/json. Tanto o curl quanto qualquer cliente HTTP Python definem isso para você, mas vale explicitar, para que o conjunto de cabeçalhos não seja ambíguo.

O corpo da requisição: model e messages

O corpo da requisição é um objeto JSON com pelo menos dois campos:

  • model — a string do identificador do modelo, aqui grok-4.7.
  • messages — um array ordenado de objetos de mensagem. Cada objeto tem role e content. Os papéis comuns são: system para instruções que enquadram a conversa, user para a própria requisição e assistant para fornecer turnos anteriores do modelo quando você continua uma conversa.

O corpo mínimo da requisição é assim:

{
  "model": "grok-4.7",
  "messages": [
    { "role": "system", "content": "You are a concise technical assistant." },
    { "role": "user", "content": "Explain what an idempotent HTTP method is in two sentences." }
  ]
}

Esse é todo o contrato de uma chamada básica. Qualquer outra coisa — streaming, definições de ferramentas — são campos adicionais no mesmo objeto, e é por isso que as seções anteriores importam: uma vez que esse formato está correto, o resto é acréscimo.

Como é a resposta

A resposta é um objeto JSON. A parte que você quase sempre quer está em choices, que é um array; cada entrada tem um message contendo role e content. Também há metadados, como o modelo que processou a requisição e um bloco usage que descreve a contagem de tokens. Leia choices[0].message.content e você tem o texto da resposta. Os outros campos são úteis para logging e acompanhamento de custos, mas não são necessários para começar.

Uma requisição curl que funciona

Com a chave exportada e o formato da requisição entendido, a chamada curl fica curta. Quando você quiser isolar a pergunta do código da aplicação, esta é a versão a copiar.

curl -sS "$HIAPI_BASE_URL/v1/chat/completions" \
  -H "Authorization: Bearer $HIAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "grok-4.7",
    "messages": [
      { "role": "system", "content": "You are a concise technical assistant." },
      { "role": "user", "content": "In one sentence, what is a bearer token?" }
    ]
  }'

O que cada flag faz

  • -sS mantém a saída silenciosa, mas ainda imprime erros. Sem ela, uma requisição com falha pode parecer uma resposta vazia.
  • A URL é formada pela variável da URL base mais o caminho de chat completions, então você nunca precisa codificar o host diretamente em scripts.
  • -H "Authorization: ..." envia o bearer token. A variável é expandida pelo shell, e é por isso que exportá-la antes era importante.
  • -H "Content-Type: application/json" informa ao servidor que o corpo da requisição é JSON.
  • -d '...' é o corpo da requisição. As aspas simples em volta do JSON evitam que o shell interprete as chaves e aspas internas.

Se você preferir colocar o corpo em um arquivo, grave-o em body.json e substitua o argumento -d por -d @body.json. Isso costuma ficar mais claro quando o array messages cresce.

Lendo o JSON bruto

A resposta chega à saída padrão como um objeto JSON. Quando quiser inspecioná-la a olho nu, canalize-a por um formatador:

curl -sS "$HIAPI_BASE_URL/v1/chat/completions" \
  -H "Authorization: Bearer $HIAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -d @body.json | python -m json.tool

Você deve conseguir ver um array choices cujo primeiro elemento contém um objeto message com uma string content — essa string é a resposta do modelo. Ao lado dela normalmente há também um identificador da resposta, o nome do modelo ecoado e um objeto usage com a contagem de tokens de prompt e de completion. Registre agora uma resposta bem-sucedida: quando você for validar o cliente Python, ela será a referência de comparação.

Falhas comuns nesta etapa

Um 401 quase sempre significa que o bearer token está ausente, mal formatado ou não foi realmente exportado no shell atual. Um 400 acompanhado de uma mensagem sobre o corpo da requisição geralmente significa JSON malformado — vírgulas finais ou aspas tipográficas coladas da documentação são os culpados comuns. Corrija esses dois pontos antes de olhar qualquer outra coisa.

A mesma requisição em Python

A versão em Python faz a mesma coisa com o mesmo corpo de requisição. O sentido de reescrevê-la é passar de um teste no shell para um código que pode ir para uma aplicação, com o corpo da requisição como estrutura de dados em vez de uma string entre aspas.

Usando a biblioteca padrão

Se você não quer adicionar dependências, urllib é suficiente:

import json
import os
import urllib.request

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

payload = {
    "model": "grok-4.7",
    "messages": [
        {"role": "system", "content": "You are a concise technical assistant."},
        {"role": "user", "content": "In one sentence, what is a bearer token?"},
    ],
}

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

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

print(body["choices"][0]["message"]["content"])

Usando requests

Se o requests já estiver no seu ambiente, a chamada fica mais curta:

import os
import requests

response = requests.post(
    f"{os.environ['HIAPI_BASE_URL']}/v1/chat/completions",
    headers={"Authorization": f"Bearer {os.environ['HIAPI_API_KEY']}"},
    json={
        "model": "grok-4.7",
        "messages": [
            {"role": "system", "content": "You are a concise technical assistant."},
            {"role": "user", "content": "In one sentence, what is a bearer token?"},
        ],
    },
    timeout=60,
)
response.raise_for_status()
print(response.json()["choices"][0]["message"]["content"])

Por que esta versão é mais segura para aplicações

Observe três escolhas deliberadas. A chave e a URL base vêm de variáveis de ambiente, nunca de literais no código-fonte. O corpo da requisição é um dicionário Python, então aspas fora de lugar geram imediatamente um SyntaxError, em vez de uma rejeição confusa do lado do servidor. E a chamada define um timeout: sem ele, uma conexão travada pode deixar um worker pendurado indefinidamente.

Execute a versão Python com o mesmo prompt que você usou no curl. A redação da resposta pode variar um pouco entre execuções — o modelo não é determinístico —, mas a estrutura da resposta deve ser exatamente a mesma: um array choices, um message com content e um bloco usage. Se a estrutura coincidir, seu cliente está conectado corretamente e todas as seções seguintes são melhorias opcionais.

Ativando o streaming

O streaming muda a forma como os tokens chegam, não o que você pede. Em vez de esperar pela resposta completa, você a recebe aos poucos, e é isso que faz uma interface de chat parecer responsiva.

O que muda na requisição

Adicione um campo ao corpo da requisição que você já tem:

{
  "model": "grok-4.7",
  "stream": true,
  "messages": [
    { "role": "user", "content": "Count from one to five, one number per line." }
  ]
}

O endpoint, os cabeçalhos e o restante do messages não mudam. É exatamente por isso que aprender primeiro o formato básico faz sentido: o streaming é um flag adicional, não uma segunda API.

O que é retornado

Com stream ativado, a resposta deixa de ser um único objeto JSON. Ela passa a ser uma sequência de Server-Sent Events (SSE). Cada evento carrega uma linha data: cujo payload é um fragmento JSON com o mesmo formato da resposta normal, exceto que choices[0] contém um objeto delta em vez de um message completo. Os primeiros fragmentos podem conter apenas o papel; os fragmentos intermediários trazem trechos de conteúdo; o stream termina com a linha sentinela data: [DONE].

Como cliente, sua tarefa é concatenar as strings de delta.content em ordem e parar na sentinela. Trate qualquer fragmento sem content como uma não operação, e não como erro.

Consumindo os blocos em Python

import json
import os
import requests

with requests.post(
    f"{os.environ['HIAPI_BASE_URL']}/v1/chat/completions",
    headers={"Authorization": f"Bearer {os.environ['HIAPI_API_KEY']}"},
    json={
        "model": "grok-4.7",
        "stream": True,
        "messages": [{"role": "user", "content": "Count from one to five."}],
    },
    stream=True,
    timeout=60,
) as response:
    response.raise_for_status()
    for line in response.iter_lines():
        if not line:
            continue
        line = line.decode("utf-8")
        if not line.startswith("data: "):
            continue
        data = line[len("data: "):]
        if data == "[DONE]":
            break
        delta = json.loads(data)["choices"][0].get("delta", {})
        text = delta.get("content")
        if text:
            print(text, end="", flush=True)

Dois detalhes determinam se o streaming funciona ou parece travar. Passe stream=True para o cliente HTTP, para que ele não faça buffer do corpo inteiro da resposta, e itere linha a linha em vez de ler a resposta de uma vez. O flush=True no print diz respeito apenas ao que você vê na tela; sem ele, a saída pode parecer explodir de uma vez no final, mesmo que os blocos estejam sendo processados à medida que chegam.

Valide o streaming isoladamente

Não valide o streaming e a chamada de ferramentas no mesmo teste. Primeiro confirme que o texto concatenado produz uma resposta coerente para um prompt simples, e então vá adicionando recursos um a um. Se o stream terminar sem a sentinela, isso é um sinal para verificar a conexão, não o modelo.

A opção de chamada de ferramentas

A chamada de ferramentas permite que o modelo solicite funções definidas no seu código, em vez de apenas gerar texto. O acréscimo do lado da requisição funciona exatamente como o streaming.

Onde fica a opção

A definição de ferramentas é um array tools no corpo da requisição. Cada entrada descreve um item chamável: nome, descrição de quando usá-lo e uma descrição em JSON schema dos seus parâmetros. A descrição importa mais do que parece — é a única orientação que o modelo tem para julgar quando a ferramenta se aplica.

{
  "model": "grok-4.7",
  "messages": [
    { "role": "user", "content": "What is the weather in Lisbon right now?" }
  ],
  "tools": [
    {
      "type": "function",
      "function": {
        "name": "get_weather",
        "description": "Return the current weather for a named city.",
        "parameters": {
          "type": "object",
          "properties": {
            "city": { "type": "string", "description": "City name, e.g. Lisbon" }
          },
          "required": ["city"]
        }
      }
    }
  ]
}

O formato a memorizar é type mais function, que contém name, description e parameters. Se você já tem definições de JSON schema, o bloco parameters é onde elas vão.

Como o modelo responde

Quando o modelo decide que precisa de uma ferramenta, a mensagem assistant em choices[0] não é texto comum. Seu content normalmente vem vazio e carrega um array tool_calls. Cada entrada tem um identificador, um nome de função que corresponde a uma das suas definições e uma string arguments contendo JSON. Faça o parse dessa string de arguments — ela é uma string, não um objeto, e tratá-la como objeto é uma fonte comum de erros.

Seu código então executa a função e envia uma requisição subsequente: a conversa original, a mensagem assistant com tool_calls e uma nova mensagem com papel tool contendo o identificador da chamada e o resultado. O modelo usa esse resultado para gerar a resposta final. O tool_call_id deve corresponder ao identificador da mensagem assistant; sem isso, a requisição subsequente fica ambígua.

Proteções práticas

  • Valide os argumentos obtidos no parse com o mesmo schema que você enviou. O modelo é guiado pelo schema, mas não está restrito a ele.
  • Trate o nome de função retornado como entrada não confiável e roteie apenas para uma lista explícita de funções permitidas.
  • Não ative stream e ferramentas ao mesmo tempo no primeiro teste. Confirme primeiro o ciclo completo de ferramentas sem streaming e depois, se o seu caso de uso precisar dos dois, combine-os.

Validando a resposta antes de ir para produção

Uma chamada que funciona no terminal não é o mesmo que uma integração validada. Percorra esta lista por completo e depois mantenha o script como smoke test.

Confirme a camada de transporte

Antes de fazer o parse de qualquer coisa, verifique se o status HTTP é 200. Um cliente que faz o parse primeiro produz um KeyError confuso quando o problema real é um 401. Verifique o status explicitamente e, em caso de falha, registre também o corpo da resposta — normalmente o servidor indica onde está o erro.

Confirme a estrutura da resposta

Verifique com asserções, não com suposições. Em uma chamada bem-sucedida sem streaming, valide três coisas: choices existe e não está vazio, choices[0].message.content é uma string não vazia e o modelo ecoado na resposta é o mesmo que você enviou. Essa última verificação detecta uma quantidade surpreendente de erros de configuração — um modelo padrão sobrescrevendo o modelo que você pediu.

Exercite deliberadamente os caminhos de erro

Não espere uma falha acontecer para descobrir como o seu código se comporta. Execute três testes negativos rápidos:

  • Faça uma chamada removendo o cabeçalho de autenticação e confirme que seu código expõe um erro de autenticação explícito, em vez de tentar novamente sem limite.
  • Envie um corpo de requisição sem o campo model e confirme que você recebe um erro de cliente, em vez de ficar pendurado.
  • Envie um prompt deliberadamente muito longo e confirme que seu timeout e seu tratamento de truncamento se comportam como esperado.

Cada um deles deve produzir uma falha concreta e registrada — não um genérico “algo deu errado”.

Valide os recursos adicionais separadamente

Se você ativou o streaming, confirme que os blocos concatenados formam uma resposta coerente e que a sentinela encerrou o loop. Se você ativou ferramentas, confirme que o ciclo se completa: a chamada de ferramenta é interpretada, a função é executada, o resultado volta com o identificador correspondente e produz a resposta final em texto. Coloque cada validação em seu próprio script pequeno, para que uma falha aponte para um único recurso.

Torne as verificações repetíveis

Coloque a sequência inteira em um arquivo, faça-o sair com código diferente de zero se qualquer asserção falhar e execute-o contra sua configuração de staging antes de cada implantação. Ele deve levar só alguns segundos e cobrir a chamada básica, uma chamada com streaming e, se você usa ferramentas, mais um ciclo de ferramentas. Quando ele passa, você pode confiar que uma falha em produção está na requisição que você envia, e não na infraestrutura subjacente.

Depois que as verificações passarem, execute a chamada curl mais uma vez. Se o JSON bruto coincidir com a saída da sua aplicação, a integração está concluída.

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