> ## Documentation Index
> Fetch the complete documentation index at: https://docs.acedata.cloud/llms.txt
> Use this file to discover all available pages before exploring further.

# AI Chat v2 API Documentation

> AI Dialogue API guide - Ace Data Cloud

L'API AI Chat v2 (`/aichat2/conversations`) est la nouvelle génération d'interface de conversation, une version entièrement mise à jour de l'[API AI Chat](https://platform.acedata.cloud/documents/aichat-conversations). Elle s'étend sur la base de la v1 simple et hébergeant des conversations multi-tours :

* **Entrée utilisateur multimodale** : via le champ structuré `message`, il est possible de transmettre directement du texte + des images + des fichiers, sans avoir besoin de les ajouter indirectement avec `references`.
* **Appels d'outils agentisés** : un ensemble d'outils intégrés pour la recherche en ligne, le scraping web, la lecture de fichiers, etc., et la possibilité de monter des serveurs MCP autorisés par l'utilisateur (Google Drive, Notion, Slack, GitHub, etc.), le modèle peut appeler de manière autonome des outils en plusieurs tours dans une seule requête pour accomplir des tâches complexes.
* **Événements structurés en flux** : via `accept: text/event-stream` ou `application/x-ndjson`, il est possible d'obtenir des événements tels que `text_delta`, `tool_use`, `tool_result`, `thinking`, `citation`, `card`, `artifact`, etc., facilitant le rendu en front-end par type correspondant.
* **Interruption / Reprise** : le modèle émettra un événement `ask_user_question` et se mettra en pause lorsqu'il a besoin d'informations supplémentaires de l'utilisateur, la prochaine invocation peut continuer en remplissant la réponse via `tool_results`.
* **Nouvelles actions CRUD** : sur le même point de terminaison, il est possible d'effectuer `retrieve` / `retrieve_batch` / `update` / `delete` via le champ `action`, sans nécessiter d'API de gestion de session supplémentaire.
* **Liste de modèles mise à jour en continu** : accès par défaut à GPT-5.4, Claude Opus 4.8, Claude Sonnet 4.6, Gemini 3.1 Pro, GLM 5.1, DeepSeek V4, Kimi K3 et d'autres modèles contemporains.

De plus, au niveau du corps de la requête, elle est **entièrement rétrocompatible avec la v1** : il suffit de transmettre `model` + `question` (+ optionnel `stateful` / `id` / `references` / `preset`) pour obtenir une réponse JSON équivalente `{answer, id}` à celle de la v1, donc la migration depuis `/aichat/conversations` ne nécessite pas de réécriture du client, il suffit de changer le chemin en `/aichat2/conversations`.

> Si vous utilisez actuellement `/aichat/conversations`, l'ancienne interface restera disponible, vous pouvez migrer à votre rythme.

## Processus de demande

Pour utiliser l'API AI Chat v2, commencez par obtenir votre token API sur le [tableau de bord Ace Data Cloud](https://platform.acedata.cloud/console/applications) pour le garder en réserve.

![](https://cdn.acedata.cloud/5hmkdg.jpg)

Si vous n'êtes pas encore connecté ou inscrit, vous serez automatiquement redirigé vers la page de connexion pour vous inviter à vous inscrire et à vous connecter, après quoi vous serez automatiquement renvoyé à la page actuelle.

**Un seul token API suffit pour appeler tous les services de la plateforme, sans avoir besoin de demander séparément pour chaque service.** La première demande vous donnera un quota gratuit pour une expérience sans frais ; lorsque le quota est insuffisant, vous pouvez recharger le solde général dans le [tableau de bord](https://platform.acedata.cloud/console/coin).

> 📘 Documentation complète : [API AI Chat v2 →](https://platform.acedata.cloud/documents/aichat2-conversations)

## Utilisation de base

L'utilisation la plus simple est identique à la v1 : transmettez `model` + `question`, et obtenez `{answer, id}`.

Exemple CURL :

```shell theme={null}
curl -X POST 'https://api.acedata.cloud/aichat2/conversations' \
  -H 'accept: application/json' \
  -H 'authorization: Bearer {token}' \
  -H 'content-type: application/json' \
  -d '{
    "model": "gpt-5.4",
    "question": "Présentez AceDataCloud en une phrase."
  }'
```

Résultat retourné :

```json theme={null}
{
  "answer": "AceDataCloud est une plateforme API unifiée qui agrège des modèles AI mainstream et des services multimodaux, permettant aux développeurs d'accéder à GPT, Claude, Gemini, Midjourney, Suno, Veo et d'autres services avec une seule clé.",
  "id": "f2f4b3e8-0c0a-4d3a-aaa2-7ff80c0a1c44"
}
```

Exemple Python :

```python theme={null}
import requests

url = "https://api.acedata.cloud/aichat2/conversations"

headers = {
    "accept": "application/json",
    "authorization": "Bearer {token}",
    "content-type": "application/json",
}

payload = {
    "model": "gpt-5.4",
    "question": "Présentez AceDataCloud en une phrase.",
}

response = requests.post(url, json=payload, headers=headers)
print(response.json())
```

Les valeurs de `model` disponibles peuvent être directement vues dans le panneau d'essai à droite, les catégories courantes incluent :

* OpenAI : `gpt-5.4-mini`, `gpt-5.4-nano`, `gpt-5.2-pro`, `gpt-5.1-all`, `gpt-5-all`, `gpt-4.1`, `gpt-4o`, `gpt-4o-image`, `o3`, `o4-mini`, etc.
* Anthropic : `claude-opus-4-8`, `claude-opus-4-7`, `claude-opus-4-6`, `claude-opus-4-5-20251101`, `claude-sonnet-4-6`, `claude-sonnet-4-5-20250929`, `claude-haiku-4-5-20251001`, etc.
* Google : `gemini-3.1-pro`, `gemini-3.1-pro-preview`, `gemini-3.1-flash-image-preview`, `gemini-3-pro-preview`, `gemini-2.5-flash-lite`, etc.
* xAI : `grok-4`, etc.
* DeepSeek : `deepseek-v4-flash`, `deepseek-v3.2-exp`, `deepseek-r1-0528`, etc.
* Moonshot : `kimi-k3`, `kimi-k2.6`, `kimi-k2.5`, etc.
* Zhipu : `glm-5.1`, `glm-5`, `glm-5-turbo`, `glm-4.7`, `glm-4.5v`, etc.

Les règles de facturation spécifiques peuvent être consultées sur la carte de tarification de la page de service.

## Conversations multi-tours

Comme pour la v1, transmettez `stateful: true` pour activer la sauvegarde de session, l'API renverra un `id` ; les requêtes suivantes doivent inclure cet `id` pour continuer la conversation, sans avoir à gérer l'historique des messages vous-même.

Première requête :

```shell theme={null}
curl -X POST 'https://api.acedata.cloud/aichat2/conversations' \
  -H 'accept: application/json' \
  -H 'authorization: Bearer {token}' \
  -H 'content-type: application/json' \
  -d '{
    "model": "gpt-5.4",
    "stateful": true,
    "question": "Souviens-toi d'un nombre : 42."
  }'
```

Retour :

```json theme={null}
{
  "answer": "D'accord, je me souviens de 42. Que dois-je en faire ?",
  "id": "f2f4b3e8-0c0a-4d3a-aaa2-7ff80c0a1c44"
}
```

Deuxième requête, en incluant le même `id` :

```shell theme={null}
curl -X POST 'https://api.acedata.cloud/aichat2/conversations' \
  -H 'accept: application/json' \
  -H 'authorization: Bearer {token}' \
  -H 'content-type: application/json' \
  -d '{
    "model": "gpt-5.4",
    "stateful": true,
    "id": "f2f4b3e8-0c0a-4d3a-aaa2-7ff80c0a1c44",
    "question": "Quel est le nombre que je t'ai demandé de retenir tout à l'heure ?"
  }'
```

```json theme={null}
{
  "answer": "Le nombre que tu m'as demandé de retenir est 42.",
  "id": "f2f4b3e8-0c0a-4d3a-aaa2-7ff80c0a1c44"
}
```

> `stateful` est par défaut `true`, omettre et transmettre explicitement `true` sont équivalents. Si vous ne souhaitez pas que le serveur conserve cette conversation, vous pouvez définir explicitement `stateful: false`.

## Réponse en flux

v2 prend en charge deux formats de flux, selon l'en-tête `accept` :

| Scénario                             | `accept`                        | Forme des données                                        |
| ------------------------------------ | ------------------------------- | -------------------------------------------------------- |
| Frontend Web / EventSource           | `text/event-stream`             | `data: {json}\n\n`, la dernière ligne `data: [DONE]\n\n` |
| Serveur / CLI / Analyse de flux Node | `application/x-ndjson`          | Un objet JSON par ligne                                  |
| Pas besoin de flux                   | `application/json` (par défaut) | Retour unique `{answer, id}`                             |

### Exemple NDJSON

```python theme={null}
import json
import requests

url = "https://api.acedata.cloud/aichat2/conversations"

headers = {
    "accept": "application/x-ndjson",
    "authorization": "Bearer {token}",
    "content-type": "application/json",
}

payload = {
    "model": "gpt-5.4",
    "stateful": True,
    "question": "Présente Hangzhou en trois phrases.",
}

with requests.post(url, json=payload, headers=headers, stream=True) as resp:
    answer = ""
    for line in resp.iter_lines():
        if not line:
            continue
        event = json.loads(line)
        if event.get("type") == "text_delta":
            # Compatibilité avec v1 : les segments incrémentaux sont également fournis via le champ delta_answer
            answer += event["content"]
            print(event["delta_answer"], end="", flush=True)
        elif event.get("type") == "done":
            print()
            print("usage =", event.get("usage"))
```

Chaque ligne NDJSON est un événement structuré, le plus courant étant `text_delta` :

```json theme={null}
{"type":"text_delta","content":"杭","delta_answer":"杭","id":"f2f4b3e8-..."}
{"type":"text_delta","content":"州","delta_answer":"州","id":"f2f4b3e8-..."}
{"type":"text_delta","content":"是","delta_answer":"是","id":"f2f4b3e8-..."}
...
{"type":"done","conversation_id":"f2f4b3e8-...","usage":{"prompt_tokens":21,"completion_tokens":58,"total_tokens":79},"terminal_reason":"natural_stop"}
```

### Exemple SSE

L'utilisation de `EventSource` côté navigateur ne prend pas en charge les corps de requête personnalisés, il est recommandé d'utiliser `fetch` + découpage manuel par `\n\n` :

```javascript theme={null}
const resp = await fetch("https://api.acedata.cloud/aichat2/conversations", {
  method: "POST",
  headers: {
    accept: "text/event-stream",
    authorization: "Bearer {token}",
    "content-type": "application/json",
  },
  body: JSON.stringify({
    model: "gpt-5.4",
    stateful: true,
    question: "Présente Hangzhou en trois phrases.",
  }),
});

const reader = resp.body.getReader();
const decoder = new TextDecoder();
let buffer = "";
while (true) {
  const { value, done } = await reader.read();
  if (done) break;
  buffer += decoder.decode(value, { stream: true });
  const blocks = buffer.split("\n\n");
  buffer = blocks.pop() ?? "";
  for (const block of blocks) {
    const dataLine = block.split("\n").find((l) => l.startsWith("data: "));
    if (!dataLine) continue;
    const payload = dataLine.slice(6);
    if (payload === "[DONE]") return;
    const event = JSON.parse(payload);
    if (event.type === "text_delta") process.stdout.write(event.content);
  }
}
```

### Types d'événements en flux

| `type`              | Signification                                                                                                                                                                                                                            |
| ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `text_delta`        | Segments de texte incrémentaux de la réponse de l'assistant. `content` est le contenu ajouté ; pour compatibilité avec v1, le même événement transporte également `delta_answer` (égal à `content`) et `id`.                             |
| `thinking`          | Processus de réflexion du modèle (n'apparaît que lorsque le modèle sélectionné expose le raisonnement).                                                                                                                                  |
| `tool_use`          | Le modèle décide d'appeler un outil, l'événement transporte `tool_id`, `tool_name`, `input`.                                                                                                                                             |
| `tool_result`       | Résultat de l'exécution de l'outil, associé à la précédente `tool_use` par `tool_id`, `is_error` indique si cela a échoué.                                                                                                               |
| `card`              | Carte structurée produite par l'outil (comme une image, un aperçu de lien), adaptée à un rendu direct.                                                                                                                                   |
| `citation`          | Utilisé pour compléter la source URL d'un extrait de texte correspondant.                                                                                                                                                                |
| `ask_user_question` | Émis lorsque le modèle a besoin d'informations supplémentaires de l'utilisateur, la conversation entre dans l'état `awaiting_user_input`, voir ci-dessous [Restaurer une conversation suspendue](#restaurer-une-conversation-suspendue). |
| `artifact`          | Produit indépendant généré par le modèle (comme des blocs de code, des documents), pouvant être enregistré ou téléchargé.                                                                                                                |
| `system_message`    | Informations de message système (non contenu utilisateur-assistant), utilisées uniquement pour les notifications UI.                                                                                                                     |
| `compact`           | Événement dont le contexte interne a été compressé, sans besoin de traitement spécial.                                                                                                                                                   |
| `error`             | Une erreur s'est produite lors de ce tour, `message` décrit le contenu de l'erreur.                                                                                                                                                      |
| `done`              | Fin de la réponse en flux, transportant `usage` (comprenant `prompt_tokens` / `completion_tokens` / `total_tokens`) et `terminal_reason`.                                                                                                |

Pour les clients qui ne se soucient que de la réponse finale, concaténer tous les `content` de `text_delta` équivaut à `answer` en mode `application/json`.

## Entrée multimodale

Si l'entrée de l'utilisateur contient des images ou des fichiers, transmettez `message` (tableau) à la place de `question`. Chaque élément du tableau est un bloc de contenu :

```json theme={null}
{
  "model": "gpt-5.4",
  "stateful": true,
  "message": [
    { "type": "text", "text": "Combien de chats y a-t-il sur cette image ?" },
    { "type": "image_url", "image_url": { "url": "https://cdn.acedata.cloud/cats.jpg" } }
  ]
}
```

Types de blocs pris en charge :

* `text` — Texte ordinaire, champ `text` requis.
* `image_url` — Image, champ `image_url.url` requis.
* `file_url` — Fichier (PDF, CSV, TXT, etc.), champ `file_url.url` requis.

### Relation avec `references` de v1

Pour la compatibilité avec les anciens clients, v2 reconnaît toujours le champ `references: ["https://...", ...]` :

* Les suffixes d'URL sont `jpg / jpeg / png / gif / bmp / webp / svg / heic / heif`, automatiquement convertis en bloc `image_url` ;
* Les autres extensions sont converties en bloc `file_url` ;
* Si une `question` est également fournie, elle est placée comme un bloc `text` en préfixe.

Ainsi, si vous souhaitez migrer de v1 sans modifier le corps de la requête, il suffit de changer le chemin en `/aichat2/conversations`, l'utilisation originale de `references` fonctionne comme d'habitude.

Pour un contrôle plus précis (par exemple, placer plusieurs images entre le texte, ou si l'ordre est très important), utilisez directement le tableau `message`.

## Appels d'outils et MCP

Le point central d'amélioration de v2 est que le modèle peut appeler des outils de manière autonome pour accomplir des tâches en plusieurs étapes, **ceci est activé par défaut**, sans que le client ait besoin de faire des configurations supplémentaires dans la requête. Scénarios courants :

* L'utilisateur demande « Aide-moi à chercher les nouvelles expositions à Shanghai récemment » → le modèle appelle la recherche web intégrée → organise les résultats en réponse.
* L'utilisateur demande « Lis ce PDF puis écris un résumé » → le modèle appelle file\_read → écrit le résumé.
* L'utilisateur a déjà autorisé Google Drive / GitHub / Notion, etc., dans [Connections](https://platform.acedata.cloud/connections) → le modèle peut appeler les outils MCP correspondants pour lire et écrire ses données.

Dans le flux NDJSON / SSE, les appels d'outils sont présentés par les événements `tool_use` et `tool_result`, par exemple :

```json theme={null}
{"type":"tool_use","tool_id":"toolu_01ABCDEF","tool_name":"web_search","input":{"query":"expositions de printemps 2026 à Shanghai"},"id":"f2f4b3e8-..."}
{"type":"tool_result","tool_id":"toolu_01ABCDEF","output":"...","is_error":false,"id":"f2f4b3e8-..."}
{"type":"text_delta","content":"Actuellement","delta_answer":"Actuellement","id":"f2f4b3e8-..."}
{"type":"text_delta","content":"Shanghai","delta_answer":"Shanghai","id":"f2f4b3e8-..."}
...
```

Si vous ne souhaitez pas afficher les détails des appels d'outils sur le front-end, ignorez les événements `tool_use` / `tool_result` / `card` / `citation`, la sortie finale du modèle passe toujours par `text_delta`.

`max_turns` peut limiter le nombre maximum d'appels d'outils que le modèle peut faire dans cette requête, la limite par défaut est déterminée par la plateforme. La définir à un petit nombre (par exemple `max_turns: 1`) peut forcer une réponse unique, sans permettre d'appels d'outils.

## Exécution asynchrone et autorisation sans surveillance

Si votre appel provient d'un Webhook d'alerte, CI/CD, système de surveillance ou autre tâche en arrière-plan, vous pouvez définir `async: true` pour que l'interface retourne immédiatement l'ID de la tâche, l'arrière-plan continue l'exécution :

```json theme={null}
{
  "model": "gpt-5.5",
  "async": true,
  "question": "Mon service a déclenché une alerte, utilise WeChat personnel pour notifier le groupe WeChat « Équipe AceDataCloud »……"
}
```

Exemple de retour :

```json theme={null}
{
  "task_id": "f2f4b3e8-0c0a-4d3a-aaa2-7ff80c0a1c44",
  "conversation_id": "f2f4b3e8-0c0a-4d3a-aaa2-7ff80c0a1c44",
  "id": "f2f4b3e8-0c0a-4d3a-aaa2-7ff80c0a1c44",
  "status": "queued"
}
```

Vous pouvez ensuite utiliser `action: retrieve` + `id` pour interroger les résultats de la conversation ; vous pouvez également fournir `callback_url`, après l'achèvement de la tâche, la plateforme enverra `{ status, answer, usage, error }` par POST à votre adresse de rappel. `callback_url` doit utiliser `http` / `https`, et ne peut pas être directement rempli avec `localhost` ou une adresse IP privée littérale.

Les tâches en arrière-plan n'ont généralement personne pour cliquer sur la confirmation. Si vous souhaitez que certaines compétences ou serveurs MCP exécutent des actions d'envoi, de publication, d'écriture, etc., en mode sans surveillance, veuillez transmettre explicitement la liste des pré-autorisations dans le corps de la requête :

```json theme={null}
{
  "model": "gpt-5.5",
  "async": true,
  "allowed_skills": ["acedatacloud/personal-wechat"],
  "allowed_mcp_servers": [],
  "question": "Mon service a déclenché une alerte, utilise WeChat personnel pour notifier le groupe WeChat « Équipe AceDataCloud »……"
}
```

Les valeurs dans `allowed_skills` sont les slugs des compétences connectées ; les valeurs dans `allowed_mcp_servers` sont les slugs des serveurs MCP connectés. Les compétences / serveurs MCP non inclus dans la pré-autorisation ne peuvent toujours que prévisualiser, faire un dry-run ou refuser d'exécuter des opérations d'écriture en mode sans surveillance.

Si un contrôle plus fin est nécessaire, vous pouvez également utiliser l'objet équivalent `unattended_policy` :

```json theme={null}
{
  "unattended_policy": {
    "allowed_skills": ["acedatacloud/personal-wechat"],
    "allowed_mcp_servers": [],
    "expires_at": 1790000000
  }
}
```

La pré-autorisation est simplement ces deux listes elles-mêmes : une liste vide signifie qu'aucune capacité n'est autorisée, sans besoin de champ de commutation supplémentaire.

Remarque : la pré-autorisation ne représente que « cette requête permet à ces capacités de sauter la confirmation humaine en mode sans surveillance ». Les compétences spécifiques doivent toujours prendre en charge `--unattended-confirm` ou un mécanisme de sécurité correspondant ; sinon, elles continueront à faire un dry-run et ne procéderont pas à l'exécution des opérations d'écriture.

## Récupération de conversations suspendues

Certains outils amènent le modèle à « poser une question à l'utilisateur », à ce moment-là, le modèle émet un événement `ask_user_question`, la conversation est gelée dans l'état `awaiting_user_input` :

```json theme={null}
{
  "type": "ask_user_question",
  "tool_id": "toolu_01XYZW",
  "tool_name": "ask_user_question",
  "question": "Souhaitez-vous que le rapport généré soit en chinois ou en anglais ?",
  "options": ["中文", "英文"],
  "id": "f2f4b3e8-..."
}
```

Sur le front-end, ce type d'événement est rendu sous forme de carte pour que l'utilisateur choisisse une réponse, puis avec le même `id`, vous lancez une nouvelle requête, en renvoyant la réponse via `tool_results` :

```shell theme={null}
curl -X POST 'https://api.acedata.cloud/aichat2/conversations' \
  -H 'accept: text/event-stream' \
  -H 'authorization: Bearer {token}' \
  -H 'content-type: application/json' \
  -d '{
    "model": "gpt-5.4",
    "stateful": true,
    "id": "f2f4b3e8-0c0a-4d3a-aaa2-7ff80c0a1c44",
    "tool_results": [
      {
        "tool_use_id": "toolu_01XYZW",
        "output": "中文"
      }
    ]
  }'
```

Dans le corps de la requête, `tool_use_id` **doit** être exactement identique à `tool_id` au moment de la suspension ; toute incohérence renverra 400. Lorsque `tool_results` est présent dans la requête, `question` / `message` / `references` seront tous ignorés.

Si l'utilisateur décide d'abandonner cette question, il suffit de transmettre une nouvelle `question` / `message`, la plateforme marquera automatiquement l'appel d'outil suspendu comme « sauté par l'utilisateur ».

## Gestion des sessions (CRUD)

v2 propose une gestion légère des sessions via le champ `action` sur le même point de terminaison, sans nécessiter d'API supplémentaire.

### `action: retrieve` —— Récupérer une session

```shell theme={null}
curl -X POST 'https://api.acedata.cloud/aichat2/conversations' \
  -H 'accept: application/json' \
  -H 'authorization: Bearer {token}' \
  -H 'content-type: application/json' \
  -d '{
    "action": "retrieve",
    "id": "f2f4b3e8-0c0a-4d3a-aaa2-7ff80c0a1c44"
  }'
```

Retourne le document de conversation complet (y compris l'historique des `messages`, `model`, `title`, `tools_used`, etc.).

### `action: retrieve_batch` —— Lister les résumés de conversation

```json theme={null}
{
  "action": "retrieve_batch",
  "model_group": "chatgpt",
  "limit": 20,
  "offset": 0
}
```

Retourne `{ items: [...], total }`. **Le résumé ne contient pas de `messages`**, adapté pour une liste de barre latérale ; si l'utilisateur ouvre une conversation, utilisez ensuite `action: retrieve` pour récupérer ses messages complets.

Paramètres de filtrage optionnels : `user_id`, `application_id`, `model_group`, `model`.

### `action: update` —— Modifier le titre ou réécrire l'historique

```json theme={null}
{
  "action": "update",
  "id": "f2f4b3e8-0c0a-4d3a-aaa2-7ff80c0a1c44",
  "title": "Plan de voyage à Hangzhou"
}
```

Les `messages` peuvent également être transmis, mais le serveur effectuera une validation stricte du schéma (doit être sous la forme de `ToolUseContent` repliée), toute non-conformité retournera 400. Il est généralement conseillé de l'utiliser uniquement pour modifier le `title`.

### `action: delete` —— Supprimer une conversation

```json theme={null}
{
  "action": "delete",
  "id": "f2f4b3e8-0c0a-4d3a-aaa2-7ff80c0a1c44"
}
```

Retourne `{ id, success: true }`. Une fois supprimé, il ne peut pas être récupéré, veuillez confirmer avant d'appeler.

## Migration fluide depuis v1

Si vous utilisez déjà [`/aichat/conversations`](https://platform.acedata.cloud/documents/aichat-conversations), la migration vers v2 nécessite presque aucune modification de code :

1. Changez l'URL de `https://api.acedata.cloud/aichat/conversations` à `https://api.acedata.cloud/aichat2/conversations`.
2. Si vous avez précédemment utilisé des noms de modèles v1 (comme `gpt-3.5`, `gpt-4-browsing`, etc.), il est conseillé de passer aux modèles contemporains (comme `gpt-5.4`, `claude-opus-4-8`, `gemini-3.1-pro`, etc.) lors de la transition vers v2.
3. Les champs du flux NDJSON restent rétrocompatibles : chaque événement `text_delta` contient toujours `delta_answer` et `id`, donc les clients qui analysent `delta_answer` par ligne n'ont pas besoin de modification.

Après la migration, vous pouvez activer les nouvelles capacités de v2 selon vos besoins (message multimodal, SSE, appels d'outils, CRUD d'`action`), à votre rythme.

## Gestion des erreurs

Les réponses d'erreur sont uniformément :

```json theme={null}
{
  "error": {
    "code": "chat_error",
    "message": "le LLM en amont a retourné une erreur"
  },
  "trace_id": "2cf86e86-22a4-46e1-ac2f-032c0f2a4e89"
}
```

Erreurs courantes :

* `400 bad_request` : champs obligatoires manquants, `tool_use_id` non correspondant, schéma des `messages` illégal, etc.
* `401 invalid_token` : l'en-tête `authorization` est incorrect.
* `404 not_found` : lors de `action: retrieve / update / delete`, la conversation correspondant à `id` n'existe pas.
* `429 too_many_requests` : limite de taux atteinte.
* `500 chat_error` : erreur du LLM en amont ou `completion_tokens=0` pour ce tour (traité comme non consommé, aucun frais ne sera facturé).

Dans les réponses en streaming, les erreurs sont envoyées sous la forme `{"type":"error","message":"..."}` et le flux se termine immédiatement après.

## Conclusion

L'API AI Chat v2 est rétrocompatible avec v1 tout en mettant à niveau les conversations de « questions-réponses à une ou plusieurs étapes » à « conversations observables par agent » : entrée multimodale, appels d'outils, pause/reprise, événements structurés en streaming, CRUD intégré. Il est conseillé aux nouvelles intégrations d'utiliser directement v2 ; les intégrations existantes de v1 peuvent migrer en plusieurs étapes. Si vous avez des questions, n'hésitez pas à contacter notre équipe de support technique.
