> ## 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 Integración

> AI Dialogue API guide - Ace Data Cloud

AI Chat v2 API (`/aichat2/conversations`) es la nueva generación de la interfaz de conversación, una versión completamente mejorada de [AI Chat API](https://platform.acedata.cloud/documents/aichat-conversations). Se basa en la simplicidad de v1 y la gestión de diálogos múltiples, y se ha ampliado con:

* **Entrada de usuario multimodal**: a través del campo estructurado `message`, se puede enviar texto + imágenes + bloques de archivos directamente, sin necesidad de adjuntar indirectamente con `references`.
* **Llamadas a herramientas como agente**: incluye un conjunto de herramientas para búsqueda en línea, raspado web, lectura de archivos, etc., y puede montar servidores MCP autorizados por el usuario (Google Drive, Notion, Slack, GitHub, etc.), permitiendo que el modelo llame a herramientas de forma autónoma en una sola solicitud para completar tareas complejas.
* **Eventos estructurados en flujo**: a través de `accept: text/event-stream` o `application/x-ndjson`, se pueden obtener eventos como `text_delta`, `tool_use`, `tool_result`, `thinking`, `citation`, `card`, `artifact`, etc., lo que facilita la renderización en el frontend según el tipo correspondiente.
* **Interrumpible / recuperable**: el modelo emitirá un evento `ask_user_question` y se pausará cuando necesite información adicional del usuario; la próxima llamada puede continuar rellenando la respuesta a través de `tool_results`.
* **Nuevas acciones CRUD**: en el mismo endpoint, se pueden realizar `retrieve` / `retrieve_batch` / `update` / `delete` a través del campo `action`, sin necesidad de una API de gestión de sesiones adicional.
* **Lista de modelos en constante actualización**: por defecto, se conectan modelos contemporáneos como GPT-5.4, Claude Opus 4.8, Claude Sonnet 4.6, Gemini 3.1 Pro, GLM 5.1, DeepSeek V4, Kimi K3, entre otros.

Además, en el nivel del cuerpo de la solicitud, es **totalmente compatible hacia atrás con v1**: solo se necesita enviar `model` + `question` (+ opcionalmente `stateful` / `id` / `references` / `preset`) para obtener una respuesta JSON `{answer, id}` equivalente a v1, por lo que la migración desde `/aichat/conversations` no requiere reescribir el cliente, solo cambiar la ruta a `/aichat2/conversations`.

> Si actualmente estás utilizando `/aichat/conversations`, la interfaz antigua seguirá disponible, puedes migrar a tu propio ritmo.

## Proceso de Solicitud

Para usar AI Chat v2 API, primero ve a [Ace Data Cloud Console](https://platform.acedata.cloud/console/applications) para obtener tu API Token, guárdalo como respaldo.

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

Si aún no has iniciado sesión o registrado, serás redirigido automáticamente a la página de inicio de sesión que te invitará a registrarte e iniciar sesión; una vez completado, volverás automáticamente a la página actual.

**Un API Token es suficiente para acceder a todos los servicios de la plataforma, no es necesario solicitar uno por cada servicio.** La primera solicitud incluirá un crédito gratuito para que puedas probar; si el crédito es insuficiente, puedes recargar el saldo general en [la consola](https://platform.acedata.cloud/console/coin).

> 📘 Documentación completa: [AI Chat v2 API →](https://platform.acedata.cloud/documents/aichat2-conversations)

## Uso Básico

La forma más simple de uso es completamente idéntica a v1: envía `model` + `question` y obtén `{answer, id}`.

Ejemplo de 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": "Describe AceDataCloud en una frase."
  }'
```

Resultado devuelto:

```json theme={null}
{
  "answer": "AceDataCloud es una plataforma API unificada que agrega modelos de IA y servicios multimodales, permitiendo a los desarrolladores acceder a servicios como GPT, Claude, Gemini, Midjourney, Suno, Veo, entre otros, con una sola clave.",
  "id": "f2f4b3e8-0c0a-4d3a-aaa2-7ff80c0a1c44"
}
```

Ejemplo en 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": "Describe AceDataCloud en una frase.",
}

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

Los valores disponibles para `model` se pueden ver directamente en el panel de prueba a la derecha, las categorías comunes incluyen:

* 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.

Las reglas de facturación específicas se pueden consultar en la tarjeta de precios de la página de servicios.

## Diálogo Multiturno

Al igual que en v1, envía `stateful: true` para habilitar el almacenamiento de la sesión, la API devolverá un `id`; las solicitudes posteriores deben incluir el `id` para continuar la conversación, sin necesidad de mantener el historial de mensajes.

Primera solicitud:

```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": "Recuerda un número: 42."
  }'
```

Respuesta:

```json theme={null}
{
  "answer": "Está bien, ya he recordado 42. ¿Qué necesitas que haga con él?",
  "id": "f2f4b3e8-0c0a-4d3a-aaa2-7ff80c0a1c44"
}
```

Segunda solicitud, incluye el mismo `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": "¿Cuál es el número que te pedí que recordaras hace un momento?"
  }'
```

```json theme={null}
{
  "answer": "El número que me pediste que recordara es 42.",
  "id": "f2f4b3e8-0c0a-4d3a-aaa2-7ff80c0a1c44"
}
```

> `stateful` por defecto es `true`, omitirlo y pasar `true` es equivalente. Si no deseas que el servidor guarde esta ronda de conversación, puedes establecer explícitamente `stateful: false`.

## Respuesta en flujo

v2 soporta dos formatos de flujo, seleccionados según el encabezado `accept`:

| Escenario                                  | `accept`                         | Forma de datos                                         |
| ------------------------------------------ | -------------------------------- | ------------------------------------------------------ |
| Frontend Web / EventSource                 | `text/event-stream`              | `data: {json}\n\n`, la última línea `data: [DONE]\n\n` |
| Servidor / CLI / Análisis de flujo en Node | `application/x-ndjson`           | Un objeto JSON por línea                               |
| Sin necesidad de flujo                     | `application/json` (por defecto) | Devuelve una vez `{answer, id}`                        |

### Ejemplo de 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": "Describe Hangzhou en tres frases.",
}

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":
            # Compatible con v1: fragmentos incrementales también se proporcionan a través del campo delta_answer
            answer += event["content"]
            print(event["delta_answer"], end="", flush=True)
        elif event.get("type") == "done":
            print()
            print("uso =", event.get("usage"))
```

Cada línea de NDJSON es un evento estructurado, siendo el más común `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"}
```

### Ejemplo de SSE

El lado del navegador usa `EventSource` y no soporta un cuerpo de solicitud personalizado, se recomienda usar `fetch` + análisis manual por `\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: "Describe Hangzhou en tres frases.",
  }),
});

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);
  }
}
```

### Tipos de eventos en flujo

| `type`              | Significado                                                                                                                                                                                                      |
| ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `text_delta`        | Fragmentos de texto incrementales de la respuesta del asistente. `content` es el contenido nuevo; para compatibilidad con v1, el mismo evento también lleva `delta_answer` (igual a `content`) y `id`.           |
| `thinking`          | Proceso de pensamiento del modelo (solo aparece cuando el modelo seleccionado expone razonamiento).                                                                                                              |
| `tool_use`          | El modelo decide llamar a una herramienta, el evento lleva `tool_id`, `tool_name`, `input`.                                                                                                                      |
| `tool_result`       | Resultado de la ejecución de la herramienta, emparejado con la anterior `tool_use` a través de `tool_id`, `is_error` indica si falló.                                                                            |
| `card`              | Tarjeta estructurada producida por la herramienta (como imágenes, vista previa de enlaces), adecuada para renderizar directamente.                                                                               |
| `citation`          | Se utiliza para complementar la fuente URL de un fragmento de texto correspondiente.                                                                                                                             |
| `ask_user_question` | Emitido cuando el modelo necesita información adicional del usuario, la conversación entra en estado `awaiting_user_input`, ver más abajo [Reanudar conversación pausada](#reanudación-de-conversación-pausada). |
| `artifact`          | Producto independiente generado por el modelo (como bloques de código, documentos), que se puede guardar o descargar.                                                                                            |
| `system_message`    | Mensaje de información del sistema (no contenido del usuario y asistente), solo para indicaciones de UI.                                                                                                         |
| `compact`           | Evento de contexto interno comprimido, no requiere tratamiento especial.                                                                                                                                         |
| `error`             | Error ocurrido en esta ronda, `message` describe el contenido del error.                                                                                                                                         |
| `done`              | Fin de la respuesta en flujo, lleva `usage` (que incluye `prompt_tokens` / `completion_tokens` / `total_tokens`) y `terminal_reason`.                                                                            |

Para los clientes que solo se preocupan por la respuesta final, concatenar todos los `content` de `text_delta` es equivalente a `answer` en modo `application/json`.

## Entrada multimodal

Si la entrada del usuario incluye imágenes o archivos, pasa `message` (array) en lugar de `question`. Cada elemento del array es un bloque de contenido:

```json theme={null}
{
  "model": "gpt-5.4",
  "stateful": true,
  "message": [
    { "type": "text", "text": "¿Cuántos gatos hay en esta imagen?" },
    { "type": "image_url", "image_url": { "url": "https://cdn.acedata.cloud/cats.jpg" } }
  ]
}
```

Tipos de bloques soportados:

* `text` — Texto normal, el campo `text` es obligatorio.
* `image_url` — Imagen, el campo `image_url.url` es obligatorio.
* `file_url` — Archivo (PDF, CSV, TXT, etc.), el campo `file_url.url` es obligatorio.

### Relación con `references` de v1

Para compatibilidad con clientes antiguos, v2 aún reconoce el campo `references: ["https://...", ...]`:

* La extensión de la URL es `jpg / jpeg / png / gif / bmp / webp / svg / heic / heif`, se convierte automáticamente en un bloque `image_url`;
* Otras extensiones se convierten en un bloque `file_url`;
* Si también se proporciona una `question`, se coloca como un bloque `text` al principio.

Por lo tanto, si solo deseas migrar de v1 y no quieres cambiar el cuerpo de la solicitud, simplemente cambia la ruta a `/aichat2/conversations`, el uso original de `references` seguirá funcionando.

Si necesitas un control más fino (por ejemplo, colocar varias imágenes entre textos, o si el orden es muy importante), utiliza directamente el array `message`.

## Llamadas a herramientas y MCP

El punto central de mejora de v2 es que el modelo puede llamar a herramientas de forma autónoma para completar tareas de múltiples pasos, **esto está habilitado por defecto**, no se requiere que el cliente haga ninguna configuración adicional en la solicitud. Escenarios comunes:

* El usuario pregunta "Ayúdame a buscar qué nuevas exposiciones hay en Shanghái" → el modelo llama a la búsqueda web incorporada → organiza los resultados en una respuesta.
* El usuario pregunta "Lee este PDF y luego escribe un resumen" → el modelo llama a file\_read → escribe el resumen.
* El usuario ya ha autorizado en [Connections](https://platform.acedata.cloud/connections) Google Drive / GitHub / Notion, etc. → el modelo puede llamar a las herramientas MCP correspondientes para leer y escribir sus datos.

En el flujo NDJSON / SSE, las llamadas a herramientas se presentan a través de eventos de `tool_use` y `tool_result`, por ejemplo:

```json theme={null}
{"type":"tool_use","tool_id":"toolu_01ABCDEF","tool_name":"web_search","input":{"query":"exposición de primavera 2026 en Shanghái"},"id":"f2f4b3e8-..."}
{"type":"tool_result","tool_id":"toolu_01ABCDEF","output":"...","is_error":false,"id":"f2f4b3e8-..."}
{"type":"text_delta","content":"Actualmente","delta_answer":"Actualmente","id":"f2f4b3e8-..."}
{"type":"text_delta","content":"Shanghái","delta_answer":"Shanghái","id":"f2f4b3e8-..."}
...
```

Si no deseas mostrar los detalles de la llamada a la herramienta en el frontend, ignora los eventos `tool_use` / `tool_result` / `card` / `citation`, la salida final del modelo seguirá fluyendo a través de `text_delta`.

`max_turns` puede limitar cuántas veces el modelo puede llamarse a sí mismo en esta solicitud, el límite predeterminado es decidido por la plataforma. Establecerlo bajo (por ejemplo, `max_turns: 1`) puede forzar una respuesta única, sin permitir ninguna llamada a herramientas.

## Ejecución asíncrona y autorización sin supervisión

Si tu llamada proviene de un Webhook de alerta, CI/CD, sistema de monitoreo u otra tarea en segundo plano, puedes establecer `async: true` para que la interfaz devuelva inmediatamente el ID de la tarea, continuando la ejecución en segundo plano:

```json theme={null}
{
  "model": "gpt-5.5",
  "async": true,
  "question": "Mi servicio ha alertado, notifica al grupo de WeChat 'Equipo AceDataCloud'..."
}
```

Ejemplo de respuesta:

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

Luego puedes usar `action: retrieve` + `id` para consultar el resultado de la conversación; también puedes proporcionar `callback_url`, y una vez que la tarea esté completa, la plataforma enviará `{ status, answer, usage, error }` a tu dirección de callback. `callback_url` debe usar `http` / `https`, y no se puede ingresar directamente `localhost` o direcciones IP privadas.

Las tareas en segundo plano generalmente no pueden ser confirmadas por nadie. Si deseas que ciertas habilidades o servidores MCP realicen acciones de envío, publicación, escritura, etc., en modo sin supervisión, proporciona explícitamente la lista de preautorización en el cuerpo de la solicitud:

```json theme={null}
{
  "model": "gpt-5.5",
  "async": true,
  "allowed_skills": ["acedatacloud/personal-wechat"],
  "allowed_mcp_servers": [],
  "question": "Mi servicio ha alertado, notifica al grupo de WeChat 'Equipo AceDataCloud'..."
}
```

Los valores en `allowed_skills` son los slug de las habilidades conectadas; los valores en `allowed_mcp_servers` son los slug de los servidores MCP conectados. Las habilidades / servidores MCP no incluidos en la preautorización solo podrán previsualizar, realizar pruebas o rechazar operaciones de escritura en modo sin supervisión.

Si necesitas un control más detallado, también puedes usar el objeto equivalente `unattended_policy`:

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

La preautorización es simplemente estas dos listas: una lista vacía significa que no se autoriza ninguna capacidad, sin necesidad de un campo de interruptor adicional.

Nota: La preautorización solo representa "esta solicitud permite que estas capacidades se salten la confirmación manual en modo sin supervisión". La habilidad específica aún debe soportar `--unattended-confirm` o mecanismos de seguridad correspondientes; de lo contrario, continuará en modo de prueba y no ejecutará directamente operaciones de escritura.

## Recuperar conversaciones pausadas

Algunas herramientas harán que el modelo "pregunte al usuario", en este momento el modelo emitirá un evento `ask_user_question`, y la conversación se congelará en estado `awaiting_user_input`:

```json theme={null}
{
  "type": "ask_user_question",
  "tool_id": "toolu_01XYZW",
  "tool_name": "ask_user_question",
  "question": "¿Prefieres que el informe generado sea en chino o en inglés?",
  "options": ["chino", "inglés"],
  "id": "f2f4b3e8-..."
}
```

En el frontend, renderiza este evento como una tarjeta para que el usuario elija una respuesta, luego usa el mismo `id` para iniciar la siguiente solicitud, rellenando la respuesta a través de `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": "chino"
      }
    ]
  }'
```

El `tool_use_id` en el cuerpo de la solicitud **debe** coincidir exactamente con el `tool_id` en el momento de la pausa; de lo contrario, se devolverá un 400. Cuando hay `tool_results` en la solicitud, se ignorarán `question` / `message` / `references`.

Si el usuario decide abandonar esta pregunta, simplemente envía una nueva `question` / `message`, y la plataforma marcará automáticamente la llamada a la herramienta pausada como "saltada por el usuario".

## Gestión de sesiones (CRUD)

v2 proporciona gestión de sesiones ligera a través del campo `action` en el mismo endpoint, sin necesidad de abrir una API adicional.

### `action: retrieve` — Obtener una sesión

```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"
  }'
```

Devuelve el documento completo de la conversación (incluyendo el historial de `messages`, `model`, `title`, `tools_used`, etc.).

### `action: retrieve_batch` —— Listar resúmenes de conversaciones

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

Devuelve `{ items: [...], total }`. **El resumen no incluye `messages`**, es adecuado para hacer una lista en la barra lateral; si el usuario abre una conversación, se puede usar `action: retrieve` para obtener sus mensajes completos.

Parámetros de filtrado opcionales: `user_id`, `application_id`, `model_group`, `model`.

### `action: update` —— Cambiar el título o reescribir el historial

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

También se pueden enviar `messages`, pero el servidor realizará una verificación estricta del esquema (debe ser en la forma de `ToolUseContent` colapsado), si no cumple, devolverá 400. Generalmente se recomienda usarlo solo para cambiar el `title`.

### `action: delete` —— Eliminar una conversación

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

Devuelve `{ id, success: true }`. Una vez eliminada, no se puede recuperar, por favor confirma antes de llamar.

## Migración suave desde v1

Si ya estás utilizando [`/aichat/conversations`](https://platform.acedata.cloud/documents/aichat-conversations), migrar a v2 casi no requiere cambios en el código:

1. Cambia la URL de `https://api.acedata.cloud/aichat/conversations` a `https://api.acedata.cloud/aichat2/conversations`.
2. Si anteriormente usabas nombres de modelos v1 (como `gpt-3.5`, `gpt-4-browsing`, etc.), al cambiar a v2 se recomienda actualizar a modelos contemporáneos (como `gpt-5.4`, `claude-opus-4-8`, `gemini-3.1-pro`, etc.).
3. Los campos del flujo NDJSON se mantienen compatibles hacia atrás: cada evento `text_delta` aún lleva `delta_answer` e `id`, por lo que los clientes que originalmente analizaban `delta_answer` por línea no necesitan cambios.

Después de la migración, puedes habilitar las nuevas capacidades de v2 según sea necesario (entrada multimodal `message`, SSE, llamadas a herramientas, CRUD de `action`), avanzando a tu propio ritmo.

## Manejo de errores

Las respuestas de error son uniformes:

```json theme={null}
{
  "error": {
    "code": "chat_error",
    "message": "el LLM de upstream devolvió un error"
  },
  "trace_id": "2cf86e86-22a4-46e1-ac2f-032c0f2a4e89"
}
```

Errores comunes:

* `400 bad_request`: falta un campo obligatorio, `tool_use_id` no coincide, esquema de `messages` no válido, etc.
* `401 invalid_token`: el encabezado `authorization` no es correcto.
* `404 not_found`: al usar `action: retrieve / update / delete`, la conversación correspondiente al `id` no existe.
* `429 too_many_requests`: se activó el límite de velocidad.
* `500 chat_error`: error del LLM de upstream o en esta ronda `completion_tokens=0` (se maneja como no consumido, no se cobrará).

En la respuesta en streaming, los errores se envían como `{"type":"error","message":"..."}` y a continuación el flujo se detendrá.

## Conclusión

La API de AI Chat v2, manteniendo la compatibilidad con v1, ha actualizado las conversaciones de "preguntas y respuestas de una sola ronda/múltiples rondas" a "conversaciones observables tipo Agente": entrada multimodal, llamadas a herramientas, pausables/reanudables, eventos estructurados en streaming, CRUD incorporado. Se recomienda que las nuevas integraciones utilicen directamente v2; las integraciones existentes de v1 pueden migrar suavemente en fases. Si tienes alguna pregunta, no dudes en contactar a nuestro equipo de soporte técnico.
