Référence API
Points d’accès servis
Section intitulée « Points d’accès servis »L’inférence passe par trois points d’accès, compatibles avec l’API OpenAI :
| Point d’accès | Usage |
|---|---|
POST /v1/chat/completions | Complétion : conversation, sortie structurée, outils, bases de connaissance |
POST /v1/embeddings | Vectorisation de texte |
POST /v1/audio/transcriptions | Transcription audio (voir plus bas) |
Les règles de conformité de votre organisation (pseudonymisation, longueur maximale, règles personnalisées) s’appliquent à chaque requête, et elles ne peuvent l’être qu’aux formats que Miraca sait lire. Les autres points d’accès de la norme OpenAI (/v1/responses, /v1/completions, génération d’images, synthèse vocale…) ne sont donc pas servis et répondent 404. Pour une complétion, utilisez /v1/chat/completions : les SDK OpenAI l’appellent par client.chat.completions.create.
Paramètres de complétion
Section intitulée « Paramètres de complétion »Endpoint : POST https://api.miraca.fr/v1/chat/completions
| Paramètre | Type | Défaut | Description |
|---|---|---|---|
model | string | — | mistral-small (défaut) — voir Modèles & tarifs |
messages | array | — | Tableau [{role, content}] — rôles : system, user, assistant. Le content peut être une chaîne ou un tableau de parties (texte + fichiers joints — voir Fichiers dans le chat) |
max_tokens | integer | — | Recommandé ≥ 300. Tokens alloués à la réponse (raisonnement inclus) |
temperature | float | 0.7 | 0 = déterministe, 1 = créatif |
top_p | float | 1.0 | Nucleus sampling (alternative à temperature) |
stream | boolean | false | Réponse en streaming SSE |
response_format | object | — | Voir Sortie structurée |
stop | string/array | — | Séquences d’arrêt |
workspace | string | — | Slug d’un espace de travail : le modèle reçoit les outils workspace_*, un script run_code y lit les tableaux en cellules typées. Créé au premier usage ; piloté par /v1/workspaces/* |
reasoning_effort | string | — | none, low, medium, high : combien le modèle réfléchit avant de répondre. Les niveaux acceptés dépendent du modèle (reasoning_efforts dans /v1/pricing) ; sur un modèle qui n’en propose pas, ou pour un niveau inconnu, la réponse est un 400 explicite. Posé, il prime sur miraca_niveau |
miraca_niveau | integer ou string | — | Niveau de réflexion Miraca : 1 à 5, ou sa clé (direct, rapide, standard, approfondi, maximal). Un seul réglage que la plateforme traduit pour le modèle choisi (nombre de tours d’outils et raisonnement). Alias accepté : astrolabe_niveau. Valeur illisible : 400 |
tools_enabled | string[] | — | Outils à activer pour la requête (mode agent) : web_search et web_fetch (recherche web), kb:<slug> (bases de connaissance), connection:<slug> (connecteurs API), mcp:<slug> (serveur MCP tiers déclaré par l’organisation), mailbox:<slug> (boîtes mail), code (exécution de code), files (fichiers générés), agents (sous-agents). connection: et mcp: exigent le scope de clé connections. Pas de streaming, voir plus bas |
Taille de contexte
Section intitulée « Taille de contexte »262 144 tokens (entrée + sortie cumulés) — capacité de mistral-small (Mistral Small 4).
| Repère | Tokens approximatifs |
|---|---|
| 1 mot français | ~1,3 token |
| 1 page A4 (~400 mots) | ~520 tokens |
| 262 144 tokens | ~200 000 mots / ~640 pages |
Structure de réponse
Section intitulée « Structure de réponse »mistral-small (Mistral Small 4) est un modèle avec raisonnement interne. La réponse inclut deux champs :
{ "id": "chatcmpl-…", "choices": [{ "index": 0, "message": { "role": "assistant", "content": "La réponse finale à utiliser.", "reasoning_content": "…réflexion interne du modèle (null si le modèle n'a pas raisonné)…" }, "finish_reason": "stop" }], "usage": { "prompt_tokens": 42, "completion_tokens": 318, "total_tokens": 360 }}content— la réponse finale, directement exploitable.reasoning_content— la chaîne de pensée interne du modèle (nullsi le modèle n’a pas généré de raisonnement). Non-standard OpenAI — ignoré par les SDK qui ne le supportent pas.
Raisonnement
Section intitulée « Raisonnement »mistral-small est un modèle avec raisonnement interne (chain-of-thought) : il réfléchit
avant de formuler sa réponse sur les tâches complexes. Quand ce raisonnement a lieu, il est
exposé dans le champ reasoning_content du message.
Quand le raisonnement est visible
Section intitulée « Quand le raisonnement est visible »| Mode | reasoning_content | content |
|---|---|---|
Chat libre (sans response_format) | Présent si le modèle a raisonné, null sinon | Réponse finale |
json_object ou json_schema | Toujours null (raisonnement désactivé) | JSON contraint |
Par défaut, le modèle décide lui-même s’il a besoin de raisonner : les tâches simples (reformulation, réponse directe) n’en déclenchent pas toujours.
Le régler explicitement
Section intitulée « Le régler explicitement »Le paramètre reasoning_effort prend la main sur cette décision :
{ "model": "mistral-medium", "reasoning_effort": "none", "messages": [...] }Les niveaux acceptés dépendent du modèle et sont donnés par reasoning_efforts dans
/v1/pricing : none et high sur mistral-small et
mistral-medium ; les quatre niveaux sur qwen-small, qwen-large et gemma ; low,
medium et high sur gpt-oss. Les autres modèles n’ont pas de réglage, et leur envoyer
le paramètre vaut une erreur explicite plutôt qu’un silence.
L’écart n’est pas anecdotique : sur mistral-medium, la même question produit 601 tokens
de sortie en none contre 3 000 en high. Sur une automatisation répétée, c’est la
différence entre payer une réflexion utile et la payer pour rien.
Le niveau de réflexion
Section intitulée « Le niveau de réflexion »Plutôt que de connaître les niveaux de chaque modèle, vous pouvez poser un seul
réglage, miraca_niveau, que la plateforme traduit pour le modèle qui répond :
| Niveau | Clé | Tours d’outils | Raisonnement visé |
|---|---|---|---|
| 1 | direct | 1 | none |
| 2 | rapide | 3 | low |
| 3 | standard | 8 | medium |
| 4 | approfondi | 20 | high |
| 5 | maximal | 99 | high |
{ "model": "gpt-oss", "miraca_niveau": "approfondi", "tools_enabled": ["web_search"], "messages": [...] }Le raisonnement posé est le niveau visé si le modèle le propose, sinon le niveau qu’il
propose juste en dessous (jamais plus que ce que vous avez demandé), sinon son plus
bas. Sur mistral-small et mistral-medium (none, high), les niveaux 1 à 3 donnent
none et 4 et 5 high ; sur gpt-oss (low, medium, high), 1 et 2 donnent low,
3 medium, 4 et 5 high. Un modèle sans réglage de raisonnement reçoit seulement le
nombre de tours, sans erreur. Les tours ne comptent que si la requête active des outils
(tools_enabled, base de connaissance en mode agentique) ; au niveau 1, un seul tour
d’outils est permis.
Ce que vous posez explicitement prime : reasoning_effort remplace le raisonnement
du niveau, tools_max_steps (ou knowledge_base_max_steps) remplace son nombre de tours,
y compris avec une base en knowledge_base_mode: "agentic". Une intégration existante qui
n’envoie pas miraca_niveau garde exactement son comportement.
Les sous-agents (tools_enabled: ["agents"]) ne sont offerts qu’aux
niveaux 4 et 5, chacun avec un budget de tours propre (5 et 10) : aux niveaux 1 à 3, le
jeton agents est ignoré. Sans miraca_niveau, il reste honoré comme avant.
miraca_niveau accepte un entier de 1 à 5, la même valeur en chaîne de chiffres ("3")
ou la clé ("standard") ; toute autre valeur (y compris des chiffres non latins comme
"3") est refusée en 400, avec la liste des valeurs acceptées.
Impact sur max_tokens
Section intitulée « Impact sur max_tokens »Les tokens de raisonnement sont comptabilisés dans completion_tokens. Avec max_tokens
trop bas, le quota peut être épuisé avant la réponse finale → content vide ou tronqué.
Règle pratique :
- Sortie structurée (
json_schema/json_object) :max_tokens ≥ 200suffit (pas de raisonnement) - Chat court (classification, extraction) :
max_tokens ≥ 300 - Chat long (rédaction, analyse) :
max_tokens 1000–2000
Streaming
Section intitulée « Streaming »Avec stream: true, la réponse arrive en Server-Sent Events (même format qu’OpenAI).
Les chunks de raisonnement arrivent dans delta.reasoning_content, les chunks de réponse
finale dans delta.content.
stream = client.chat.completions.create( model="mistral-small", messages=[{"role": "user", "content": "Résume ce compte-rendu en 3 points."}], max_tokens=600, stream=True,)for chunk in stream: delta = chunk.choices[0].delta if delta.content: print(delta.content, end="", flush=True)Mode agent : usage et incidents du fournisseur
Section intitulée « Mode agent : usage et incidents du fournisseur »Une requête qui active des outils (bases de connaissance en mode agent, recherche web, connecteurs,
exécution de code) enchaîne plusieurs tours côté serveur. La réponse porte alors, en plus du usage
standard, un champ additionnel miraca_usage : le cumul des tokens de tous les tours, et le
forfait des outils web.
{ "miraca_usage": { "prompt_tokens": 18420, "completion_tokens": 912, "total_tokens": 19332, "cached_prompt_tokens": 12288, "cache_creation_prompt_tokens": 0, "web_searches": 0, "tools_cost_eur": 0 }}Comme les autres champs miraca_*, il est ignoré par les SDK OpenAI standards et aussi servi sous son
ancien nom astrolabe_usage, avec la même valeur.
cached_prompt_tokens compte les tokens d’entrée que le fournisseur a servis depuis son cache de prompt,
facturés à tarif réduit quand le modèle en prévoit un. Ce cache n’est jamais partagé entre organisations ni
entre personnes : chaque requête commence par une courte ligne propre à l’appelant, ajoutée par Miraca, qui
compte dans prompt_tokens (environ 26 tokens).
cache_creation_prompt_tokens compte les tokens d’entrée que le fournisseur a écrits dans son cache.
Seuls les modèles Claude le facturent à part, 1,25 fois le prix d’entrée ; pour les autres modèles il vaut
0. Comme cached_prompt_tokens, ces tokens sont déjà comptés dans
prompt_tokens.
Quand le fournisseur du modèle échoue
Section intitulée « Quand le fournisseur du modèle échoue »Si le fournisseur du modèle échoue en cours de route, la réponse reste un 200 : le message est rendu
dans content, sans erreur HTTP. Quatre cas :
miraca_usage.incident | Message rendu dans content | À faire |
|---|---|---|
saturation | « Le service d’inférence est momentanément saturé… » | Réessayer dans quelques instants |
delai | « Le service d’inférence n’a pas répondu à temps… », ou « Le modèle « X » n’a rien renvoyé en 10 minutes… » | Réessayer, ou alléger la demande, ou choisir un autre modèle |
indisponible | « Le fournisseur du modèle « X » est momentanément indisponible… » (ou « n’est pas accessible pour le moment ») | Réessayer plus tard, ou choisir un autre modèle |
refus | « Le fournisseur du modèle « X » a refusé la requête (erreur 400 : raison)… » | Ne pas relancer à l’identique : le même refus reviendrait. Choisir un autre modèle, ou alléger la demande |
Les messages d’indisponibilité et de refus nomment le modèle public que vous avez demandé, et la raison d’un refus n’est dite que lorsqu’elle est reconnue (par exemple « la conversation dépasse la fenêtre de contexte de ce modèle »). Le texte brut du fournisseur n’est jamais recopié.
Quand le modèle avait déjà écrit un texte avant le refus (typiquement « Je cherche… »), ce texte est
conservé et le refus est ajouté dessous, précédé de « Réponse interrompue ». Ce marqueur n’est pas
ajouté à une sortie JSON demandée par response_format (il la rendrait illisible).
Quand le fournisseur ne renvoie rien
Section intitulée « Quand le fournisseur ne renvoie rien »Chaque fournisseur ferme lui-même une demande à laquelle il n’a encore rien répondu, au bout d’une durée qu’il fixe : 5 minutes de silence chez Scaleway, 10 minutes sans réponse chez OVHcloud, 15 minutes chez Mistral (mesuré le 16 octobre 2026). Passé ce délai, aucune réponse ne peut plus arriver.
- En cours de route (un appel de la boucle d’outils) : l’appel est abandonné à ce délai, sans être
relancé (la même demande attendrait autant). La réponse reste un
200, avec l’incidentdelaiet un message qui nomme le modèle : « Le modèle « X » n’a rien renvoyé en 10 minutes : son fournisseur ne répond pas à cette demande. Réessayez, ou choisissez un autre modèle. » - Dès le premier appel : la réponse est une erreur HTTP
504. Le même message est danserror.message, et la nature de l’incident danserror.provider_specific_fields.miraca_incident("delai", aussi servi sousastrolabe_incident).
{ "error": { "message": "Le modèle « qwen-27b » n'a rien renvoyé en 10 minutes : son fournisseur ne répond pas à cette demande. Réessayez, ou choisissez un autre modèle.", "type": "internal_server_error", "code": "504", "provider_specific_fields": { "miraca_incident": "delai", "astrolabe_incident": "delai" } }}Transcription audio
Section intitulée « Transcription audio »POST /v1/audio/transcriptions, compatible avec l’API OpenAI (champ file, en multipart/form-data), avec le modèle voxtral-transcribe. La transcription est servie par Mistral dans l’Union européenne.
curl https://api.miraca.fr/v1/audio/transcriptions \ -H "Authorization: Bearer sk-..." \ -F model=voxtral-transcribe \ -F file=@reunion.flac- Permission : une clé restreinte doit porter le scope
audio. Sans lui, la requête est refusée en401. - Formats acceptés : FLAC, WAV et OGG (ainsi que les autres formats non compressés : AIFF, CAF). La transcription est facturée à la durée mesurée du fichier (voir Modèles et tarifs).
- Formats refusés : MP3, M4A/AAC et WebM répondent
400(« Format audio non pris en charge »). Leur durée ne peut pas être mesurée de façon fiable, et une durée inconnue ne se facture pas. Convertissez-les avant l’envoi :
ffmpeg -i reunion.m4a -ac 1 -ar 16000 reunion.flacRate limits
Section intitulée « Rate limits »| Code HTTP | Cause | À faire |
|---|---|---|
429 Too Many Requests | Débit maximal de la clé atteint (tokens par minute, réglé dans le portail), ou fournisseur du modèle momentanément saturé | Attendre et réessayer : les SDK OpenAI gèrent le retry avec backoff automatiquement |
503 Service Unavailable | Backend temporairement indisponible | Réessayer après 30 s |
401 Unauthorized | Clé absente, invalide, supprimée ou bloquée | Vérifier la clé dans le portail |
422 Unprocessable Entity | Crédits épuisés (« Budget has been exceeded! »). Chaque requête réserve son coût maximal estimé le temps de s’exécuter : quand le solde est bas, des requêtes simultanées peuvent être refusées alors qu’il n’est pas nul | Recharger les crédits ; quand le solde est bas, fixer max_tokens et éviter de lancer en parallèle des requêtes coûteuses |
404 Not Found | Point d’accès non servi (/v1/responses, /v1/completions…) | Utiliser l’un des points d’accès servis |
400 Bad Request | Paramètre invalide, contexte dépassé, ou règle de conformité violée | Vérifier max_tokens + taille du prompt ; lire le message d’erreur (les refus de conformité y sont explicites) |
413 Payload Too Large | Corps de requête trop volumineux sur une route de gestion (/v1/kb, /v1/workspaces, /v1/anonymize, /v1/tasks…) : 24 Mo par requête JSON, 15 Mo par fichier envoyé en multipart/form-data | Envoyer le fichier en multipart/form-data plutôt qu’en base64, ou découper le contenu en plusieurs documents |
Requêtes simultanées : Miraca n’impose pas de plafond global de requêtes simultanées. Un
429 vient soit du débit maximal posé sur votre clé, soit du fournisseur du modèle quand il
est saturé ; votre client SDK retente automatiquement. Au-delà de quelques dizaines de
requêtes simultanées soutenues, les réponses ralentissent : pour un tel volume,
contactez-nous.
Retrouver la cause d’une requête en échec
Section intitulée « Retrouver la cause d’une requête en échec »La page Usage du portail liste les requêtes en échec des 30 derniers jours, avec leur cause : limite de débit du fournisseur ou de la clé, crédits épuisés, clé absente ou bloquée, modèle inconnu ou non autorisé pour l’organisation, refus des règles de conformité, requête trop longue, délai dépassé, fournisseur indisponible. Quand elle est sûre, une précision s’y ajoute (le modèle refusé, le type de donnée personnelle détectée).
Le message d’erreur lui-même n’y figure pas : il peut recopier une partie de la requête, et une requête d’un membre n’est pas lisible par l’administrateur de l’organisation. Le message complet reste dans la réponse reçue par l’application qui a fait l’appel.