# Conversation (chat completions)

> Référence de POST /v1/chat/completions : paramètres, messages, réponse, flux SSE et format des morceaux, outils, images, longueur de sortie et erreurs.

`POST /v1/chat/completions` est le point d’accès des modèles de conversation. Le corps de la requête et la réponse suivent l’API Chat Completions d’OpenAI : les SDK d’OpenAI s’en servent sans réglage particulier.

```http
POST https://api.realmoon.ai/v1/chat/completions
```

- Authentification : clé `sk-moon-…` avec la portée `inference` (voir [Authentification](https://realmoon.ai/documentation/api/authentification/)).
- Corps : JSON (`Content-Type: application/json`).
- Réponse : un objet `chat.completion`, ou un flux SSE de morceaux `chat.completion.chunk` avec `"stream": true`.
- Facturation : à l’usage, sur le porte-monnaie du workspace de la clé (voir [Coûts](https://realmoon.ai/documentation/api/couts/)).

## Exemple

```bash title="cURL"
curl https://api.realmoon.ai/v1/chat/completions \
  -H "Authorization: Bearer $MOONAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
        "model": "anthropic/claude-haiku-4.5",
        "messages": [
          {"role": "system", "content": "Tu réponds en une phrase."},
          {"role": "user", "content": "Qu’est-ce qu’une API ?"}
        ],
        "max_tokens": 300,
        "temperature": 0.3
      }'
```

```python title="Python"
import os
from openai import OpenAI

client = OpenAI(base_url="https://api.realmoon.ai/v1", api_key=os.environ["MOONAI_API_KEY"])

response = client.chat.completions.create(
    model="anthropic/claude-haiku-4.5",
    messages=[
        {"role": "system", "content": "Tu réponds en une phrase."},
        {"role": "user", "content": "Qu’est-ce qu’une API ?"},
    ],
    max_tokens=300,
    temperature=0.3,
)
print(response.choices[0].message.content)
```

```javascript title="JavaScript"
import OpenAI from 'openai';

const client = new OpenAI({ baseURL: 'https://api.realmoon.ai/v1', apiKey: process.env.MOONAI_API_KEY });

const response = await client.chat.completions.create({
  model: 'anthropic/claude-haiku-4.5',
  messages: [
    { role: 'system', content: 'Tu réponds en une phrase.' },
    { role: 'user', content: 'Qu’est-ce qu’une API ?' },
  ],
  max_tokens: 300,
  temperature: 0.3,
});
console.log(response.choices[0].message.content);
```

## Paramètres

Le corps est un objet JSON. Les paramètres du tableau sont transmis au modèle, sauf `provider` et `transforms`, vérifiés à part (voir [Préférences de fournisseur](https://realmoon.ai/documentation/api/chat/#provider)) ; les autres sont retirés sans erreur (voir [Paramètres ignorés](https://realmoon.ai/documentation/api/chat/#ignores)). Un modèle peut refuser un paramètre qu’il ne connaît pas (`400 unsupported_parameter`).

| Paramètre | Type | Obligatoire | Description |
| --- | --- | --- | --- |
| `model` | chaîne | oui | Identifiant d’un modèle de type `chat` de `GET /v1/models`. Absent : `400 missing_required_parameter`. Inconnu : `404 model_not_found`. |
| `messages` | tableau | oui | La conversation, voir [Messages](https://realmoon.ai/documentation/api/chat/#messages). Absent ou mal formé : `400 unsupported_content`. |
| `stream` | booléen | non | `true` pour recevoir la réponse en flux SSE, voir [Flux](https://realmoon.ai/documentation/api/chat/#flux). `false` par défaut. |
| `max_tokens` | entier | non | Nombre maximal de jetons de sortie, raisonnement compris. Voir [Longueur de la réponse](https://realmoon.ai/documentation/api/chat/#longueur). |
| `max_completion_tokens` | entier | non | Même rôle que `max_tokens`, sous le nom utilisé par les modèles de raisonnement d’OpenAI. |
| `temperature` | nombre | non | Aléa de l’échantillonnage. |
| `top_p` | nombre | non | Échantillonnage par noyau. |
| `top_k`, `min_p`, `top_a`, `repetition_penalty` | nombre | non | Réglages d’échantillonnage, pour les modèles qui les acceptent. |
| `frequency_penalty`, `presence_penalty` | nombre | non | Pénalités de répétition. |
| `stop` | chaîne ou tableau | non | Séquences qui arrêtent la génération. |
| `seed` | entier | non | Graine, pour les modèles qui la respectent. |
| `logit_bias` | objet | non | Biais par jeton, pour les modèles qui l’acceptent. |
| `logprobs` | booléen | non | Demande les probabilités des jetons, pour les modèles qui les renvoient. |
| `top_logprobs` | entier | non | Nombre de jetons probables renvoyés à chaque position, avec `logprobs`. |
| `response_format` | objet | non | Sortie JSON (`{"type": "json_object"}`) ou conforme à un schéma (`{"type": "json_schema", "json_schema": {…}}`), selon le modèle. |
| `tools` | tableau | non | Fonctions que le modèle peut appeler, voir [Outils](https://realmoon.ai/documentation/api/chat/#outils). |
| `tool_choice` | chaîne ou objet | non | `none`, `auto`, `required`, une fonction précise (`{"type": "function", "function": {"name": "…"}}`) ou `{"type": "allowed_tools", …}`. |
| `parallel_tool_calls` | booléen | non | Autorise plusieurs appels d’outils dans une même réponse. |
| `functions`, `function_call` | tableau, chaîne ou objet | non | Ancienne forme des outils, encore acceptée. |
| `reasoning_effort` | chaîne | non | Effort de raisonnement (par exemple `low`, `medium`, `high`), pour les modèles qui l’acceptent. |
| `reasoning` | objet | non | Réglage du raisonnement. Seules les clés `effort`, `max_tokens`, `exclude` et `enabled` sont transmises. |
| `include_reasoning` | booléen | non | Demande au modèle de renvoyer son raisonnement, quand il le permet. |
| `verbosity` | chaîne | non | Niveau de détail, pour les modèles qui l’acceptent. |
| `user`, `safety_identifier`, `prompt_cache_key` | chaîne | non | Identifiant de votre utilisateur final ou clé de cache. Remplacé par un pseudonyme s’il contient une donnée personnelle détectée (voir [Confidentialité](https://realmoon.ai/documentation/api/confidentialite/#moon-blur)). |
| `n` | entier | non | Seule la valeur `1` est acceptée (`400 n_not_supported` sinon). |
| `provider` | objet | non | Préférences de fournisseur, voir [ci-dessous](https://realmoon.ai/documentation/api/chat/#provider). |
| `transforms` | tableau | non | `["middle-out"]` seulement, voir [ci-dessous](https://realmoon.ai/documentation/api/chat/#provider). |

Les réglages d’échantillonnage dépendent du modèle : un modèle peut en ignorer certains.

### Préférences de fournisseur

Un même modèle peut être servi par plusieurs fournisseurs. L’objet `provider` restreint ou ordonne ce choix ; il ne l’élargit jamais.

| Clé | Valeur | Effet |
| --- | --- | --- |
| `only` | tableau de noms | Ne sert la requête que par ces fournisseurs. |
| `ignore` | tableau de noms | Écarte ces fournisseurs. |
| `order` | tableau de noms | Essaie les fournisseurs dans cet ordre. |
| `quantizations` | tableau de noms | Ne garde que ces niveaux de quantification. |
| `sort` | `price`, `throughput` ou `latency` | Trie les fournisseurs par prix, débit ou latence. |
| `allow_fallbacks` | booléen | `false` : pas de repli vers un autre fournisseur. |
| `require_parameters` | booléen | `true` : seulement les fournisseurs qui acceptent tous les paramètres de la requête. |
| `max_price` | objet | Prix maximal accepté, en dollars US : `prompt` et `completion` par million de jetons, `request` par requête, `image` par image. |
| `data_collection` | `"deny"` | Écarte les fournisseurs qui déclarent réutiliser les données. |
| `zdr` | booléen | `true` : seulement les fournisseurs qui déclarent ne rien conserver. |

- Les listes comptent 64 noms au plus.
- Une valeur par défaut (`allow_fallbacks: true`, `zdr: false`, `data_collection: "allow"`, liste vide) est ignorée.
- Toute autre clé, ou une valeur invalide, est refusée avec `400 unsupported_parameter` et `param` qui la nomme (par exemple `provider.foo`).
- Le prix maximal transmis n’est jamais plus haut que le prix du modèle dans `/v1/models` : une préférence ne fait jamais servir la requête plus cher que ce que la réserve couvre.
- Tous les modèles ne prennent pas ces préférences en charge. Sur un modèle qui ne les accepte pas, par exemple un modèle hébergé par Moon AI, une préférence active est refusée avec `400 unsupported_parameter` (`param: "provider"`).
- Les engagements `data_collection` et `zdr` sont ceux que déclarent les fournisseurs ; Moon AI ne les contrôle pas.

`transforms: ["middle-out"]` raccourcit le milieu d’une conversation trop longue pour la fenêtre de contexte du modèle. Toute autre valeur est refusée (`400 unsupported_parameter`, `param: "transforms"`), comme `middle-out` sur un modèle qui ne prend pas les préférences de fournisseur en charge.

## Messages

`messages` est un tableau d’objets message, du plus ancien au plus récent.

| Champ | Type | Obligatoire | Description |
| --- | --- | --- | --- |
| `role` | chaîne | oui | `system`, `user`, `assistant` ou `tool`. |
| `content` | chaîne, tableau de parties ou `null` | oui | Le contenu. `null` est permis pour un message `assistant` qui ne porte que des `tool_calls`. |
| `name` | chaîne | non | Nom de l’auteur. Remplacé par un pseudonyme s’il contient une donnée personnelle détectée. |
| `tool_calls` | tableau | non | Sur un message `assistant` : les appels d’outils que le modèle a faits, renvoyés tels quels. |
| `tool_call_id` | chaîne | dans un message `tool` | L’identifiant de l’appel auquel le message répond. |

Un `content` en tableau contient des parties :

| Type de partie | Forme | Remarques |
| --- | --- | --- |
| `text` | `{"type": "text", "text": "…"}` | Texte. |
| `refusal` | `{"type": "refusal", "refusal": "…"}` | Refus renvoyé par un modèle, dans un message `assistant` que vous renvoyez. |
| `image_url` | `{"type": "image_url", "image_url": {"url": "…", "detail": "auto"}}` | Adresse `https://` ou `http://`, ou `data:image/…;base64,…`. Voir [Images et fichiers](https://realmoon.ai/documentation/api/chat/#images-fichiers). |
| `input_audio` | `{"type": "input_audio", "input_audio": {"data": "<base64>", "format": "wav"}}` | Audio en base64 seulement, pour les modèles qui lisent l’audio. |
| `file` | `{"type": "file", "file": {"filename": "devis.pdf", "file_data": "data:application/pdf;base64,…"}}` | Fichier en base64, en URL `data:` ou à une adresse `http(s)://`. |

Toute autre partie est refusée avec `400 unsupported_content`, en particulier :

- un fichier désigné par son identifiant (`file_id`) : envoyez son contenu dans `file_data` ;
- une vidéo ;
- de l’audio envoyé comme `file` : utilisez une partie `input_audio` ;
- de l’audio sur un modèle dont le prix de l’audio n’est pas connu.

## Réponse

Sans flux, la réponse est un objet `chat.completion`.

```json title="Réponse"
{
  "id": "gen-6f1c2b7e9a4d4c0e8b3a5d2f1e0c9b8a",
  "object": "chat.completion",
  "created": 1793577600,
  "model": "anthropic/claude-haiku-4.5",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": "Une API est une interface qui permet à deux logiciels d’échanger des données."
      },
      "finish_reason": "stop"
    }
  ],
  "usage": { "prompt_tokens": 24, "completion_tokens": 18, "total_tokens": 42 }
}
```

| Champ | Type | Description |
| --- | --- | --- |
| `id` | chaîne | Identifiant de la requête chez Moon AI (`gen-…`), le même que l’en-tête `X-Moon-Request-Id`. Il sert à lire le coût avec [`GET /v1/generation`](https://realmoon.ai/documentation/api/solde/#generation). |
| `object` | chaîne | `chat.completion`. |
| `created` | entier | Date en secondes Unix. |
| `model` | chaîne | Le modèle appelé, ou le nom exact de la version servie. Pour un modèle maison de Moon AI, toujours l’identifiant Moon AI. |
| `choices` | tableau | Une seule réponse (`n` vaut toujours 1). |
| `choices[].message.role` | chaîne | `assistant`. |
| `choices[].message.content` | chaîne ou `null` | Le texte de la réponse. `null` quand le modèle ne fait qu’appeler des outils. |
| `choices[].message.tool_calls` | tableau | Les appels d’outils demandés par le modèle, voir [Outils](https://realmoon.ai/documentation/api/chat/#outils). |
| `choices[].message.refusal` | chaîne | Le refus du modèle, quand il refuse de répondre. |
| `choices[].message.reasoning` | chaîne | Le raisonnement, quand le modèle le renvoie (`reasoning_content` chez certains modèles). |
| `choices[].finish_reason` | chaîne | `stop`, `length` (limite de sortie atteinte), `tool_calls`, `content_filter`… |
| `choices[].logprobs` | objet | Les probabilités des jetons, avec `logprobs: true`. |
| `usage.prompt_tokens`, `usage.completion_tokens`, `usage.total_tokens` | entier | Jetons comptés. |
| `usage.prompt_tokens_details`, `usage.completion_tokens_details` | objet | Détails que le modèle fournit : jetons lus en cache, jetons de raisonnement. |

La réponse ne donne jamais le coût, ni le fournisseur qui a servi le modèle : `provider`, `system_fingerprint`, `native_finish_reason` et les champs de coût de `usage` sont retirés.

### En-têtes de réponse

| En-tête | Valeur |
| --- | --- |
| `X-Moon-Request-Id` | `gen-…`, identifiant de la requête. |
| `X-Moon-Prompt-Storage` | `none` : le contenu n’est pas conservé. |
| `X-Moon-Blur` | `on` si Moon Blur a analysé la requête, `off` s’il est désactivé pour la clé. |
| `X-Moon-Blur-Redactions` | Nombre de valeurs remplacées par Moon Blur, quand il y en a. |

## Flux

Avec `"stream": true`, la réponse arrive en Server-Sent Events (`Content-Type: text/event-stream`) au format d’OpenAI. Le statut HTTP (200) et les en-têtes partent avec le premier octet.

```bash title="cURL"
curl -N https://api.realmoon.ai/v1/chat/completions \
  -H "Authorization: Bearer $MOONAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
        "model": "anthropic/claude-haiku-4.5",
        "messages": [{"role": "user", "content": "Écris un haïku sur la Lune."}],
        "stream": true
      }'
```

```python title="Python"
stream = client.chat.completions.create(
    model="anthropic/claude-haiku-4.5",
    messages=[{"role": "user", "content": "Écris un haïku sur la Lune."}],
    stream=True,
)
for chunk in stream:
    if chunk.choices and chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="", flush=True)
    if chunk.usage:
        print("\n", chunk.usage)
```

```javascript title="JavaScript"
const stream = await client.chat.completions.create({
  model: 'anthropic/claude-haiku-4.5',
  messages: [{ role: 'user', content: 'Écris un haïku sur la Lune.' }],
  stream: true,
});
for await (const chunk of stream) {
  const text = chunk.choices[0]?.delta?.content;
  if (text) process.stdout.write(text);
  if (chunk.usage) console.log('\n', chunk.usage);
}
```

### Format des événements

Chaque événement est une ligne `data: ` suivie d’un objet JSON, puis une ligne vide. Le dernier événement est `data: [DONE]`. Les lignes qui commencent par `:` sont des commentaires.

```text title="Flux"
data: {"id":"gen-6f1c2b7e9a4d4c0e8b3a5d2f1e0c9b8a","object":"chat.completion.chunk","created":1793577600,"model":"anthropic/claude-haiku-4.5","choices":[{"index":0,"delta":{"role":"assistant","content":"Lune"},"finish_reason":null}]}

data: {"id":"gen-6f1c2b7e9a4d4c0e8b3a5d2f1e0c9b8a","object":"chat.completion.chunk","created":1793577600,"model":"anthropic/claude-haiku-4.5","choices":[{"index":0,"delta":{"content":" pâle au-dessus des toits"},"finish_reason":null}]}

: keep-alive

data: {"id":"gen-6f1c2b7e9a4d4c0e8b3a5d2f1e0c9b8a","object":"chat.completion.chunk","created":1793577600,"model":"anthropic/claude-haiku-4.5","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}

data: {"id":"gen-6f1c2b7e9a4d4c0e8b3a5d2f1e0c9b8a","object":"chat.completion.chunk","created":1793577600,"model":"anthropic/claude-haiku-4.5","choices":[],"usage":{"prompt_tokens":16,"completion_tokens":21,"total_tokens":37}}

data: [DONE]
```

| Champ d’un morceau | Description |
| --- | --- |
| `id` | Identifiant de la requête (`gen-…`), le même dans tous les morceaux. |
| `object` | `chat.completion.chunk`. |
| `created`, `model` | Comme dans la réponse sans flux. |
| `choices[].delta.role` | `assistant`, dans le premier morceau. |
| `choices[].delta.content` | Le fragment de texte suivant. |
| `choices[].delta.tool_calls` | Fragments d’appels d’outils : `index`, puis `id` et `function.name` au début, `function.arguments` découpé en morceaux à concaténer. |
| `choices[].delta.reasoning` | Fragment du raisonnement, quand le modèle le renvoie (`reasoning_content` chez certains modèles). |
| `choices[].finish_reason` | `null` tant que la réponse continue, puis la raison de fin. |
| `usage` | Dans un des derniers morceaux : les jetons comptés, parfois avec un tableau `choices` vide. |

- Le morceau qui porte `usage` arrive toujours, même sans `stream_options` : vérifiez que `choices` n’est pas vide avant de le lire.
- Des commentaires `: keep-alive` arrivent pendant que le modèle réfléchit, pour garder la connexion ouverte. Les SDK les ignorent.
- Quand Moon Blur a remplacé une valeur, elle est remise dans le texte, le raisonnement et les arguments d’outils, même quand un jeton est coupé entre deux morceaux.
- Si le flux est coupé de notre côté ou chez le fournisseur, un dernier événement `data: {"error": {"message": "upstream stream interrupted", "type": "server_error", "code": "upstream_error"}}` signale que la réponse est incomplète. Les SDK le lèvent comme une erreur pendant l’itération.
- Le flux dure une heure au plus, et il est coupé si le modèle n’envoie rien pendant 5 minutes.
- Le coût est réglé à la fin du flux. Si votre client ferme la connexion avant, la requête est réglée sur le coût que le fournisseur annonce pour ce qu’il a produit, ou garde une partie de sa réserve (voir [Règlement](https://realmoon.ai/documentation/api/couts/#reglement)).

> [!TIP]
> **Réponses longues**
>
> Pour une réponse longue ou un modèle de raisonnement, utilisez le flux : la connexion reste active pendant que le modèle travaille. Une requête sans flux n’envoie rien avant la fin de la réponse et peut être coupée par le réseau au-delà de 100 secondes environ (voir [Limites](https://realmoon.ai/documentation/api/limites/#durees)).

## Outils (function calling)

Seuls les outils de type `function`, exécutés par votre programme, sont acceptés. Un outil d’un autre type (exécuté par le fournisseur, comme une recherche web) est refusé avec `400 unsupported_parameter` et `param: "tools"`.

```bash title="cURL"
curl https://api.realmoon.ai/v1/chat/completions \
  -H "Authorization: Bearer $MOONAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
        "model": "anthropic/claude-haiku-4.5",
        "messages": [{"role": "user", "content": "Quel temps fait-il à Lyon ?"}],
        "tools": [{
          "type": "function",
          "function": {
            "name": "meteo",
            "description": "Météo actuelle d’une ville",
            "parameters": {
              "type": "object",
              "properties": {"ville": {"type": "string"}},
              "required": ["ville"]
            }
          }
        }],
        "tool_choice": "auto"
      }'
```

```python title="Python"
import json

tools = [{
    "type": "function",
    "function": {
        "name": "meteo",
        "description": "Météo actuelle d’une ville",
        "parameters": {
            "type": "object",
            "properties": {"ville": {"type": "string"}},
            "required": ["ville"],
        },
    },
}]
messages = [{"role": "user", "content": "Quel temps fait-il à Lyon ?"}]

first = client.chat.completions.create(model="anthropic/claude-haiku-4.5", messages=messages, tools=tools)
call = first.choices[0].message.tool_calls[0]
args = json.loads(call.function.arguments)

messages.append(first.choices[0].message)
messages.append({"role": "tool", "tool_call_id": call.id, "content": json.dumps({"ville": args["ville"], "ciel": "dégagé", "temperature": 18})})

final = client.chat.completions.create(model="anthropic/claude-haiku-4.5", messages=messages, tools=tools)
print(final.choices[0].message.content)
```

```javascript title="JavaScript"
const tools = [{
  type: 'function',
  function: {
    name: 'meteo',
    description: 'Météo actuelle d’une ville',
    parameters: {
      type: 'object',
      properties: { ville: { type: 'string' } },
      required: ['ville'],
    },
  },
}];
const messages = [{ role: 'user', content: 'Quel temps fait-il à Lyon ?' }];

const first = await client.chat.completions.create({ model: 'anthropic/claude-haiku-4.5', messages, tools });
const call = first.choices[0].message.tool_calls[0];
const args = JSON.parse(call.function.arguments);

messages.push(first.choices[0].message);
messages.push({ role: 'tool', tool_call_id: call.id, content: JSON.stringify({ ville: args.ville, ciel: 'dégagé', temperature: 18 }) });

const final = await client.chat.completions.create({ model: 'anthropic/claude-haiku-4.5', messages, tools });
console.log(final.choices[0].message.content);
```

```json title="Message renvoyé par le modèle"
{
  "role": "assistant",
  "content": null,
  "tool_calls": [
    {
      "id": "call_01",
      "type": "function",
      "function": { "name": "meteo", "arguments": "{\"ville\":\"Lyon\"}" }
    }
  ]
}
```

- Tous les modèles ne savent pas appeler des outils.
- Les arguments (`function.arguments`) arrivent sous forme de chaîne JSON. Quand Moon Blur a masqué une valeur, elle est remise dans les arguments, qui restent du JSON valide.
- `finish_reason` vaut `tool_calls` quand le modèle attend le résultat de vos fonctions.

## Images et fichiers

Un modèle qui lit les images accepte des parties `image_url` dans un message `user`.

```bash title="cURL"
curl https://api.realmoon.ai/v1/chat/completions \
  -H "Authorization: Bearer $MOONAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
        "model": "anthropic/claude-haiku-4.5",
        "messages": [{
          "role": "user",
          "content": [
            {"type": "text", "text": "Décris cette image."},
            {"type": "image_url", "image_url": {"url": "https://example.com/photo.jpg"}}
          ]
        }]
      }'
```

```python title="Python"
import base64

with open("photo.jpg", "rb") as f:
    data_url = "data:image/jpeg;base64," + base64.b64encode(f.read()).decode()

response = client.chat.completions.create(
    model="anthropic/claude-haiku-4.5",
    messages=[{
        "role": "user",
        "content": [
            {"type": "text", "text": "Décris cette image."},
            {"type": "image_url", "image_url": {"url": data_url}},
        ],
    }],
)
print(response.choices[0].message.content)
```

```javascript title="JavaScript"
import fs from 'node:fs';

const dataUrl = 'data:image/jpeg;base64,' + fs.readFileSync('photo.jpg').toString('base64');

const response = await client.chat.completions.create({
  model: 'anthropic/claude-haiku-4.5',
  messages: [{
    role: 'user',
    content: [
      { type: 'text', text: 'Décris cette image.' },
      { type: 'image_url', image_url: { url: dataUrl } },
    ],
  }],
});
console.log(response.choices[0].message.content);
```

- Une image à une adresse `https://` est lue par le fournisseur du modèle, pas par Moon AI.
- Sur les modèles d’OpenAI, une image sans `detail` (ou avec `auto`) est envoyée avec `detail: "high"`.
- Pour la plupart des modèles, un PDF envoyé dans une partie `file` est lu par le modèle s’il sait lire les fichiers ; sinon, son texte en est extrait avant l’envoi.
- La réserve d’une requête tient compte de ses pièces jointes. Une image d’un modèle dont le traitement des images n’est pas connu, un fichier PDF ou un audio peuvent être retenus jusqu’à la taille de la fenêtre de contexte : la réserve peut être élevée, mais elle est rendue après la réponse (voir [Coûts](https://realmoon.ai/documentation/api/couts/#reserve)).

Moon Blur ne lit que le texte : les images, fichiers et sons partent tels quels.

## Raisonnement

Les modèles de raisonnement acceptent `reasoning_effort` ou l’objet `reasoning` selon leur famille. Quand le modèle renvoie son raisonnement, il arrive dans un champ du message ou du morceau de flux (`reasoning` ou `reasoning_content`, selon le modèle). Les jetons de raisonnement sont des jetons de sortie : ils sont comptés dans `usage` et dans la limite de sortie.

## Longueur de la réponse

- **Avec `max_tokens`** (ou `max_completion_tokens`), le modèle ne produit pas plus que cette valeur, raisonnement compris. Un budget `reasoning.max_tokens` plus grand est ramené à cette valeur.
- **Sans `max_tokens`**, la réponse dispose d’au moins 4 096 jetons de sortie (moins si la limite du modèle est plus basse). Si le solde ou un plafond de dépense ne couvre pas cette taille, la requête est refusée (`402`) plutôt que servie en quelques mots. Au-delà, la limite monte jusqu’à celle du modèle (16 384 jetons au plus), tant qu’une petite part de ce qu’il reste au solde et aux plafonds la couvre, pour laisser de la place aux requêtes simultanées. Elle laisse aussi la place de l’entrée dans la fenêtre de contexte.
- Pour un modèle de raisonnement d’OpenAI appelé directement, la limite est envoyée sous le nom `max_completion_tokens`.

Fixer `max_tokens` rend la réserve plus petite et plus prévisible. C’est recommandé quand beaucoup de requêtes partent en même temps.

## Paramètres ignorés

Ces paramètres sont retirés avant l’envoi, sans erreur : `store`, `metadata`, `service_tier`, `modalities`, `audio`, `prediction`, `web_search_options`, `plugins`, `stream_options` (le serveur demande lui-même l’usage en fin de flux) et tout paramètre absent du tableau des paramètres. Le paramètre `store` ne peut donc pas demander au fournisseur de garder vos requêtes.

## Erreurs

| HTTP | `code` | Signification |
| --- | --- | --- |
| 400 | `null` | `invalid JSON body` ou `body must be a JSON object`. |
| 400 | `missing_required_parameter` | `model` absent (`param: "model"`). |
| 400 | `unsupported_content` | `messages` absent ou mal formé, ou partie de message que l’API ne sert pas (voir [Messages](https://realmoon.ai/documentation/api/chat/#messages)). |
| 400 | `n_not_supported` | `n` différent de 1. |
| 400 | `unsupported_parameter` | Outil d’un autre type que `function`, `tool_choice` invalide, préférence de fournisseur refusée, ou paramètre refusé par le modèle. |
| 400 ou 413 | `context_length_exceeded` | Requête trop longue pour la fenêtre de contexte du modèle (`param: "messages"`), avec son explication. |
| 400 ou 413 | `no_available_route`, `invalid_request` | Le modèle a refusé la requête, avec son explication. |
| 402 | `insufficient_credits`, `spend_cap_exceeded`, `hold_exceeds_cap` | Le solde ou un plafond ne couvre pas la réserve (voir [Coûts](https://realmoon.ai/documentation/api/couts/#reserve)). |
| 403 | `org_policy` | Les règles de votre organisation refusent l’API ou ce modèle. |
| 404 | `model_not_found` | Modèle inconnu ou non servi par l’API (`param: "model"`). |
| 413 | `moon_blur_payload_too_large` | Un texte dépasse 500 000 caractères, trop long pour Moon Blur : rien n’est envoyé ni retenu. |
| 429 | `model_rate_limited` | Le modèle reçoit trop de requêtes, rien n’est facturé ; `Retry-After` dit quand réessayer. |
| 429 | `credits_held_in_progress` | Vos requêtes en cours retiennent le solde qui manque ; réessayez après `Retry-After` (2 secondes). |
| 500 à 504 | `upstream_error` | Le fournisseur a échoué, ou ne peut pas servir la requête pour l’instant. |
| 503 | `null` | `upstream unavailable` : le fournisseur n’a pas pu être joint. |
| 503 | `pricing_unavailable` | Prix du modèle momentanément inconnu : la requête est refusée plutôt que mal facturée. |
| 503 | `moon_blur_unavailable` | Moon Blur n’a pas pu analyser la requête : elle n’est pas envoyée, rien n’est retenu. `Retry-After: 5`. |
| 503 | `billing_unavailable`, `org_policy_unavailable` | Le solde ou les règles de l’organisation sont momentanément illisibles. |
| 504 | `upstream_timeout` | Le fournisseur n’a pas répondu à temps. La réserve est gardée (voir [Règlement](https://realmoon.ai/documentation/api/couts/#reglement)). |

Les erreurs de clé et de débit, communes à toute l’API, sont dans [Erreurs](https://realmoon.ai/documentation/api/erreurs/). Les refus du modèle sont relayés sans le nom de son fournisseur, ses liens ni ses identifiants internes.

## Voir aussi

- [Modèles](https://realmoon.ai/documentation/api/modeles/) : les identifiants et les prix.
- [Solde et coût d’une requête](https://realmoon.ai/documentation/api/solde/) : lire le coût d’une conversation.
- [Limites](https://realmoon.ai/documentation/api/limites/) : débit, durées et nouvelles tentatives.

---

Documentation Moon AI › API développeur › Conversation. Page : https://realmoon.ai/documentation/api/chat/. Modifiée le 5 novembre 2026.

© 2026 Stellarr Studio SAS. Tous droits réservés. Moon AI, Moon Blur et Stellarr Studio sont des marques déposées à l’INPI.
