> Pour les agents IA : guide de configuration étape par étape — [`/docs/agents.md`](https://gate.joingonka.ai/docs/agents.md), index de la documentation — [`/llms.txt`](https://gate.joingonka.ai/llms.txt).

# Référence API

Tout sur les requêtes adressées à la passerelle : protocoles, adresses, clés et paramètres. Ci-dessous — streaming, appel d'outils, raisonnement, plugins et coût de la requête dans la réponse.

## Protocoles et adresses

La passerelle accepte les formats OpenAI et Anthropic. L'URL de base pour le SDK OpenAI est `https://gate.joingonka.ai/v1`, pour le SDK Anthropic — `https://gate.joingonka.ai`. Tous les protocoles fonctionnent avec une seule clé et un seul solde : une requête dans n'importe quel format emprunte le même chemin.

| Méthode et chemin | Format | Usage | Particularités |
| --- | --- | --- | --- |
| `POST /v1/chat/completions` | OpenAI Chat Completions | Chat, agents, appels d'outils | Chemin principal : la passerelle y convertit tous les autres formats. |
| `POST /v1/messages` | Anthropic Messages | Claude Code et SDK Anthropic | URL de base sans `/v1` ; les modèles `claude-*` sont remplacés par le modèle recommandé ; le champ `max_tokens` est obligatoire. |
| `POST /v1/responses` | OpenAI Responses | Codex CLI et les nouveaux SDK OpenAI | Sans état : envoyez tout l'historique à chaque requête. |
| `POST /v1/completions` | OpenAI Completions (legacy) | Autocomplétion et correction de code dans les éditeurs | `suffix` est transmis au modèle comme indice ; la réponse contient `logprobs: null`. |
| `POST /v1/embeddings` | OpenAI Embeddings | Représentations vectorielles du texte | Réponse `501` : le réseau ne propose pas de modèles d'embeddings. |

### Adresses de référence

Répondent sans clé. Le tableau des modèles avec contexte et statut se trouve dans la section [Modèles](https://gate.joingonka.ai/fr/docs/models).

| Méthode et chemin | Description |
| --- | --- |
| `GET /v1/models` | Liste des modèles : contexte, prix, paramètres pris en charge — champs au format OpenRouter. |
| `GET /v1/models/{model}` | Fiche d'un modèle ; le slash dans l'id s'écrit tel quel ou `%2F`. Modèle masqué ou inconnu — `404 model_not_found`. |
| `GET /v1/capabilities` | Capacités de la passerelle : paramètres, protocoles, plugins, champs de coût et limites (`limits`). |
| `GET /v1/plugins` | Plugins : id et nom. |
| `GET /v1/network-status` | État des modèles du réseau : disponibilité, latences, uptime. |
| `GET /v1/nodes` | Résumé du pool de nœuds : total, actifs et en quarantaine. |
| `GET /v1/web-search/engines` | Si la recherche web est activée et dans quel état sont ses moteurs. |

### Anthropic Messages

- URL de base — `https://gate.joingonka.ai` : le SDK ajoutera `/v1/messages` lui-même.
- Clé — dans l'en-tête `x-api-key` (comme l'envoie le SDK Anthropic) ou `Authorization: Bearer`.
- Les modèles `claude-*` sont remplacés par la passerelle par le modèle recommandé (`MiniMaxAI/MiniMax-M2.7`) ; le champ `model` de la réponse conserve le nom envoyé par le client.
- `max_tokens` est obligatoire, comme dans l'API Anthropic ; au-delà du plafond du modèle — la valeur est tronquée.
- Stream — événements Anthropic ; pendant les pauses, la passerelle envoie `event: ping`, une erreur arrive via l'événement `event: error`.
- Les raisonnements du modèle n'apparaissent pas dans la réponse : pas de blocs `thinking`.
- L'outil intégré `web_search` est exécuté par le plugin de recherche web de la passerelle — voir la section [Plugins](https://gate.joingonka.ai/fr/docs/api#plugins).
- Pas de comptage de tokens (`/v1/messages/count_tokens`) — réponse `404`.

Claude Code se configure plus simplement avec l'installateur — [connexion des outils](https://gate.joingonka.ai/fr/docs#connect). Manuellement — via des variables d'environnement ; `ANTHROPIC_MODEL` fixe le modèle du réseau.

#### 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

- La passerelle ne stocke pas les réponses : envoyez tout l'historique dans `input`. Les champs `previous_response_id` et `conversation` — erreur `400` avec code.
- `store` est accepté sans rien changer.
- Outils : `function` et `web_search` — ce dernier est exécuté par le plugin de recherche web. Les autres outils intégrés sont ignorés par la passerelle et la requête s'exécute sans eux ; exiger un tel outil via `tool_choice` — erreur `400`.
- Les parties `input_image` et `input_file` — erreur `400` : les modèles du réseau travaillent avec du texte.
- Les adresses d'état (`GET /v1/responses/{id}`, `DELETE /v1/responses/{id}`, `GET /v1/responses/{id}/input_items`, `POST /v1/responses/{id}/cancel`, `POST /v1/responses/compact`) répondent `404` avec code — la passerelle ne stocke pas les réponses.
- Codex CLI : définissez votre propre id de fournisseur dans `model_provider` (pas openai) — Codex compresse alors l'historique lui-même, sans `/v1/responses/compact`.

### Legacy Completions

- `prompt` — une chaîne ou un tableau d'une seule chaîne ; la réponse est dans `choices[].text`. Plusieurs prompts ou des tokens à la place du texte — erreur `400`.
- `suffix` est transmis au modèle comme indice dans le prompt : le réseau ne fait pas de vrai remplissage du milieu (fill-in-the-middle).
- La réponse contient `logprobs: null` ; `best_of` est ignoré ; `echo` fonctionne.

## Clés et autorisation

La clé se transmet dans l'en-tête `Authorization: Bearer jg-…` ou `x-api-key: jg-…` — sur toutes les adresses. La clé se crée après inscription sur la page [gate.joingonka.ai/keys](https://gate.joingonka.ai/keys).

| Préfixe | Clé | Requêtes vers les modèles |
| --- | --- | --- |
| `jg-` | Clé de compte classique | oui |
| `gc-` | Clé enfant : limites propres, dépenses débitées du solde du propriétaire | oui |
| `gm-` | Clé de gestion : uniquement la gestion des clés enfants | non — `403 forbidden` |

- Chaque clé peut avoir une limite de dépenses par jour, par mois et au total dans l'espace client ; dépassement — `402 child_key_limit_exceeded`.
- Le nombre de requêtes par minute par clé est limité — les valeurs se trouvent dans la section [Limites](https://gate.joingonka.ai/fr/docs/errors#limits).
- Sans clé, seul le chat démo du site fonctionne : une requête sans clé depuis votre code recevra `402` avec `is_demo`.
- Les clés se gèrent uniquement dans l'espace client : `/api/keys` avec une clé API est inaccessible. Solde et dépenses par clé — [API du compte](https://gate.joingonka.ai/fr/docs/billing#account-api).

> La clé est un secret : ne la stockez ni dans le dépôt ni dans le code front-end, transmettez-la via des variables d'environnement.

## Exemples

Une même requête dans quatre SDK. Modèle recommandé (`MiniMaxAI/MiniMax-M2.7`), clé issue de la variable d'environnement `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)
```

### Réponse en 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)
```

## Paramètres de requête

Paramètres de `POST /v1/chat/completions` que la passerelle garantit elle-même — la liste `supported_parameters` dans la réponse de capacités :

| Paramètre | Description |
| --- | --- |
| `temperature` | Aléa de la réponse : plus il est élevé, plus la réponse est variée. |
| `top_p` | Sélection des tokens par probabilité cumulée. |
| `top_k` | Sélection parmi les k tokens les plus probables. |
| `min_p` | Élimination des tokens peu probables par rapport au plus probable. |
| `frequency_penalty` | Pénalité pour les répétitions fréquentes. |
| `presence_penalty` | Pénalité pour les tokens déjà apparus. |
| `repetition_penalty` | Multiplicateur anti-répétition. |
| `stop` | Chaînes sur lesquelles la génération s'arrête. |
| `seed` | Graine pour la reproductibilité. |
| `max_tokens` | Limite de tokens de la réponse ; au-delà du plafond du modèle, elle est ramenée au plafond. |
| `max_completion_tokens` | Autre nom pour `max_tokens` : la passerelle y reporte la valeur. |
| `tools` | Fonctions que le modèle peut appeler, au format OpenAI. |
| `tool_choice` | Faut-il appeler une fonction : au choix du modèle, jamais, obligatoirement ou une fonction précise. |
| `response_format` | Réponse structurée : `json_object` ou `json_schema`. |

- Sans `temperature`, la passerelle applique `0.7`.
- Sans `max_tokens`, la passerelle applique la valeur par défaut du modèle : plus courte hors streaming, plafond du modèle en streaming. Les valeurs chiffrées par modèle sont dans la section [Limites](https://gate.joingonka.ai/fr/docs/errors#limits).

### Transmis au réseau tel quel

`reasoning_effort`, `reasoning`, `enable_thinking`, `chat_template_kwargs`, `thinking_token_budget`, `min_tokens`, `logit_bias`, `n`, `parallel_tool_calls`, `extra_body`. La passerelle ne les vérifie pas : une valeur hors de la liste du réseau renvoie une erreur `400` de type `api_error`.

### Non transmis au réseau

Les autres champs sont acceptés par la passerelle mais non transmis au réseau — par exemple `user`, `metadata`, `store`, `logprobs`, `top_logprobs`, `thinking`, `stream_options`, `web_search_options`. `usage` arrive toujours en streaming.

## Streaming

- `stream: true` — réponse sous forme d'événements SSE ; le dernier événement est `data: [DONE]`.
- Avant la fin, un chunk contenant `usage` arrive — toujours, même sans `stream_options`.
- Pendant les pauses, la passerelle envoie toutes les 15 s un commentaire `: keep-alive` — les clients SSE l'ignorent.
- Tant que le flux n'est pas ouvert, un refus arrive via un code de réponse classique ; une fois ouvert, via un chunk `joingonka-error`.
- Dans `delta.tool_calls` — un appel par chunk : les appels fusionnés par le réseau sont découpés par la passerelle.

```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 de service de la passerelle

On les reconnaît au champ `id` :

| `id` | Quand et quoi dedans |
| --- | --- |
| `joingonka-error` | Échec après l'ouverture du flux : champ `error`, puis coupure sans `[DONE]`. |
| `joingonka-stream-stalled` | Le réseau est resté silencieux au-delà de la pause autorisée : le flux se ferme avec `finish_reason: stop`. |
| `joingonka-stream-unfinished` | Le réseau a interrompu la génération : `finish_reason: length` — reprenez avec une requête suivante. |
| `joingonka-citations` | Sources de la recherche web dans `delta.annotations` — avant la fin. |
| `joingonka-meta` | Coût et timings — uniquement avec l'en-tête `x-joingonka-meta: 1`. |

### Streaming dans d'autres protocoles

- Anthropic Messages : événements de `message_start` à `message_stop`, `event: ping` pendant les pauses, échec — `event: error`.
- OpenAI Responses : événements `response.*`, échec — `response.failed`.
- Legacy Completions : en cas d'échec — `data: {"error": …}`, puis `[DONE]`.

## Appel d'outils

- Format OpenAI : `tools` et `tool_choice`. L'ancien format `functions` et `function_call` est aussi accepté — la réponse arrivera dans ce même format.
- En streaming — un appel par chunk : les clients qui ne lisent que le premier élément ne perdent pas d'appels.
- L'historique sur lequel le réseau renverrait une erreur `400` est corrigé par la passerelle : le rôle `developer` devient `system`, les id d'appels vides ou en doublon reçoivent des identifiants uniques, `arguments` sous forme d'objet est converti en chaîne JSON, le `type` manquant est complété, un appel sans nom est supprimé avec son résultat.
- Un appel que le modèle a écrit en balisage dans le texte est déplacé par la passerelle dans `tool_calls` ; les faux appels dans une réponse à une requête sans outils sont supprimés.
- La génération s'est interrompue au milieu des arguments — c'est `finish_reason: length` qui arrive, pas `tool_calls` : augmentez la limite de réponse.

```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"]
      }
    }
  }]
}
```

### Contraintes JSON-Schema

Les schémas d'outils et `response_format` sont compilés en grammaire par le réseau ; les expressions régulières par le moteur RE2. La passerelle ramène le schéma à une forme acceptable par le réseau :

- Les `$ref` sont développées sur place, les sections `$defs` et `definitions` sont supprimées ; une référence récursive devient un schéma sans contraintes.
- `pattern` contenant des constructions absentes de RE2 (lookahead, lookbehind, rétroréférences, groupes atomiques, quantificateurs possessifs) est retiré ; les répétitions supérieures à 1000 sont réduites à 1000.
- `anyOf` et `oneOf` composés de constantes sont repliés en `enum` ; si les branches non repliables dépassent 16, l'union est supprimée.

> Le schéma peut devenir plus permissif que l'original — validez les arguments d'appel de votre côté.

## Réponse structurée

`response_format` : `{"type": "json_object"}` — réponse en JSON valide, `{"type": "json_schema", "json_schema": {"name": …, "schema": …}}` — selon votre schéma avec les contraintes ci-dessus. Le JSON tronqué hors streaming est corrigé par le 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"]
      }
    }
  }
}
```

## Raisonnement

- Le raisonnement du modèle arrive séparément de la réponse : `message.reasoning_content`, en streaming — `delta.reasoning_content`. Le champ `reasoning` est renommé par la passerelle dans ce format.
- Le raisonnement consomme `max_tokens` : avec une limite basse, la réponse se coupe (`finish_reason: length`) avant même le texte.
- Si la réponse ne contient pas de texte mais que le raisonnement est présent, la passerelle le reporte dans `content` — sauf pour les réponses avec appel d'outil.
- `reasoning_effort` et `reasoning.effort` sont transmis au réseau. Si le modèle n'a que deux modes, la passerelle y ramène la valeur : `none` et `minimal` → `low`, les valeurs plus élevées → raisonnement par défaut.
- Si un nœud rejette la valeur, la passerelle la rétrograde (`max` et `xhigh` → `high`, `minimal` → `low`, sinon elle retire le champ) et relance la requête.
- Dans `/v1/messages`, le raisonnement n'est pas transmis — pas de blocs `thinking`.

## Plugins

Les plugins s'activent via le champ `plugins` — tableau de chaînes ou d'objets avec options. La liste — `GET /v1/plugins`.

| Plugin | Description | Conditions |
| --- | --- | --- |
| `response-healing` | Corrige le JSON tronqué dans la réponse du modèle. | Uniquement hors streaming et si la réponse commence par `{` ou `[`. |
| `privacy-sanitization` | Masque dans les messages texte les emails, IPv4, numéros de carte, JWT, clés hex de 64 caractères et clés du type `sk-…`, `gw_…`, `gm-…`, `Bearer …`. | Mode — champ `privacy_mode` : `redact` (par défaut) ou `tokenize`. |
| `file-parser` | Extrait le texte d'un PDF. | Si le texte du message est intégralement un PDF en base64 : `data:application/pdf;base64,…` ou sans préfixe. |
| `web` | Recherche web : les résultats sont intégrés à la requête, la réponse reçoit des liens vers les sources. | Avec `privacy-sanitization` — erreur `400`. |

### Recherche web

- Options : `max_results` — de 1 à 10, par défaut 5 ; `engine` — indication du moteur ; `search_prompt` — texte personnalisé avant les résultats ; `enabled: false` — désactiver la recherche.
- Sources — dans `message.annotations[].url_citation` ; en streaming — via le chunk `joingonka-citations` avant la fin.
- `mode: "agent"` — le modèle décide lui-même s'il faut chercher et quoi ; `max_searches` — de 1 à 5, par défaut 3.
- Facturation : en mode normal — uniquement les tokens (les résultats de recherche sont inclus dans les tokens d'entrée) ; en mode agent — les tokens de toutes les étapes plus 1000 nGNK par recherche effectuée (`x_joingonka.web_search_surcharge_ngonka`).
- Dans Anthropic Messages et OpenAI Responses, l'outil intégré `web_search` exécute ce même plugin en mode agent.

#### 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}]
}
```

## Coût et champs de service

Une réponse non-streaming indique le coût de la requête dans `usage` :

| Champ | Description |
| --- | --- |
| `usage.cost_gnk` | Coût de la requête en GNK |
| `usage.platform_fee_gnk` | Dont marge de la plateforme, GNK |
| `usage.total_cost_gnk` | Total à débiter en GNK |
| `usage.total_cost_usd` | Total en dollars au taux actuel du GNK |

- En streaming, `usage` ne contient que les tokens ; le coût se trouve dans le chunk `joingonka-meta`.
- Avec l'en-tête `x-joingonka-meta: 1`, la réponse `POST /v1/chat/completions` inclut un bloc `x_joingonka` : coût (`cost_ngonka`), solde après débit (`balance_ngonka`, uniquement hors streaming) et timings (`ttft_ms`). Les autres protocoles ne renvoient pas ce bloc.
- `x-request-id` — identifiant de la requête : joignez-le à toute demande au support.
- `Retry-After` accompagne un `429` : nombre de secondes à attendre avant de réessayer.
- Les en-têtes `X-Title` et `HTTP-Referer` (comme chez OpenRouter) aident la passerelle à identifier votre application ; leur contenu n'est pas conservé.

## Limites

- Images : les parties `image_url` sont remplacées par un texte de substitution — le modèle ne voit pas l'image (`vision: false` dans les capacités).
- Depuis un navigateur, l'API n'est accessible que depuis les domaines JoinGonka (vérification `Origin`) : appelez-la depuis votre serveur, ne placez jamais la clé dans le frontend.
- Embeddings : `POST /v1/embeddings` renvoie `501` — aucun modèle d'embedding n'est disponible sur le réseau.
- Codes d'erreur, limites et timeouts — dans la section [Erreurs et limites](https://gate.joingonka.ai/fr/docs/errors).
