Tutorial
Como chamar o kimi-k3.1-pro pela API do HiAPI: curl, Python e requisições prontas para executar
Um guia prático de integração que cobre endpoint, parâmetros de requisição, streaming, chamadas de ferramentas e solução de erros
Nesta página
Por que chamar o kimi-k3.1-pro por meio de uma API agregadora
Toda integração de modelo carrega o mesmo custo oculto: no primeiro dia é divertido, no segundo mês é manutenção. Quando você conecta o kimi-k3.1-pro diretamente na aplicação, herda junto o esquema de autenticação, a semântica de erros, o modelo de cotas e o ritmo de lançamentos do provedor. Para um protótipo de modelo único, isso não é problema. Mas quando você quiser um segundo modelo, um segundo ambiente, ou um caminho de degradação para quando algum endpoint apresentar problema, isso se transforma em atrito.
Uma API agregadora reduz essas diferenças a um único contrato. O HiAPI expõe o kimi-k3.1-pro em um formato de requisição compatível com OpenAI, o que significa que o código cliente que você escrever aqui não é descartável. Troque o identificador do modelo e a mesma estrutura de requisição continua valendo para outros modelos da plataforma — os mesmos cabeçalhos, o mesmo array de mensagens, o mesmo envelope de streaming.
No caso específico do kimi-k3.1-pro, isso tem três implicações práticas:
- Uma única superfície de credenciais. Você gerencia apenas uma API Key e uma URL base, em vez de um conjunto crescente de contas de provedores.
- Payloads previsíveis. Os esquemas de requisição e resposta se mantêm estáveis entre modelos, então suas camadas de parsing, retry e logging precisam ser escritas uma única vez.
- Baixo custo de migração. Se no futuro algum tipo de carga for mais adequado a outro modelo, a mudança é uma string no payload, não uma reescrita da camada de transporte.
O restante deste guia é a integração em si: anatomia da requisição, chamada curl pronta para copiar, o cliente Python equivalente e, em seguida, os dois recursos que costumam causar mais problemas em produção — streaming e chamadas de ferramentas — e por fim uma lista de verificação para solução de erros.
O que você precisa antes de começar
- Uma API Key do HiAPI, armazenada onde o seu projeto guarda segredos.
- A URL base da API da sua conta, obtida no console do HiAPI. Todos os exemplos abaixo usam
https://api.hiapi.ai/v1como URL base de exemplo; antes de ir para produção, confirme o host real no console. - A string do identificador do modelo kimi-k3.1-pro — copiada exatamente como aparece na lista de modelos do console, pois o identificador diferencia maiúsculas de minúsculas.
curlpara o primeiro teste, e Python 3.9+ com a bibliotecarequestspara o exemplo de cliente.
Forma da requisição: endpoint, cabeçalhos e parâmetros do modelo
Toda chamada de conversa segue a mesma anatomia. Entenda cada parte uma vez e você não precisará depurar campo por campo depois.
Endpoint
A conclusão de conversa fica em um único caminho sob a URL base:
POST {BASE_URL}/chat/completions
Este é o único endpoint necessário para todos os exemplos deste guia. Streaming e chamadas de ferramentas não são endpoints separados — são opções no mesmo corpo da requisição.
Cabeçalhos
Apenas dois cabeçalhos realmente importam:
Authorization: Bearer $HIAPI_API_KEY
Content-Type: application/json
A chave vai no cabeçalho Authorization, com o prefixo Bearer. Não a coloque na URL, em parâmetros de consulta nem no corpo da requisição — essas três práticas a expõem em logs e relatórios de erro. Defina Content-Type explicitamente; alguns clientes HTTP não o inferem por você.
Os campos do corpo da requisição que realmente importam
Uma requisição mínima tem quatro campos relevantes:
model— o identificador do kimi-k3.1-pro. Obrigatório. É o campo mais fácil de errar na primeira tentativa, porque precisa corresponder exatamente.messages— um array ordenado de objetos, cada um comrole(system,userouassistant) econtent. Obrigatório e não vazio. A ordem é o seu histórico de conversa; o modelo vê exatamente esse array, e nada mais.stream— booleano, padrãofalse. Quandotrue, a resposta chega como eventos enviados pelo servidor, em vez de um único corpo JSON. Há uma seção dedicada abaixo.temperature— controle opcional de amostragem. Valores baixos produzem saídas mais determinísticas; valores altos, mais variação. Escolha um valor por caso de uso e não mexa mais; não o ajuste a cada requisição.
Campos opcionais que você pode adicionar conforme a integração amadurece:
max_tokens— limite de comprimento da geração. Serve como proteção contra custo e latência. Observe que ele limita a saída, não a entrada.tools— array de definições de ferramentas, detalhado mais adiante.tool_choice— controla se e como o modelo deve chamar as ferramentas que você forneceu.stop— uma ou mais sequências que encerram a geração.
A resposta que você deve esperar
Uma resposta não streaming retorna um objeto JSON cujo array choices contém pelo menos um item. Nesse item você encontrará um objeto message, com role e content, além de um finish_reason, que informa por que a geração parou. Sempre ramifique com base no finish_reason, em vez de presumir que o conteúdo está completo — uma resposta truncada ainda tem conteúdo, só não é a resposta completa.
Escreva o parser para essa estrutura, e não para uma resposta serializada como string. Assim ele sobrevive independentemente de como você trocar de modelo na plataforma.
Uma requisição curl pronta para executar
Comece por aqui. Se ela retornar uma resposta válida, significa que sua chave, URL base e identificador de modelo estão corretos; qualquer problema depois disso está no código, não nas credenciais.
curl -sS "$HIAPI_BASE_URL/chat/completions" \
-H "Authorization: Bearer $HIAPI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "kimi-k3.1-pro",
"messages": [
{"role": "system", "content": "Você é um assistente técnico conciso."},
{"role": "user", "content": "Explique em duas frases o que é uma chave de idempotência."}
],
"temperature": 0.3,
"max_tokens": 256
}'
Explicação de cada campo
-sSmantém o curl silencioso quanto ao progresso, mas ainda expõe erros. Sem o segundoS, uma requisição com falha pode sair silenciosamente, desperdiçando uma rodada de depuração.- Variáveis de ambiente mantêm a chave fora do histórico do shell e do buffer de rolagem do terminal. Exporte
HIAPI_BASE_URLeHIAPI_API_KEYno seu arquivo de configuração de shell ou em um.envcarregado. - Corpo entre aspas simples é o correto para shells POSIX, desde que o payload não contenha aspas simples. Quando precisar de aspas simples, mova o corpo para um arquivo e passe com
-d @body.json— isso evita uma classe de bugs de aspas que parecem erros de formato JSON. - A mensagem
systemé opcional, mas vale a pena incluir. É o lugar mais simples para fixar tom e formato de saída. max_tokensé deliberadamente conservador neste exemplo. Ele limita tanto a latência quanto o custo do teste rápido.
Interpretando o resultado
Uma chamada bem-sucedida retorna HTTP 200 e um corpo JSON. Antes de prosseguir, confirme três coisas:
choicesé um array não vazio.choices[0].message.contentcontém uma resposta real.choices[0].finish_reasoné um valor de conclusão normal, e não truncamento por comprimento.
Se o corpo da resposta for um objeto de erro, pule para a seção de solução de problemas — a mensagem de erro geralmente aponta o campo específico com problema.
Dica de repetibilidade
Salve essa chamada curl como um script de shell no repositório. Um único comando para fazer um teste rápido contra a API em tempo real é a forma mais rápida de distinguir "minha integração quebrou" de "minha conta ou chave mudou". Sempre que algo parecer errado, execute-o primeiro.
A mesma requisição em Python
A versão em Python deve parecer entediante — esse é justamente o objetivo. Todas as decisões interessantes (identificador do modelo, URL base, timeout) devem ficar na configuração, e não espalhadas pelos pontos de chamada.
import os
import requests
BASE_URL = os.environ["HIAPI_BASE_URL"].rstrip("/")
API_KEY = os.environ["HIAPI_API_KEY"]
MODEL = os.environ.get("HIAPI_MODEL", "kimi-k3.1-pro")
HEADERS = {
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json",
}
def chat(messages, temperature=0.3, max_tokens=512, timeout=60):
payload = {
"model": MODEL,
"messages": messages,
"temperature": temperature,
"max_tokens": max_tokens,
}
resp = requests.post(
f"{BASE_URL}/chat/completions",
headers=HEADERS,
json=payload,
timeout=timeout,
)
resp.raise_for_status()
data = resp.json()
choice = data["choices"][0]
return choice["message"]["content"], choice.get("finish_reason")
if __name__ == "__main__":
text, reason = chat([
{"role": "system", "content": "Você é um assistente técnico conciso."},
{"role": "user", "content": "Explique em duas frases o que é uma chave de idempotência."},
])
print(reason)
print(text)
Por que organizar assim
- Use
json=em vez dedata=— a bibliotecarequestsserializa o dicionário e define o tipo de conteúdo por você. Serializar manualmente introduz erros de escape com facilidade. - Sempre
timeout=60— a ausência de timeout é a causa mais comum de processos de trabalho travarem até serem mortos pelo gerenciador. Toda chamada de rede em um serviço deve ter timeout. raise_for_status()antes de analisar — isso transforma falhas na camada HTTP em exceções no ponto da chamada, em vez de deixar um corpo de resposta malformado fluir para o downstream.MODELvindo do ambiente — ao trocar de modelo, o identificador é a única coisa que muda. Mantê-lo na configuração significa que a troca é uma variável de implantação, não uma alteração de código.- Retornar
finish_reason— quem chama quase sempre precisa saber se a resposta foi truncada.
Mantenha reutilizável entre modelos
A assinatura de chat(messages, ...) deliberadamente não expõe nada específico de modelo. Se mais tarde você rotear cargas mais baratas para outros modelos, ou passe um parâmetro explícito de substituição de modelo, ou construa um segundo objeto de cliente com um MODEL diferente. Transporte, cabeçalhos, política de retry e tratamento de erros permanecem iguais.
Uma observação sobre retries
Não faça retry cego dentro de chat(). Faça retry na camada que sabe se a operação pode ser repetida com segurança — uma conclusão que falhou geralmente é segura, mas uma requisição que já alterou estado downstream não é. Faça retry apenas para falhas transitórias de transporte e respostas de rate limiting, e apenas com backoff exponencial limitado.
Streaming de respostas sem quebrar o cliente
Streaming é a diferença entre uma interface de chat que parece instantânea e uma tela em branco por dez segundos. Também é o que introduz mais bugs de integração, porque a resposta deixa de ser um único documento JSON.
Como ativar
Adicione "stream": true ao corpo da requisição. O restante da requisição não muda.
with requests.post(
f"{BASE_URL}/chat/completions",
headers=HEADERS,
json={"model": MODEL, "messages": messages, "stream": True},
stream=True,
timeout=120,
) as resp:
resp.raise_for_status()
for line in resp.iter_lines(decode_unicode=True):
if not line or not line.startswith("data:"):
continue
chunk = line[len("data:"):].strip()
if chunk == "[DONE]":
break
# Analise o chunk como JSON e leia choices[0].delta.content
O que realmente chega
O corpo da resposta é uma série de eventos enviados pelo servidor. Cada evento é uma linha data: que carrega um pequeno objeto JSON. Em choices[0] há um objeto delta em vez de um objeto message — o delta geralmente contém um fragmento de content, e pode não conter nada. O stream termina com a linha sentinela data: [DONE].
Quatro regras cobrem quase todos os erros:
- Acumule, não substitua. Cada delta é um fragmento. Anexe
delta.contenta um buffer; a resposta completa é a concatenação de cada fragmento na ordem. - Ignore deltas vazios. O primeiro e o último evento frequentemente não trazem conteúdo. Evite anexar
None. - Trate
[DONE]como terminador, não como dado. Pare de ler ali; o conteúdo posterior não faz parte da resposta. - Leia
finish_reasondo último evento que o carrega. No modo streaming, o estado de conclusão aparece em um delta mais tarde, não em um campo de nível superior.
Armadilhas que merecem ser citadas
- Esquecer de definir
stream=Truena chamada do cliente. Você receberá o stream inteiro como um corpo em buffer, o que contraria o objetivo e parece uma requisição não streaming muito lenta. - Timeout configurado como em não streaming. Streams de gerações longas duram mais que requisições curtas. Dê ao caminho de streaming um timeout de leitura mais folgado e considere um temporizador de inatividade que aborta quando nenhum byte chega em um intervalo escolhido.
- Analisar linha por linha sem verificar o prefixo. Nem toda linha é dado. Linhas vazias separam eventos; ignore-as.
- Presumir que o delta tem a chave
content. O streaming de chamadas de ferramentas coloca outras chaves no delta. Sempre leia de forma defensiva. - Esquecer o consumidor no cliente. Um servidor que grava o stream em um buffer e só o emite no final é tecnicamente streaming, mas não na prática. Garanta que o downstream renderize os fragmentos à medida que chegam.
Quando não usar streaming
Tarefas em lote, resumos em background e qualquer coisa cuja saída seja consumida por um programa em vez de exibida a uma pessoa costumam ser mais simples sem streaming. Respostas não streaming exigem apenas uma análise, são mais fáceis de registrar em log e mais fáceis de validar por esquema. Use streaming onde a latência é visível para o usuário; não o use por padrão.
Adicionando chamadas de ferramentas ao fluxo
Chamadas de ferramentas permitem que o modelo peça ao seu código para executar uma ação, em vez de inventar uma resposta. O protocolo é uma conversa em duas rodadas: você declara a ferramenta, o modelo pode responder com uma solicitação de chamada, você a executa e então envia o resultado de volta.
Declarando uma ferramenta
Adicione o array tools à requisição. Cada item envolve a descrição de uma função:
{
"model": "kimi-k3.1-pro",
"messages": [{"role": "user", "content": "Como está o tempo em Lisboa?"}],
"tools": [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Retorna o tempo atual na cidade especificada.",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string", "description": "Nome da cidade"}
},
"required": ["city"]
}
}
}
],
"tool_choice": "auto"
}
O description na função e em cada parâmetro não é decoração — é a única orientação que o modelo tem para decidir quando e como chamar a ferramenta. Escreva-o como se estivesse explicando para um novo colega.
O ciclo de resposta
- Envie a requisição.
- Se
choices[0].finish_reasonindicar uma chamada de ferramenta, leiachoices[0].message.tool_calls. Cada item temid, onameda função earguments— uma string codificada em JSON, não um objeto. Analise-a. - Execute a função no seu código. Valide os argumentos antes de fazer qualquer coisa com eles; o modelo pode gerar payloads plausíveis, mas com campos faltando ou tipos errados.
- Anexe a mensagem do assistente — incluindo suas
tool_calls— ao seu arraymessages. - Anexe uma nova mensagem com role
tool, contendo otool_call_idcorrespondente e o resultado comocontent. - Envie a requisição novamente. O modelo agora monta a resposta final usando a saída da ferramenta.
O passo 4 é o que as pessoas pulam, e é exatamente onde quebra. Se você só devolver o resultado da ferramenta sem a rodada de chamada de ferramenta do assistente, a conversa terá uma referência pendente e o modelo não terá registro de que pediu algo.
Lidando com múltiplas chamadas
Uma resposta pode conter várias chamadas de ferramenta na mesma rodada. Execute cada uma e retorne uma mensagem tool para cada chamada, cada uma com seu próprio tool_call_id. Não as combine.
Controlando chamadas
tool_choice é sua alavanca de política: auto deixa o modelo decidir, exigir uma ferramenta específica força uma chamada, e desabilitar ferramentas diz ao modelo para responder diretamente. Mantenha um orçamento — se uma ferramenta continuar falhando e o modelo continuar tentando, o ciclo de ferramentas pode durar muito. Limite o número de iterações no seu próprio ciclo e retorne uma mensagem clara ao atingir o limite, em vez de deixar a requisição se arrastar.
Trate a saída da ferramenta como não confiável
O modelo lê o resultado da ferramenta como texto. Mantenha-os pequenos, estruturados, sem instruções, e valide os argumentos do seu lado. Ferramentas que retornam texto ilimitado são tanto um problema de custo quanto um risco de correção.
Diagnosticando erros comuns
A maioria das falhas de integração se encaixa em cinco categorias. Siga esta lista antes de mexer nos prompts.
1. Autenticação e autorização
- Sintoma: status HTTP na faixa 401/403.
- Verifique: a chave existe, não tem espaços em branco antes ou depois ao colar, e tem exatamente o prefixo
Bearer. - Verifique: a URL base corresponde à exibida no console do HiAPI — um host desatualizado ou colado errado gera erros de autenticação confusos.
- Correção: reexporte as variáveis de ambiente e execute novamente o teste rápido com curl antes de mexer no código.
2. Payload malformado
- Sintoma: erro de validação de requisição nomeando um campo, ou corpo de resposta impossível de analisar.
- Verifique: o corpo é JSON válido. Quando construído manualmente, valide com um
json.toolrápido; quando construído em código, garanta que o dicionário não tenha um nível extra de aninhamento por acidente. - Verifique:
messagesnão está vazio e cada item temroleecontent. - Verifique: os valores de
rolepertencem ao conjunto suportado. Erros de digitação comorole: "human"são falhas silenciosas em alguns clientes, e não erros óbvios. - Verifique: os itens de
toolstêmtype: "function"e um objetofunctionaninhado. Definições achatadas são o erro mais comum de chamadas de ferramentas.
3. Identificador do modelo
- Sintoma: erro do tipo não encontrado, ou aviso de que o modelo não está disponível para sua conta.
- Verifique: o identificador foi copiado exatamente do console. Maiúsculas, minúsculas e separadores importam.
- Verifique: o modelo está habilitado para sua chave. Mesmo com um identificador válido, um modelo que sua conta não pode chamar ainda falhará.
4. Limites de contexto e comprimento
- Sintoma: erro sobre a requisição exceder o contexto máximo, ou resposta terminando com um
finish_reasonrelacionado a comprimento. - Verifique: a soma do seu prompt de sistema, histórico de mensagens e quaisquer definições de ferramentas. Os esquemas de ferramentas contam no orçamento e são facilmente esquecidos.
- Correção: corte o histórico, resuma turnos anteriores ou divida a tarefa. Para truncamento de saída, aumente
max_tokensse a carga realmente precisar de mais; caso contrário, mantenha-o limitado.
5. Rate limiting e timeouts
- Sintoma: status de limitação sob carga, ou timeout de leitura no cliente.
- Verifique: se os retries estão sendo feitos sem nenhum backoff. Ciclos de retry apertados transformam uma limitação passageira em limitação contínua.
- Correção: siga os sinais de rate limiting indicados na resposta, use backoff exponencial limitado com jitter e controle a concorrência por chave. Para timeouts, verifique primeiro o valor de timeout do cliente — um limite do cliente menor que o tempo de geração do modelo produz exatamente esse sintoma.
Disciplina geral de depuração
Registre quatro coisas em cada falha: status HTTP, corpo da resposta, identificador do modelo e se stream estava definido. Esses quatro itens explicam a grande maioria dos incidentes. E mantenha o teste rápido com curl atualizado — quando ele passa e sua aplicação falha, você sabe que o problema está no código, não nas credenciais.
Lendo as mensagens de erro
A camada agregadora em geral informa claramente qual campo causou a rejeição. Resista à tentação de reescrever o prompt. Leia a mensagem, corrija o campo indicado e tente mais uma vez. Se o mesmo erro persistir, valide a requisição contra o teste rápido antes de aprofundar.
Antes de ir para produção: lista de verificação
A diferença entre "funciona no meu terminal" e "funciona em produção" é, em grande parte, uma lista de verificação que ninguém escreveu. Aqui está uma que vale copiar.
Configuração e segredos
- A API Key fica em um gerenciador de segredos, nunca no controle de código-fonte e nunca em uma URL ou linha de log. Confirme que seu cliente HTTP não consegue imprimir o cabeçalho
Authorizationem nível de depuração. - A URL base e o identificador do modelo são configuração, não constantes espalhadas pelo código. Confirme a URL base no console.
- Rotacione chaves de acordo com um plano e após a saída de qualquer membro da equipe. Seu código cliente deve pegar a chave rotacionada sem alterações.
Higiene das requisições
- Toda chamada de saída tem timeout explícito, e o caminho de streaming tem timeout mais folgado com regras de aborto por inatividade.
- Todo caminho de chamada define
max_tokens. Geração ilimitada é fatura ilimitada. - As configurações de amostragem são fixas por caso de uso e documentadas, para que os resultados sejam reproduzíveis quando precisar depurar.
Tratamento de respostas
- Seu parser ramifica com base no
finish_reasone trata truncamento como um resultado separado, não como resposta completa. - A acumulação de streaming é testada tanto com respostas curtas quanto longas, incluindo respostas encerradas antecipadamente.
- Os argumentos de chamadas de ferramentas são validados antes do uso, e o turno de chamada de ferramenta do assistente sempre é ecoado no array de mensagens.
- O ciclo de ferramentas tem um limite de iterações e uma mensagem de falha clara.
Comportamento em falhas
- Os retries são limitados, usam backoff exponencial limitado com jitter e se aplicam apenas a operações seguras de repetir.
- Respostas de rate limiting são respeitadas, e não bombardeadas.
- Falhas registram status, corpo da resposta, identificador do modelo e o flag de stream — esses quatro campos realmente resolvem incidentes.
- O teste rápido com curl roda em CI ou de forma agendada, para que você descubra mudanças de credenciais ou de modelo pelo painel, e não por meio de clientes.
Custo e capacidade
- Você sabe como o uso é cobrado — a plataforma cobra por token processado, então prompts longos e gerações longas importam. Consulte as tarifas atuais no painel de preços do console.
- Você sabe qual tipo de carga é o maior consumidor e se ele precisa do modelo completo ou de um modelo mais leve.
- Você tem um caminho de degradação: se uma chamada falhar repetidamente, a aplicação degrada de forma visível em vez de travar silenciosamente.
A última pergunta
Pergunte-se: alguém que não escreveu esta integração consegue observá-la. Se um desenvolvedor da sua equipe consegue ler o teste rápido, os campos de log de erro e a configuração, e entender como diagnosticar falhas, você terminou. Se não, a lista ainda não está completa.
Com uma chamada curl executável, um cliente Python reutilizável e esta lista de verificação, o kimi-k3.1-pro está de fato integrado — e não apenas conectado.
Artigos relacionados
Ver todos os artigos →-
Tutorial
API ElevenLabs Music no HiAPI: gerar música com curl, Python e receitas de prompts
Um tutorial prático para chamar elevenlabs/music-v2.5 através do HiAPI, com receitas de prompts prontas para copiar para estilo, humor e duração
-
Tutorial
Como usar gpt-image-2.5-sunburst/image-to-image com a API HiAPI: curl e Python
Requisições executáveis para desenvolvedores, fluxo de envio de imagem de referência e solução de erros
-
Tutorial
Como usar o gemini-omni-1.2-flash com a API HiAPI: curl e Python