Référence de l'API
Les sept routes, une par une : ce que vous envoyez, ce que vous recevez, et pour chaque paramètre s'il est pris en charge, ignoré ou refusé.
Toutes les routes sont sous https://app.netaix.fr/v1 et demandent une clé (voir Authentification). Une description lisible par une machine est disponible : openapi.json.
GET /v1/models
Aucun paramètre. Rend la liste des niveaux Netaix puis celle des modèles que la clé peut appeler. Le détail de la réponse et la façon de l'utiliser sont dans Modèles et routage.
POST /v1/chat/completions
La route principale. Elle suit le format d'OpenAI pour la requête comme pour la réponse.
Paramètres
Les champs inconnus sont acceptés sans erreur, comme le fait l'API d'origine. La colonne « État » dit ce que la passerelle en fait réellement : un paramètre marqué « ignoré » est accepté mais n'a aucun effet, ce qu'il valait mieux écrire que laisser découvrir.
| Champ | Type | État | Détail |
|---|---|---|---|
model | chaîne, requis | Pris en charge | Un niveau netaix-* ou un identifiant de modèle. 200 caractères au plus. |
messages | tableau, requis | Pris en charge | 200 messages au plus. Rôles system, user, assistant, tool. Le contenu peut être une chaîne ou une liste de blocs. |
stream | booléen | Pris en charge | Défaut false. Voir le flux. |
temperature | nombre, 0 à 2 | Pris en charge | Transmis au modèle. |
max_tokens | entier, 1 à 128000 | Pris en charge | Transmis au modèle. |
tools | tableau | Pris en charge | Un tour d'inférence. Voir les outils. |
tool_choice | chaîne ou objet | Pris en charge | Transmis avec tools. |
top_p | nombre, 0 à 1 | Accepté, ignoré | Validé puis non transmis au modèle. |
response_format | objet | Accepté, ignoré | Aucun mode JSON imposé. Pour obtenir du JSON, demandez-le dans la consigne, ou utilisez tools dont le schéma, lui, est transmis. |
n, stop, seed, logprobs, presence_penalty, frequency_penalty | divers | Accepté, ignoré | Une seule réponse est rendue, sans séquence d'arrêt côté passerelle. |
stream_options | objet | Accepté, inutile | Le bloc usage est déjà envoyé sur le dernier fragment de tout flux. |
Réponse
{
"id": "chatcmpl-...",
"object": "chat.completion",
"created": 1793664000,
"model": "mistral-large-latest",
"choices": [{
"index": 0,
"message": {"role": "assistant", "content": "..."},
"finish_reason": "stop"
}],
"usage": {
"prompt_tokens": 1240,
"completion_tokens": 318,
"total_tokens": 1558,
"prompt_tokens_details": {"cached_tokens": 980},
"cache_write_tokens": 0
}
}
| Champ | Ce qu'il porte |
|---|---|
model | Le modèle réellement servi, même quand vous avez demandé un niveau. |
finish_reason | stop, ou tool_calls quand le modèle demande un outil. |
usage.prompt_tokens | Jetons d'entrée hors part relue depuis le cache du fournisseur. |
usage.prompt_tokens_details.cached_tokens | Part d'entrée relue depuis le cache du fournisseur. |
usage.cache_write_tokens | Jetons écrits dans le cache du fournisseur. Ajout Netaix, hors norme OpenAI. |
Le flux
Avec "stream": true, la réponse est un flux d'événements serveur (text/event-stream). Chaque ligne utile commence par data: et porte un objet chat.completion.chunk. Le flux se termine par data: [DONE].
data: {"id":"chatcmpl-...","object":"chat.completion.chunk","created":1793664000,"model":"gpt-4.1","choices":[{"index":0,"delta":{"role":"assistant","content":"Bon"},"finish_reason":null}]}
data: {"id":"chatcmpl-...","object":"chat.completion.chunk","created":1793664001,"model":"gpt-4.1","choices":[{"index":0,"delta":{"content":"jour"},"finish_reason":null}]}
data: {"id":"chatcmpl-...","object":"chat.completion.chunk","created":1793664002,"model":"gpt-4.1","choices":[{"index":0,"delta":{},"finish_reason":"stop"}],"usage":{"prompt_tokens":18,"completion_tokens":2,"total_tokens":20,"prompt_tokens_details":{"cached_tokens":0},"cache_write_tokens":0}}
data: [DONE]
- Le premier fragment de texte porte
delta.role. Les suivants ne portent quedelta.content. - Le dernier fragment porte
finish_reasonet le blocusage, sans qu'il faille le demander. - Quand une recherche web a servi, un fragment supplémentaire porte un champ
search_resultsde premier niveau, avecdeltavide. C'est la convention employée par les fournisseurs qui exposent leurs sources ; un client strict l'ignore. - Une erreur survenue après le début du flux arrive sous la forme
data: {"error": {...}}, suivie dedata: [DONE]. Le code HTTP, lui, est déjà parti en200: votre code doit donc inspecter les fragments, pas seulement le statut.
Si vous écrivez votre propre lecteur plutôt que d'utiliser un SDK, traitez le cas du fragment d'erreur en cours de flux. Un lecteur qui ne regarde que le statut HTTP affichera une réponse tronquée comme une réponse complète.
Les outils
Envoyez vos définitions dans tools au format OpenAI. La passerelle fait un tour d'inférence et vous rend les tool_calls demandés par le modèle. Elle n'exécute pas vos outils : c'est votre code qui les exécute, puis renvoie le résultat dans un message de rôle tool au tour suivant. C'est le fonctionnement standard, en flux comme en bloc.
{
"choices": [{
"index": 0,
"message": {
"role": "assistant",
"content": null,
"tool_calls": [{
"id": "call_...",
"type": "function",
"function": {"name": "chercher_facture",
"arguments": "{\"numero\": \"F-2026-114\"}"}
}]
},
"finish_reason": "tool_calls"
}]
}
POST /v1/messages
La même passerelle, au format de l'API d'Anthropic. Elle sert les clients écrits pour ce format, Claude Code et le SDK anthropic compris, usage agent inclus. Avec un SDK Anthropic, l'adresse de base est https://app.netaix.fr sans /v1 : le SDK ajoute le chemin lui-même.
Les deux routes sont servies par le même moteur : facturation, filtre des données sensibles, appels d'outils, comptage des jetons et comportement en cas d'erreur sont identiques sur /v1/chat/completions et ici. Le choix de la route est donc celui du format que parle votre client, pas celui des fonctionnalités disponibles.
| Champ | Type | État |
|---|---|---|
model | chaîne, requis | Pris en charge, niveaux compris. 200 caractères au plus. |
messages | tableau, requis | Pris en charge, 2 000 messages au plus. Blocs text, image, tool_use et tool_result transmis sans aplatissement. |
system | chaîne ou liste de blocs | Pris en charge dans les deux formes. Examiné par le filtre des données sensibles comme les messages. |
stream | booléen | Pris en charge. Défaut false. |
max_tokens | entier, 1 à 128000 | Pris en charge. Défaut 4096. |
temperature | nombre, 0 à 2 | Pris en charge, transmis au modèle. |
top_p | nombre, 0 à 1 | Pris en charge, transmis au modèle. |
tools | tableau, 256 au plus | Pris en charge. Un tour d'inférence : la passerelle rend les blocs tool_use, c'est votre code qui exécute les outils. |
tool_choice | objet | Pris en charge, transmis avec tools. |
stop_sequences | tableau, 16 au plus | Pris en charge, appliquées par la passerelle : le texte est coupé au premier motif rencontré et l'appel au modèle est refermé, pour ne pas payer la suite. |
{
"id": "msg_...",
"type": "message",
"role": "assistant",
"content": [
{"type": "text", "text": "Je lis le fichier."},
{"type": "tool_use", "id": "toolu_...",
"name": "read_file", "input": {"path": "a.txt"}}
],
"model": "claude-sonnet-4-5",
"stop_reason": "tool_use",
"stop_sequence": null,
"usage": {
"input_tokens": 1240,
"output_tokens": 318,
"cache_read_input_tokens": 980,
"cache_creation_input_tokens": 0
}
}
stop_reason | Quand |
|---|---|
end_turn | Le modèle a terminé sa réponse. |
tool_use | Le modèle demande un outil : exécutez-le et renvoyez un tool_result au tour suivant. |
max_tokens | La réponse a atteint la borne demandée. |
stop_sequence | Un de vos stop_sequences a été rencontré. Le motif vu est dans stop_sequence. |
Le flux
Avec "stream": true, la réponse suit le protocole de flux d'Anthropic : chaque événement porte sa ligne event: puis sa ligne data:, ce qui permet à un SDK Anthropic de le lire sans adaptation.
message_start
ping
content_block_start (un bloc text, ou un bloc tool_use)
content_block_delta (text_delta, ou input_json_delta pour un outil)
content_block_stop
message_delta (porte stop_reason, stop_sequence et usage)
message_stop
message_startetpingsont émis avant le premier appel au modèle : ils ne sont pas du contenu.- Les blocs sont indexés dans leur ordre d'apparition. Un appel d'outil émet ses arguments par fragments, en
input_json_delta. - Une erreur survenue pendant le flux arrive sous la forme d'un événement
error, le code HTTP étant déjà parti en200: votre code doit inspecter les événements, pas seulement le statut.
POST /v1/messages/count_tokens
Rend une estimation du nombre de jetons d'entrée d'une requête /v1/messages. C'est la route qu'un client au format Anthropic appelle pour gérer sa fenêtre de contexte. Le corps est celui de /v1/messages ; max_tokens n'est pas nécessaire.
{"input_tokens": 1284}
- Le compte porte sur la consigne système, les messages, les arguments des appels d'outils rejoués et les définitions d'outils.
- C'est une estimation faite par la passerelle, pas le compte exact d'un fournisseur : aucun modèle n'est appelé. Utilisez-la comme un ordre de grandeur, pas comme une valeur de facturation. Le compte réel d'un appel est dans le bloc
usagede sa réponse. - L'appel n'est pas décompté en crédits. Il demande une clé et compte dans la limite de débit.
POST /v1/embeddings
Transforme du texte en vecteurs, au format d'OpenAI.
| Champ | Type | État |
|---|---|---|
input | chaîne ou tableau de chaînes, requis | Pris en charge |
model | chaîne | Pris en charge. Par défaut, le modèle d'embeddings de la passerelle. Doit être un modèle d'embeddings du catalogue, sinon 404. |
encoding_format | float ou base64 | Pris en charge. Tout autre valeur donne un 400. |
dimensions | entier | Refusé par un 400 : les modèles disponibles rendent des vecteurs de taille fixe, et l'ignorer en silence remplirait votre index de vecteurs de la mauvaise taille. |
| Limite | Valeur | Code de refus |
|---|---|---|
| Entrées par requête | 96 | too_many_inputs |
| Caractères par entrée | 32 000 | input_too_long |
| Caractères au total | 400 000 | request_too_large |
| Jetons déjà découpés | non acceptés, envoyez du texte | input_must_be_text |
curl https://app.netaix.fr/v1/embeddings \
-H "Authorization: Bearer $NETAIX_API_KEY" \
-H "Content-Type: application/json" \
-d '{"input": ["Première phrase.", "Deuxième phrase."]}'
{
"object": "list",
"model": "mistral-embed",
"data": [
{"object": "embedding", "index": 0, "embedding": [0.0123, -0.0456]},
{"object": "embedding", "index": 1, "embedding": [0.0789, -0.0012]}
],
"usage": {"prompt_tokens": 12, "total_tokens": 12}
}
Un vecteur dépend du modèle qui l'a produit. Si vous changez de modèle d'embeddings, il faut recalculer tout l'index : des vecteurs de deux modèles ne se comparent pas. Fixez donc model explicitement dès que vous constituez un index durable.
POST /v1/moderations
Rend un verdict de modération sur un texte, au format d'OpenAI. Le champ input accepte une chaîne ou une liste de blocs.
{
"id": "modr-...",
"model": "omni-moderation-latest",
"results": [{
"flagged": false,
"categories": {"violence": false, "hate": false},
"category_scores": {"violence": 0.0002, "hate": 0.0001}
}]
}
Quand aucun verdict ne peut être produit, la route répond 503 avec le code moderation_unavailable, jamais un verdict « non signalé » par défaut. Votre code ne doit pas lire un 503 comme un contenu acceptable : c'est l'absence de verdict, pas un verdict favorable.
Cet appel n'est pas décompté en crédits. Il est compté dans le relevé de consommation de votre clé et soumis à la limite de débit, comme les autres routes.
La modération juge la nature du texte (violence, haine). Ce n'est pas le filtre des données sensibles, qui empêche une donnée confidentielle de sortir et s'applique, lui, aux quatre routes qui transmettent du texte : voir Filtre des données sensibles.
GET /v1/netaix/usage
La consommation et les plafonds de la clé qui appelle, sans session ni mot de passe. C'est la route à utiliser pour afficher une jauge dans votre propre interface, ou pour qu'un traitement automatique sache qu'il approche de son plafond avant de se faire refuser.
Aucun paramètre : l'identité vient de la clé, jamais de la requête. Une clé ne lit que sa propre consommation, jamais celle d'une autre clé ni celle de l'organisation.
{
"object": "netaix.usage",
"unite": "credits",
"cle": {"prefixe": "...", "type": "personal_token"},
"jour": {
"debut": "2026-11-03T00:00:00Z",
"consomme": 1240,
"plafond": 5000,
"restant": 3760,
"part": 0.248,
"alerte": false,
"depasse": false
},
"cycle": {
"debut": "2026-11-01T00:00:00Z",
"consomme": 8120,
"plafond": 20000,
"restant": 11880,
"part": 0.406,
"alerte": false,
"depasse": false
},
"verifie_a": "2026-11-03T09:14:22Z"
}
| Champ | Ce qu'il porte |
|---|---|
unite | Toujours credits. Jamais des euros, jamais des jetons. |
cle.prefixe | Le début de votre clé, celui que l'application affiche pour vous permettre de la reconnaître. Jamais la clé entière. |
cle.type | personal_token pour un jeton d'accès personnel, workspace_key pour une clé d'organisation. |
jour, cycle | Les deux fenêtres de plafond de la clé. jour part de minuit, heure universelle ; cycle du début du cycle de facturation en cours. |
debut | Le début de la fenêtre, en heure universelle. |
consomme | Les crédits déjà consommés par cette clé dans la fenêtre. |
plafond | Le plafond réglé sur la clé pour cette fenêtre, ou null quand elle n'en a pas. |
restant, part | Ce qui reste, et la part consommée entre 0 et 1. null tous les deux quand il n'y a pas de plafond : un plafond absent n'est pas un plafond à zéro. |
alerte | true à partir de 80 % du plafond, tant qu'il n'est pas dépassé. |
depasse | true quand la fenêtre est au plafond : les appels de cette clé sont refusés par un 429 jusqu'à sa réouverture. |
verifie_a | L'instant de la lecture, en heure universelle. Aucune valeur n'est mise en cache. |
Ces chiffres sont calculés par la même fonction que celle qui refuse les appels au dépassement et que celle qui alimente le relevé de l'application. Ce que vous lisez ici est donc ce qui s'appliquera, pas une estimation parallèle.
Cette route est limitée à 30 requêtes par minute, et non 60 comme les autres. Elle n'est pas décomptée en crédits. Elle ne répond que pour une clé d'API : une instance d'agent ou une application cliente, qui n'ont pas de plafond de clé, reçoivent un 400 avec le code usage_not_available_for_this_credential.