Référence de l'API d'IA

Tous les endpoints d'api.nodion.ai/v1, avec leurs limites et leurs erreurs.

URL de base : https://api.nodion.ai/v1. L'API suit le format d'OpenAI : les SDK OpenAI fonctionnent si vous les configurez avec cette URL de base. Pour les clés, le solde et les onglets du dashboard, consultez AI Inference. Les modèles, fournisseurs et prix figurent dans le catalogue des modèles.

pythonimport os
from openai import OpenAI

client = OpenAI(
    base_url="https://api.nodion.ai/v1",
    api_key=os.environ["NODION_AI_KEY"],
)
reply = client.chat.completions.create(
    model="<model>",
    messages=[{"role": "user", "content": "Hello"}],
)
print(reply.choices[0].message.content)

Authentification

Envoyez une clé d'inférence (nodion_ai_…) comme bearer token dans chaque requête. Les clés de plateforme (nodion_…) ne fonctionnent pas ici. GET /v1/models est le seul appel qui ne nécessite pas de clé.

httpAuthorization: Bearer nodion_ai_…

Une clé refusée entraîne une réponse 401 avec l'un de ces messages :

  • missing bearer token
  • invalid api key
  • api key expired
  • account disabled
  • account under review

Chaque réponse comporte un en-tête X-Request-ID. Indiquez-le lorsque vous contactez le support.

Les corps de requête JSON peuvent atteindre 25 MiB (outils 1 MiB, System One 512 KiB). L'encodage base64 augmente la taille des fichiers d'un tiers : un fichier intégré directement dans le JSON, comme une image, un PDF ou un document OCR, peut donc faire environ 18 MiB. Les envois multipart vers /v1/audio/transcriptions et /v1/audio/voices peuvent atteindre 25 MiB, avec des fichiers de transcription jusqu'à 20 MiB et des fichiers d'échantillon de voix jusqu'à 10 MiB (11 MiB pour l'ensemble du formulaire).

Endpoints

Endpoint Rôle Facturé selon
GET /v1/modelsListe les modèles facturés au tokenGratuit
POST /v1/chat/completionsChat, outils, sortie structuréeTokens d'entrée et de sortie
POST /v1/responsesOpenAI Responses API, par exemple pour CodexTokens d'entrée et de sortie
POST /v1/embeddingsEmbeddings vectorielsTokens d'entrée
POST /v1/rerankClasse des documents selon une requête de rechercheTokens d'entrée
POST /v1/systemoneSystem One : décisions typées avec probabilitésTokens d'entrée
POST /v1/ocrOCR de documents et d'imagesPages
POST /v1/audio/transcriptionsTranscription audio (speech-to-text)Secondes d'audio
GET /v1/audio/transcriptions/realtime (WebSocket)Transcription audio en temps réelSecondes d'audio
POST /v1/audio/speechSynthèse vocale (text-to-speech)Caractères
GET, POST /v1/audio/voicesListe et crée des voix clonéesGratuit
GET, DELETE /v1/audio/voices/{id}Lit ou supprime une voix clonéeGratuit
POST /v1/images/generationsGénération d'imagesImages
POST /v1/tools/web_search, web_news, web_fetch, web_images, web_videos, web_places, web_maps, web_shopping, web_lensOutils webAppels, plus chaque page chargée par un web_search

L'audio, les images et les outils sont décrits avec des exemples dans AI Inference. Les autres endpoints sont présentés ci-dessous.

Avant chaque appel, un montant correspondant au coût maximal estimé est réservé sur le solde. La requête est ensuite facturée selon l'usage déclaré, sans dépasser le montant réservé, et le reste est libéré. Si une réponse réussie ne déclare aucun usage, la totalité de la réservation est facturée. Une session de transcription en temps réel réserve le max_audio_seconds du modèle (1 800 secondes si le modèle n'en définit pas), donc le solde doit couvrir une session complète à l'avance.

Modèles

GET /v1/models renvoie {"object": "list", "data": [...]} et liste les modèles de chat, d'embeddings et de rerank. Les modèles OCR, vocaux, d'image et d'outils n'y figurent pas ; le catalogue public sur https://api.nodion.com/v2/public/ai/models liste tous les types. Champs utiles pour chaque modèle :

  • id : la valeur de model dans les requêtes.
  • kind : chat, embeddings ou rerank.
  • context_length et max_output_length en tokens.
  • pricing : prix en USD par token, sous forme de chaînes décimales. pricing_eur contient les prix en EUR.
  • supported_sampling_parameters et supported_features (par exemple tools, json_mode, structured_outputs, reasoning).
  • reasoning_efforts : les valeurs de reasoning_effort acceptées par ce modèle (par exemple none, low, high). Le champ est vide quand les niveaux ne sont pas configurables.
  • is_ready : false signifie qu'aucune route n'est opérationnelle pour le moment. Le modèle reste listé.
  • lifecycle : ga ou preview. serving : hosted (les poids tournent sur Nodion) ou routed (transmis à un fournisseur).
  • supports_decisions : le modèle répond à System One.
  • coding_plan : Codion peut proposer ce modèle de chat. La valeur est toujours true ou false. Ce champ ne désigne pas une offre de facturation.
  • free_until : présent tant qu'une période gratuite est active sur un modèle servi uniquement par Nodion. Les prix par token affichent alors 0.

Complétions de chat

POST /v1/chat/completions accepte le corps OpenAI Chat Completions : model, messages et les champs facultatifs que le modèle liste dans supported_sampling_parameters et supported_features, comme tools ou response_format. N'envoyez reasoning_effort que si reasoning_efforts n'est pas vide, et uniquement avec une valeur de cette liste.

bashcurl https://api.nodion.ai/v1/chat/completions \
  -H "Authorization: Bearer $NODION_AI_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "<model>",
    "stream": true,
    "max_tokens": 512,
    "messages": [
      {"role": "system", "content": "Answer in one sentence."},
      {"role": "user", "content": "What is an embedding?"}
    ]
  }'

Ce que la passerelle fait de la requête et de la réponse :

  • Sans max_tokens (ou max_completion_tokens), la passerelle fixe max_tokens au max_output_length du modèle. Les valeurs supérieures sont ramenées à cette limite.
  • Avec "stream": true, la réponse arrive en server-sent events (lignes data: {...}, puis data: [DONE]). La passerelle active stream_options.include_usage, donc le dernier chunk contient normalement l'usage. Si la connexion upstream est coupée en cours de stream, un dernier chunk porte un objet error et finish_reason: "error", suivi de data: [DONE].
  • Le champ model de la réponse est l'id que vous avez envoyé. Le texte de raisonnement, quand un modèle en renvoie, se trouve dans reasoning_content.

Les PDF peuvent être intégrés directement comme blocs de contenu file avec une URI de données en base64. La passerelle convertit les 20 premières pages en images avant l'appel, donc cela ne sert qu'avec les modèles qui acceptent des images en entrée. Les références file_id sont refusées.

json{
  "role": "user",
  "content": [
    {"type": "text", "text": "Summarize this contract."},
    {"type": "file", "file": {"file_data": "data:application/pdf;base64,JVBERi0..."}}
  ]
}

Facturation : tokens d'entrée et de sortie au prix du modèle, entrée en cache au prix du cache quand la route le déclare. La réservation compte chaque octet de la requête comme un token d'entrée, plus max_tokens. Pour les requêtes avec images ou PDF, la part d'entrée est portée à la longueur de contexte du modèle, ou à au moins 128 000 tokens si la requête dépasse le contexte. Pendant la période gratuite d'un modèle (free_until), les complétions de chat sur les routes hébergées sont gratuites.

Responses API

POST /v1/responses accepte le corps de l'OpenAI Responses API : model, input (du texte ou une liste d'items) et les champs facultatifs instructions, tools, tool_choice, parallel_tool_calls, text.format, reasoning.effort, max_output_tokens, max_tool_calls, temperature, top_p, top_logprobs, include et stream. La passerelle traduit la requête en complétion de chat : les règles de la section Complétions de chat s'appliquent aussi ici : le plafond de sortie, les reasoning_efforts autorisés, les PDF et la facturation.

bashcurl https://api.nodion.ai/v1/responses \
  -H "Authorization: Bearer $NODION_AI_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "<model>",
    "instructions": "Answer in one sentence.",
    "input": "What is an embedding?"
  }'

Avec "stream": true, la réponse est le flux d'événements de la Responses API, par exemple response.created, response.output_text.delta et response.function_call_arguments.delta, qui se termine par response.completed et son usage. Si le stream est interrompu, le dernier événement est response.failed. Le texte de raisonnement arrive dans un item reasoning sous forme de reasoning_text. Renvoyez cet item dans les requêtes suivantes : le raisonnement postérieur au dernier message de l'utilisateur est retransmis au modèle, le raisonnement plus ancien uniquement avec reasoning.context: "all_turns".

La passerelle exécute elle-même web_search, via la recherche web de Nodion. Quand le modèle lance une recherche, la passerelle récupère les résultats, les transmet au modèle et l'appelle à nouveau. La réponse contient un item web_search_call avec la requête de recherche et les URL des sources, diffusé en streaming avec les événements response.web_search_call.in_progress, searching et completed. Facturation : chaque recherche est facturée comme un appel à /v1/tools/web_search, et chaque tour du modèle comme une complétion de chat. usage est la somme de tous les tours. Une Response compte une seule fois dans la limite de requêtes de la clé. Au plus max_tool_calls recherches par Response (10 par défaut, 20 au maximum) ; max_output_tokens couvre l'ensemble des tours. filters.allowed_domains, user_location (ville, région, pays) et search_context_size (5, 10 ou 20 résultats) sont pris en compte. La recherche ne renvoie que des résultats de l'index de recherche (titre, URL, extrait) et n'ouvre aucune page, même avec external_web_access: true.

Logprobs : avec top_logprobs (jusqu'à 20) ou include: ["message.output_text.logprobs"], ils figurent sur output_text quand le modèle les renvoie.

Avec cette configuration, Codex CLI fonctionne avec Nodion, recherche web comprise :

toml# ~/.codex/config.toml
model = "<model>"
model_provider = "nodion"

[model_providers.nodion]
name = "Nodion"
base_url = "https://api.nodion.ai/v1"
env_key = "NODION_AI_KEY"
wire_api = "responses"

Différences avec OpenAI :

  • Nodion ne stocke aucune réponse. store est ignoré et la réponse indique store: false. Il n'y a ni previous_response_id, ni conversation, ni item_reference, ni GET /v1/responses/{id}. Envoyez toute la conversation dans input, comme le fait Codex.
  • Outils : function, custom, namespace et web_search. Les autres outils hébergés, comme file_search ou code_interpreter, sont refusés avec une erreur 400.
  • Les résultats de recherche ne sont pas stockés. Un web_search_call présent dans la conversation parvient au modèle sous forme d'appel accompagné d'une note, sans les anciens résultats. annotations (citations) reste vide ; les sources se trouvent dans le web_search_call.
  • Les images et les fichiers contenus dans les sorties d'outils ne parviennent pas au modèle ; une note dans le texte les remplace.
  • Non pris en charge (400) : background, prompt, truncation: "auto", file_id et file_url. Envoyez les images en image_url (une URL ou une data URI) et les PDF en input_file avec file_data.

Embeddings

POST /v1/embeddings accepte le corps OpenAI (model, input sous forme de chaîne ou de tableau) et renvoie la réponse embeddings d'OpenAI. Pas de streaming. Facturé sur usage.prompt_tokens. Utilisez un modèle avec kind: "embeddings".

bashcurl https://api.nodion.ai/v1/embeddings \
  -H "Authorization: Bearer $NODION_AI_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "<embeddings-model>", "input": ["first text", "second text"]}'

Rerank

POST /v1/rerank note des documents par rapport à une query. Le paramètre facultatif top_n limite le nombre de résultats. La réponse contient results avec index (position dans documents) et relevance_score, ainsi que usage.prompt_tokens, sur lequel porte la facturation. Utilisez un modèle avec kind: "rerank".

bashcurl https://api.nodion.ai/v1/rerank \
  -H "Authorization: Bearer $NODION_AI_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "<rerank-model>",
    "query": "How do I reset my password?",
    "documents": ["Billing FAQ", "Account recovery guide", "Release notes"],
    "top_n": 2
  }'

System One

POST /v1/systemone répond à des questions typées sur un état donné. Le modèle note chaque réponse possible au lieu d'écrire du texte, donc vous recevez des probabilités, pas de la prose. Utilisez-le pour le routage, le tri, la modération, ou comme point de contrôle avant qu'un agent n'exécute un outil. Un seul appel répond à 16 questions au maximum sur le même état.

Les modèles avec supports_decisions: true sur /v1/models prennent en charge System One. Celui-ci tourne sur des routes hébergées par Nodion et chez les fournisseurs qui proposent eux-mêmes System One. Si une route échoue avant d'avoir exécuté la requête (rate limit, panne), la même requête passe à la route suivante. L'onglet Decisions du Playground contient des exemples prêts à l'emploi.

bashcurl https://api.nodion.ai/v1/systemone \
  -H "Authorization: Bearer $NODION_AI_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "aleph-alpha/kolibri-1",
    "state": {
      "customer_tier": "enterprise",
      "ticket": "My checkout page shows a blank screen after I click Pay."
    },
    "questions": {
      "is_bug": {
        "type": "noul",
        "instructions": "Is the customer reporting a software defect?"
      },
      "team": {
        "type": "choice",
        "instructions": "Which team should own this ticket?",
        "criteria": {
          "payments": "Checkout, billing, or payment processing issues.",
          "frontend": "Rendering, layout, or browser issues.",
          "account": "Login, permissions, or profile issues."
        }
      },
      "urgency": {
        "type": "score",
        "instructions": "How urgent is this ticket?",
        "criteria": [
          "Can wait for the next release",
          "Should be fixed this week",
          "Blocking revenue right now"
        ]
      }
    }
  }'

Requête

  • model (obligatoire) : un modèle avec supports_decisions.
  • state (obligatoire) : ce sur quoi portent les questions. Une chaîne, un objet, un tableau ou null.
  • questions (obligatoire) : un objet de 1 à 16 entrées. La clé est le nom que vous donnez à la question (jusqu'à 128 caractères) et revient comme clé dans answers.

Chaque question a un type, des instructions facultatives et des criteria qui dépendent du type. Les valeurs de ces deux derniers champs peuvent être une chaîne, un objet ou un tableau ; null est accepté partout sauf pour les niveaux de score.

  • noul : une question oui/non. criteria est facultatif et ne peut avoir que les clés true et false. Un noul nécessite des instructions non vides ou au moins un critère non vide.
  • choice : choisir une étiquette. criteria associe de 1 à 26 étiquettes à une valeur ; les chaînes vides sont refusées. Les étiquettes doivent être uniques, sans tenir compte de la casse, et faire au plus 256 caractères.
  • score : noter sur une échelle. criteria est un tableau de 2 à 10 niveaux non vides, du plus bas au plus haut. Les index de niveau commencent à 0.

Les champs inconnus sont refusés. Le corps peut atteindre 512 KiB, et l'état ainsi que la plus grande question doivent tenir ensemble dans le contexte du modèle.

Réponse

json{
  "model": "aleph-alpha/kolibri-1",
  "answers": {
    "is_bug": {"type": "noul", "noul": 0.91},
    "team": {
      "type": "choice",
      "choice": "payments",
      "confidence": 0.78,
      "probabilities": {"payments": 0.82, "frontend": 0.15, "account": 0.03}
    },
    "urgency": {
      "type": "score",
      "score": 1.5,
      "confidence": 0.6,
      "legend": {
        "0": "Can wait for the next release",
        "1": "Should be fixed this week",
        "2": "Blocking revenue right now"
      },
      "probabilities": {"0": 0.1, "1": 0.3, "2": 0.6}
    }
  },
  "usage": {"input_tokens": 412, "output_tokens": 0}
}
  • noul : la probabilité que la réponse soit true, de 0 à 1.
  • choice : choice est l'étiquette la plus probable. probabilities contient toutes les étiquettes, avec une somme de 1, et confidence est une valeur de 0 à 1.
  • score : score est la moyenne des index de niveau pondérée par les probabilités (de 0 jusqu'au nombre de niveaux moins 1). probabilities et legend ont pour clés les index de niveau ; legend associe chaque index à la description d'un niveau. confidence est une valeur de 0 à 1.
  • model est le modèle qui a répondu. usage.output_tokens vaut toujours 0.

Les valeurs de l'exemple de réponse sont données à titre indicatif.

Facturation

Seuls les tokens d'entrée sont facturés, au tarif d'entrée du modèle. Le modèle lit l'état une fois par question : usage.input_tokens augmente avec le nombre de questions. Avant l'appel, un montant correspondant à (octets de l'état + octets de toutes les questions + 4 096) × le nombre de questions, au tarif des tokens d'entrée, est réservé sur le solde. La requête est ensuite facturée selon usage.input_tokens, jamais au-delà de la réservation. Les requêtes en échec ne sont pas facturées ; si vous vous déconnectez après que le modèle a répondu, ses tokens d'entrée sont facturés. Les périodes gratuites s'appliquent comme pour le chat.

Erreurs

System One utilise son propre corps d'erreur : {"detail": "message"} et, pour une erreur 422, une liste d'items loc / msg / type qui désignent le champ concerné.

json{
  "detail": [
    {"loc": ["body", "questions", "team", "criteria"], "msg": "choice accepts 1 to 26 criteria", "type": "too_long"}
  ]
}
  • 401 : clé absente ou invalide.
  • 402 : la facturation a refusé la requête (solde, limites de dépenses, ou requête impossible à tarifer). Les motifs sont ceux des codes 402, ici uniquement sous forme de texte dans detail.
  • 404 : model not found, y compris pour les modèles sans supports_decisions.
  • 422 : corps invalide, corps de plus de 512 KiB, état et questions dépassant le contexte, ou requête refusée par le modèle.
  • 429 : une limite de la clé a été atteinte (Retry-After: 5), ou toutes les routes de fournisseurs testées ont atteint leur rate limit (le Retry-After du fournisseur, 60 secondes au maximum).
  • 502 : le modèle n'a pas réussi à répondre.
  • 503 : aucune route opérationnelle, aucune qui corresponde aux paramètres de confidentialité du projet, ou les paramètres n'ont pas pu être chargés.
  • 529 : toutes les routes du modèle sont à pleine capacité. Retry-After: 5.

OCR

POST /v1/ocr suit le format Mistral OCR. Envoyez le fichier inline sous forme de data URI en base64 ; les URL distantes sont refusées. PDF, PNG, JPEG et WebP sont acceptés.

bashcurl https://api.nodion.ai/v1/ocr \
  -H "Authorization: Bearer $NODION_AI_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "mistral/mistral-ocr-4-1",
    "document": {
      "type": "document_url",
      "document_url": "data:application/pdf;base64,JVBERi0..."
    }
  }'
  • model : un modèle OCR du catalogue public (kind: "ocr").
  • document : {"type": "document_url", "document_url": "data:..."} ou {"type": "image_url", "image_url": "data:..."}.
  • pages (facultatif) : index des pages à lire, à partir de 0. Tous les modèles OCR ne le prennent pas en charge ; les modèles OCR hébergés et firecrawl/pdf-inspector répondent 400.
  • include_image_base64 (facultatif) : renvoie les images intégrées en base64. Tous les modèles OCR ne renvoient pas d'images ; certains répondent toujours avec une liste images vide.

La réponse contient pages (chacune avec index, markdown et images) et usage_info.pages_processed. Facturé par page traitée. La réservation couvre tout le document, et les documents qui dépassent le max_pages du modèle sont refusés. firecrawl/pdf-inspector ne lit que les PDF générés numériquement. Une image reçoit une erreur 422 ; un PDF avec des pages scannées provoque une erreur 422 avec code: "pages_need_ocr" et les pages concernées dans pages_needing_ocr.

Erreurs et limites

Tous les endpoints sauf System One renvoient les erreurs dans l'enveloppe OpenAI :

json{
  "error": {
    "message": "insufficient AI balance. Top up in the AI Billing tab.",
    "type": "error",
    "code": "empty_balance"
  }
}

message est toujours présent. type, ainsi que la présence de code, varient selon l'endpoint : basez-vous d'abord sur le statut HTTP. Les requêtes de chat, d'embeddings, de rerank et d'outils web placent les codes 402 dans code. Quand la route du modèle répond au chat, aux embeddings ou au rerank avec une erreur HTTP, le corps contient aussi request_id. L'en-tête X-Request-ID est toujours présent.

  • 400 : JSON invalide, model manquant, ou modèle d'un type inadapté à l'endpoint (par exemple un modèle OCR pour le chat). Un corps de plus de 25 MiB qui atteint le processus de l'API renvoie request body exceeds 25 MiB.
  • 401 : voir Authentification.
  • 402 : le solde a refusé la requête ; voir les codes ci-dessous.
  • 404 : model not found, ou un endpoint qui n'existe pas.
  • 413 : l'hôte public a refusé un corps de plus de 25 MiB avant l'exécution de l'API.
  • 429 : une limite de la clé a été atteinte, ou le modèle est surchargé. Respectez Retry-After quand il est envoyé.
  • 502 : la route du modèle a échoué. Réessayez plus tard.
  • 503 : aucune route opérationnelle pour le modèle, aucune qui corresponde aux paramètres de confidentialité du projet (onglet Settings), ou les paramètres n'ont pas pu être chargés.

Codes 402. Les requêtes de chat, d'embeddings, de rerank et d'outils web les envoient dans code. L'OCR, l'audio et la génération d'images n'envoient que le message, et System One l'envoie dans detail.

  • empty_balance : le solde IA disponible ne couvre pas la réservation de cette requête. Rechargez-le dans l'onglet Billing, ou activez la recharge automatique.
  • daily_quota : les dépenses du jour sur cette clé, plus ses réservations en cours, plus cette requête dépasseraient la limite de dépenses quotidienne de la clé.
  • month_quota : les dépenses du mois, plus les réservations en cours, plus cette requête dépasseraient la limite de dépenses mensuelle que vous avez définie dans l'onglet Billing.
  • usage_limit : les dépenses du mois, plus les réservations en cours, plus cette requête dépasseraient le plafond mensuel de votre palier d'usage. L'onglet Billing affiche le palier et le moment où le suivant s'applique.
  • pricing_unavailable et reserve_failed : la requête n'a pas pu être tarifée ou réservée. Réessayez, puis contactez le support en indiquant l'id de la requête.

Limites par défaut par clé :

  • 600 requêtes par minute
  • 4 000 000 tokens par minute (chat, embeddings, rerank et System One)
  • 20 requêtes simultanées
  • 25 MiB de corps de requête pour le chat, les embeddings, le rerank, l'OCR, l'audio et les images. Outils : 1 MiB. System One : 512 KiB.

Pour le chat, les embeddings et le rerank, une erreur 429 envoie Retry-After: 5 pour le débit de requêtes et en cas de surcharge, 10 pour le débit de tokens et 2 pour la concurrence. System One envoie toujours Retry-After: 5. La création d'une voix envoie Retry-After quand ses propres limites sont atteintes (trop d'uploads en cours, ou plus de dix tentatives de création par heure). Les autres erreurs 429 sur l'OCR, l'audio, l'image, les outils web et les voix n'en envoient pas ; attendez quelques secondes avant de réessayer. Contactez le support si vous avez besoin de limites plus élevées.

Offrez un cloud à votre agent.

Jusqu'à 15 € de crédit de bienvenue à l'inscription.

Continuer avec GitHub

ou par e-mail

Restez informé.

Les nouveautés du produit, sans spam. Désabonnez-vous à tout moment.