> Para agentes de IA: guia passo a passo de configuração — [`/docs/agents.md`](https://gate.joingonka.ai/docs/agents.md), índice da documentação — [`/llms.txt`](https://gate.joingonka.ai/llms.txt).

# Referência da API

Tudo sobre requisições ao gateway: protocolos, endereços, chaves e parâmetros. Abaixo — streaming, chamada de ferramentas, raciocínio, plugins e o custo da requisição na resposta.

## Protocolos e endereços

O gateway aceita os formatos da OpenAI e da Anthropic. A URL base para o SDK da OpenAI é `https://gate.joingonka.ai/v1` e para o SDK da Anthropic, `https://gate.joingonka.ai`. Todos os protocolos funcionam com a mesma chave e o mesmo saldo: uma requisição em qualquer formato percorre o mesmo caminho.

| Método e caminho | Formato | Para que serve | Particularidades |
| --- | --- | --- | --- |
| `POST /v1/chat/completions` | OpenAI Chat Completions | Chat, agentes, chamada de ferramentas | É o caminho principal: o gateway converte os demais formatos para ele. |
| `POST /v1/messages` | Anthropic Messages | Claude Code e SDK da Anthropic | URL base sem `/v1`; os modelos `claude-*` são substituídos pelo recomendado; o campo `max_tokens` é obrigatório. |
| `POST /v1/responses` | OpenAI Responses | Codex CLI e os novos SDKs da OpenAI | Sem estado: envie o histórico completo em cada requisição. |
| `POST /v1/completions` | OpenAI Completions (legacy) | Autocompletar e edição de código em editores | `suffix` é passado ao modelo como dica; na resposta, `logprobs: null`. |
| `POST /v1/embeddings` | OpenAI Embeddings | Representações vetoriais de texto | Resposta `501`: a rede não tem modelos de embeddings. |

### Endereços de referência

Respondem sem chave. A tabela de modelos com contexto e status está na seção [Modelos](https://gate.joingonka.ai/pt/docs/models).

| Método e caminho | Descrição |
| --- | --- |
| `GET /v1/models` | Lista de modelos: contexto, preços, parâmetros aceitos; campos no formato OpenRouter. |
| `GET /v1/models/{model}` | Ficha de um modelo; a barra no id, como está ou `%2F`. Modelo oculto ou desconhecido: `404 model_not_found`. |
| `GET /v1/capabilities` | Recursos do gateway: parâmetros, protocolos, plugins, campos de custo e limites (`limits`). |
| `GET /v1/plugins` | Plugins: id e nome. |
| `GET /v1/network-status` | Estado dos modelos da rede: disponibilidade, latências, uptime. |
| `GET /v1/nodes` | Resumo do pool de nós: quantos no total, ativos e em quarentena. |
| `GET /v1/web-search/engines` | Se a busca na web está ativada e em que estado estão seus motores. |

### Anthropic Messages

- URL base: `https://gate.joingonka.ai`. O SDK adiciona `/v1/messages` sozinho.
- A chave vai no cabeçalho `x-api-key` (é assim que o SDK da Anthropic envia) ou `Authorization: Bearer`.
- O gateway substitui os modelos `claude-*` pelo recomendado (`MiniMaxAI/MiniMax-M2.7`); no campo `model` da resposta permanece o nome enviado pelo cliente.
- `max_tokens` é obrigatório, como na API da Anthropic; se ultrapassar o teto do modelo, é cortado.
- O stream são eventos da Anthropic; nas pausas o gateway envia `event: ping` e uma falha chega como evento `event: error`.
- O raciocínio do modelo não aparece na resposta: não há blocos `thinking`.
- A ferramenta integrada `web_search` é executada pelo plugin de busca na web do gateway; consulte a seção [Plugins](https://gate.joingonka.ai/pt/docs/api#plugins).
- Não há contagem de tokens (`/v1/messages/count_tokens`): resposta `404`.

O Claude Code é configurado mais facilmente com o instalador: [conexão de ferramentas](https://gate.joingonka.ai/pt/docs#connect). Manualmente, use variáveis de ambiente; `ANTHROPIC_MODEL` fixa o modelo da rede.

#### Claude Code

```bash
export ANTHROPIC_BASE_URL=https://gate.joingonka.ai
export ANTHROPIC_AUTH_TOKEN=$JOINGONKA_API_KEY
export ANTHROPIC_MODEL=MiniMaxAI/MiniMax-M2.7
claude
```

#### cURL

```bash
curl https://gate.joingonka.ai/v1/messages \
  -H "x-api-key: $JOINGONKA_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "MiniMaxAI/MiniMax-M2.7",
    "max_tokens": 1024,
    "messages": [{"role": "user", "content": "What is Gonka?"}]
  }'
```

### OpenAI Responses

- O gateway não armazena respostas: envie todo o histórico em `input`. Os campos `previous_response_id` e `conversation` geram um erro `400` com código.
- `store` é aceito e não muda nada.
- Ferramentas: `function` e `web_search`, executada pelo plugin de busca na web. O gateway ignora as outras ferramentas integradas e a requisição é executada sem elas; exigir uma dessas ferramentas via `tool_choice` gera um erro `400`.
- As partes `input_image` e `input_file` geram um erro `400`: os modelos da rede trabalham com texto.
- Os endereços de estado (`GET /v1/responses/{id}`, `DELETE /v1/responses/{id}`, `GET /v1/responses/{id}/input_items`, `POST /v1/responses/{id}/cancel`, `POST /v1/responses/compact`) respondem `404` com código: o gateway não armazena respostas.
- Codex CLI: defina seu próprio id de provedor em `model_provider` (diferente de openai); assim o Codex compacta o histórico sozinho, sem `/v1/responses/compact`.

### Legacy Completions

- `prompt` é uma string ou um array de uma única string; a resposta vai em `choices[].text`. Vários prompts ou tokens no lugar de texto geram um erro `400`.
- `suffix` é passado ao modelo como dica no prompt: a rede não faz um preenchimento real do meio.
- Na resposta, `logprobs: null`; `best_of` é ignorado; `echo` funciona.

## Chaves e autorização

A chave é enviada no cabeçalho `Authorization: Bearer jg-…` ou `x-api-key: jg-…`, em todos os endereços. A chave é criada após o cadastro na página [gate.joingonka.ai/keys](https://gate.joingonka.ai/keys).

| Prefixo | Chave | Requisições aos modelos |
| --- | --- | --- |
| `jg-` | Chave normal da conta | sim |
| `gc-` | Chave filha: limites próprios, o gasto sai do saldo do proprietário | sim |
| `gm-` | Chave de gerenciamento: só gerencia as chaves filhas | não: `403 forbidden` |

- No painel, você pode definir para cada chave um limite de gastos diário, mensal e total; se ultrapassar, `402 child_key_limit_exceeded`.
- O número de requisições por minuto por chave é limitado; os valores estão na seção [Limites](https://gate.joingonka.ai/pt/docs/errors#limits).
- Sem chave, só funciona o chat de demonstração do site: uma requisição sem chave feita do seu próprio código receberá `402` com `is_demo`.
- As chaves são gerenciadas apenas no painel: `/api/keys` não está disponível com uma chave de API. O saldo e o gasto por chave estão em [API da conta](https://gate.joingonka.ai/pt/docs/billing#account-api).

> A chave é um segredo: não a guarde no repositório nem no código do frontend, passe-a por variáveis de ambiente.

## Exemplos

A mesma requisição em quatro SDKs. O modelo é o recomendado (`MiniMaxAI/MiniMax-M2.7`), a chave vem da variável de ambiente `JOINGONKA_API_KEY`.

### Python

```python
import os
from openai import OpenAI

client = OpenAI(
    base_url="https://gate.joingonka.ai/v1",
    api_key=os.environ["JOINGONKA_API_KEY"],
)

response = client.chat.completions.create(
    model="MiniMaxAI/MiniMax-M2.7",
    messages=[{"role": "user", "content": "What is Gonka?"}],
)
print(response.choices[0].message.content)
```

### TypeScript

```typescript
import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "https://gate.joingonka.ai/v1",
  apiKey: process.env.JOINGONKA_API_KEY,
});

const response = await client.chat.completions.create({
  model: "MiniMaxAI/MiniMax-M2.7",
  messages: [{ role: "user", content: "What is Gonka?" }],
});
console.log(response.choices[0].message.content);
```

### cURL

```bash
curl https://gate.joingonka.ai/v1/chat/completions \
  -H "Authorization: Bearer $JOINGONKA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "MiniMaxAI/MiniMax-M2.7",
    "messages": [{"role": "user", "content": "What is Gonka?"}]
  }'
```

### Anthropic SDK

```python
import os
import anthropic

client = anthropic.Anthropic(
    base_url="https://gate.joingonka.ai",
    api_key=os.environ["JOINGONKA_API_KEY"],
)

message = client.messages.create(
    model="MiniMaxAI/MiniMax-M2.7",
    max_tokens=1024,
    messages=[{"role": "user", "content": "What is Gonka?"}],
)
print(message.content[0].text)
```

### Resposta em streaming

#### Python

```python
import os
from openai import OpenAI

client = OpenAI(base_url="https://gate.joingonka.ai/v1", api_key=os.environ["JOINGONKA_API_KEY"])

stream = client.chat.completions.create(
    model="MiniMaxAI/MiniMax-M2.7",
    messages=[{"role": "user", "content": "What is Gonka?"}],
    stream=True,
)
for chunk in stream:
    if chunk.choices and chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="", flush=True)
```

#### TypeScript

```typescript
import OpenAI from "openai";

const client = new OpenAI({ baseURL: "https://gate.joingonka.ai/v1", apiKey: process.env.JOINGONKA_API_KEY });

const stream = await client.chat.completions.create({
  model: "MiniMaxAI/MiniMax-M2.7",
  messages: [{ role: "user", content: "What is Gonka?" }],
  stream: true,
});
for await (const chunk of stream) {
  process.stdout.write(chunk.choices[0]?.delta?.content ?? "");
}
```

#### cURL

```bash
curl -N https://gate.joingonka.ai/v1/chat/completions \
  -H "Authorization: Bearer $JOINGONKA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "MiniMaxAI/MiniMax-M2.7",
    "messages": [{"role": "user", "content": "What is Gonka?"}],
    "stream": true
  }'
```

#### Anthropic SDK

```python
import os
import anthropic

client = anthropic.Anthropic(base_url="https://gate.joingonka.ai", api_key=os.environ["JOINGONKA_API_KEY"])

with client.messages.stream(
    model="MiniMaxAI/MiniMax-M2.7",
    max_tokens=1024,
    messages=[{"role": "user", "content": "What is Gonka?"}],
) as stream:
    for text in stream.text_stream:
        print(text, end="", flush=True)
```

## Parâmetros da requisição

Parâmetros de `POST /v1/chat/completions` que o gateway garante por conta própria: a lista `supported_parameters` na resposta de capacidades:

| Parâmetro | Descrição |
| --- | --- |
| `temperature` | Aleatoriedade da resposta: quanto maior, mais variada. |
| `top_p` | Seleção de tokens por probabilidade acumulada. |
| `top_k` | Seleção entre os k tokens mais prováveis. |
| `min_p` | Corte de tokens improváveis em relação ao mais provável. |
| `frequency_penalty` | Penalidade por repetições frequentes. |
| `presence_penalty` | Penalidade por tokens que já apareceram. |
| `repetition_penalty` | Multiplicador contra repetições. |
| `stop` | Strings em que a geração é interrompida. |
| `seed` | Semente para reprodutibilidade. |
| `max_tokens` | Limite de tokens da resposta; acima do teto do modelo, é cortado até o teto. |
| `max_completion_tokens` | Outro nome de `max_tokens`: o gateway transfere o valor para ele. |
| `tools` | Funções que o modelo pode chamar, no formato OpenAI. |
| `tool_choice` | Se deve chamar uma função: à escolha do modelo, nunca, obrigatório ou uma específica. |
| `response_format` | Resposta estruturada: `json_object` ou `json_schema`. |

- Sem `temperature`, o gateway aplica `0.7`.
- Sem `max_tokens`, o gateway aplica o padrão do modelo: sem streaming, mais curto; no streaming, o teto do modelo. Os números por modelo estão na seção [Limites](https://gate.joingonka.ai/pt/docs/errors#limits).

### São repassados à rede como estão

`reasoning_effort`, `reasoning`, `enable_thinking`, `chat_template_kwargs`, `thinking_token_budget`, `min_tokens`, `logit_bias`, `n`, `parallel_tool_calls`, `extra_body`. O gateway não os valida: um valor fora da lista da rede gera um erro `400` com tipo `api_error`.

### Não são repassados à rede

Os demais campos o gateway aceita e não repassa à rede, por exemplo `user`, `metadata`, `store`, `logprobs`, `top_logprobs`, `thinking`, `stream_options`, `web_search_options`. O `usage` no streaming chega sempre.

## Streaming

- `stream: true`: resposta por eventos SSE; o último evento é `data: [DONE]`.
- Antes do encerramento chega um chunk com `usage`, sempre, mesmo sem `stream_options`.
- Nas pausas o gateway envia a cada 15 s um comentário `: keep-alive`; os clientes SSE o ignoram.
- Enquanto o stream não está aberto, a recusa chega com um código de resposta comum; depois de aberto, chega como chunk `joingonka-error`.
- Em `delta.tool_calls` há uma chamada por chunk: as chamadas que a rede junta o gateway separa.

```text
data: {"object":"chat.completion.chunk","model":"MiniMaxAI/MiniMax-M2.7","choices":[{"index":0,"delta":{"content":"Hi"},"finish_reason":null}]}

data: {"object":"chat.completion.chunk","model":"MiniMaxAI/MiniMax-M2.7","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}

data: {"object":"chat.completion.chunk","model":"MiniMaxAI/MiniMax-M2.7","choices":[],"usage":{"prompt_tokens":12,"completion_tokens":2,"total_tokens":14}}

data: [DONE]
```

### Chunks internos do gateway

Dá para reconhecê-los pelo campo `id`:

| `id` | Quando e o que inclui |
| --- | --- |
| `joingonka-error` | Falha após abrir o stream: campo `error` e depois corte sem `[DONE]`. |
| `joingonka-stream-stalled` | A rede ficou em silêncio além da pausa permitida: o stream é fechado com `finish_reason: stop`. |
| `joingonka-stream-unfinished` | A rede interrompeu a geração: `finish_reason: length`; continue com a próxima requisição. |
| `joingonka-citations` | Fontes da busca na web em `delta.annotations`, antes do encerramento. |
| `joingonka-meta` | Custo e tempos somente com o cabeçalho `x-joingonka-meta: 1`. |

### Streaming em outros protocolos

- Anthropic Messages: eventos de `message_start` até `message_stop`, com `event: ping` nas pausas e `event: error` em caso de falha.
- OpenAI Responses: eventos `response.*`, falha `response.failed`.
- Legacy Completions: em caso de falha, `data: {"error": …}` e depois `[DONE]`.

## Chamada de ferramentas

- Formato OpenAI: `tools` e `tool_choice`. O formato antigo `functions` e `function_call` também é aceito, e a resposta vem nele mesmo.
- No streaming, uma chamada por chunk: clientes que leem apenas o primeiro elemento não perdem chamadas.
- O histórico com o qual a rede retornaria um erro `400` o gateway corrige: o papel `developer` vira `system`, ids de chamada vazios e repetidos recebem valores únicos, `arguments` como objeto vira string JSON, o `type` ausente é preenchido, e uma chamada sem nome é removida junto com o resultado.
- A chamada que o modelo escreveu como marcação no texto o gateway move para `tool_calls`; chamadas falsas na resposta a uma requisição sem ferramentas ele remove.
- A geração foi interrompida no meio dos argumentos: virá `finish_reason: length`, e não `tool_calls`; aumente o limite da resposta.

```json
{
  "model": "MiniMaxAI/MiniMax-M2.7",
  "messages": [{"role": "user", "content": "What is the weather in Paris?"}],
  "tools": [{
    "type": "function",
    "function": {
      "name": "get_weather",
      "description": "Current weather for a city",
      "parameters": {
        "type": "object",
        "properties": {"city": {"type": "string"}},
        "required": ["city"]
      }
    }
  }]
}
```

### Restrições de JSON-Schema

Os esquemas das ferramentas e `response_format` a rede compila em uma gramática; as expressões regulares usam o motor RE2. O gateway ajusta o esquema à forma que a rede aceita:

- Os `$ref` são expandidos no lugar, as seções `$defs` e `definitions` são removidas; uma referência recursiva vira um esquema sem restrições.
- O `pattern` com construções que não existem no RE2 (lookahead e lookbehind, referências anteriores, grupos atômicos, quantificadores possessivos) é removido; repetições maiores que 1000 são reduzidas a 1000.
- `anyOf` e `oneOf` de constantes são colapsados em `enum`; se houver mais de 16 ramos não colapsáveis, a união é removida.

> O esquema pode ficar mais permissivo que o original: valide os argumentos da chamada do seu lado.

## Resposta estruturada

`response_format`: `{"type": "json_object"}` para uma resposta JSON válida, `{"type": "json_schema", "json_schema": {"name": …, "schema": …}}` conforme o seu esquema com as restrições acima. O JSON truncado sem streaming é corrigido pelo plugin `response-healing`.

```json
{
  "model": "MiniMaxAI/MiniMax-M2.7",
  "messages": [{"role": "user", "content": "Name three planets."}],
  "response_format": {
    "type": "json_schema",
    "json_schema": {
      "name": "planets",
      "schema": {
        "type": "object",
        "properties": {"planets": {"type": "array", "items": {"type": "string"}}},
        "required": ["planets"]
      }
    }
  }
}
```

## Raciocínio

- O raciocínio do modelo chega separado da resposta: `message.reasoning_content`, e no streaming `delta.reasoning_content`. O campo `reasoning` o gateway renomeia para esse formato.
- O raciocínio consome `max_tokens`: com um limite pequeno a resposta é cortada (`finish_reason: length`) antes mesmo do texto.
- Se não há texto de resposta mas há raciocínio, o gateway o move para `content`, exceto em respostas com chamada de ferramenta.
- `reasoning_effort` e `reasoning.effort` são repassados à rede. Se o modelo tem apenas dois modos, o gateway ajusta o valor a eles: `none` e `minimal` para `low`, os mais altos para o raciocínio padrão.
- Se o nó rejeitar o valor, o gateway o rebaixa (`max` e `xhigh` → `high`, `minimal` → `low`, ou então remove o campo) e repete a requisição.
- Em `/v1/messages` o raciocínio não é repassado: não há blocos `thinking`.

## Plugins

Os plugins são ativados pelo campo `plugins`: um array de strings ou de objetos com opções. A lista está em `GET /v1/plugins`.

| Plugin | Descrição | Condições |
| --- | --- | --- |
| `response-healing` | Corrige o JSON truncado na resposta do modelo. | Somente sem streaming e se a resposta começar com `{` ou `[`. |
| `privacy-sanitization` | Mascara em mensagens de texto emails, IPv4, números de cartão, JWT, chaves hex de 64 caracteres e chaves no formato `sk-…`, `gw_…`, `gm-…`, `Bearer …`. | O modo é o campo `privacy_mode`: `redact` (padrão) ou `tokenize`. |
| `file-parser` | Extrai o texto de um PDF. | Se o texto da mensagem for inteiramente um PDF em base64: `data:application/pdf;base64,…` ou sem prefixo. |
| `web` | Busca na web: os resultados são incorporados à requisição e a resposta recebe links para as fontes. | Junto com `privacy-sanitization`, erro `400`. |

### Busca na web

- Opções: `max_results`, de 1 a 10, padrão 5; `engine`, dica de mecanismo; `search_prompt`, texto próprio antes dos resultados; `enabled: false`, desativar a busca.
- As fontes estão em `message.annotations[].url_citation`; no streaming, no chunk `joingonka-citations` antes do encerramento.
- `mode: "agent"`: o modelo decide por conta própria se deve buscar e o quê; `max_searches`, de 1 a 5, padrão 3.
- Pagamento: no modo normal, apenas tokens (os resultados de busca entram nos tokens de entrada); no modo agente, os tokens de todas as etapas mais 1000 nGNK por cada busca realizada (`x_joingonka.web_search_surcharge_ngonka`).
- No Anthropic Messages e no OpenAI Responses, a ferramenta integrada `web_search` executa esse mesmo plugin no modo agente.

#### plugins: web

```json
{
  "model": "MiniMaxAI/MiniMax-M2.7",
  "messages": [{"role": "user", "content": "What is new in the Gonka network?"}],
  "plugins": [{"id": "web", "max_results": 5}]
}
```

#### mode: agent

```json
{
  "model": "MiniMaxAI/MiniMax-M2.7",
  "messages": [{"role": "user", "content": "What is new in the Gonka network?"}],
  "plugins": [{"id": "web", "mode": "agent", "max_searches": 3}]
}
```

## Custo e campos de serviço

A resposta sem streaming traz o custo da requisição em `usage`:

| Campo | Descrição |
| --- | --- |
| `usage.cost_gnk` | Custo da requisição em GNK |
| `usage.platform_fee_gnk` | Desse valor, a margem da plataforma, GNK |
| `usage.total_cost_gnk` | Total a debitar em GNK |
| `usage.total_cost_usd` | Total em dólares pela cotação atual do GNK |

- No streaming, `usage` contém apenas tokens; o custo está no chunk `joingonka-meta`.
- Com o cabeçalho `x-joingonka-meta: 1`, a resposta `POST /v1/chat/completions` recebe o bloco `x_joingonka`: custo (`cost_ngonka`), saldo após o débito (`balance_ngonka`, somente sem streaming) e timings (`ttft_ms`). Outros protocolos não retornam esse bloco.
- `x-request-id` — identificador da requisição: inclua-o ao falar com o suporte.
- `Retry-After` vem com `429`: quantos segundos esperar antes de tentar de novo.
- Os cabeçalhos `X-Title` e `HTTP-Referer` (como no OpenRouter) ajudam o gateway a identificar seu aplicativo; o texto deles não é armazenado.

## Limitações

- Imagens: as partes `image_url` são substituídas por um marcador de texto — o modelo não vê a imagem (`vision: false` nas capacidades).
- Do navegador, a API só é acessível a partir de domínios da JoinGonka (verificação `Origin`): chame-a do seu próprio servidor e não coloque a chave no frontend.
- Embeddings: `POST /v1/embeddings` responde `501` — não há modelos de embeddings na rede.
- Códigos de erro, limites e timeouts estão na seção [Erros e limites](https://gate.joingonka.ai/pt/docs/errors).
