# Métricas de las conversaciones para tu bodega de datos

Una fila por conversación con sus tiempos: cuándo entró, cuándo el agente la derivó a una persona, cuándo alguien la tomó, cuándo se cerró y quién la cerró. Sirve para llevarlas cada hora a BigQuery u otra bodega y medir ahí cuántas resuelve el agente solo, cuántas pasan a una persona y cuánto esperan.

Base de la API de Lelemon: `https://api.lelemon.cl`

## Antes de empezar

Necesitas una credencial con el alcance `conversations:read`, la misma con la que lees una conversación. Se emite en Integraciones API del dashboard.

Los tiempos salen de un registro de cada paso de la conversación que existe desde el 19 de octubre de 2026. Una conversación anterior aparece recién cuando cambia, y le faltan los pasos de antes de esa fecha.

## El pedido

```
GET https://api.lelemon.cl/v1/external/metrics/conversations?from=2026-10-19T13:00:00Z&to=2026-10-19T14:00:00Z
Authorization: Bearer <tu credencial>
```

- `from` (obligatorio) y `to` (opcional, por omisión ahora) son fechas ISO 8601. Traen las conversaciones cuyo **último cambio** fue en ese rango, `to` sin incluir. El rango puede ser de hasta 31 días.
- `limit` (por omisión 50, hasta 500) y `offset` paginan. Mientras `hasMore` sea `true`, pide la página siguiente sumando `limit` al `offset`.

Para bajarlas cada hora: pide la última hora y guarda cada fila por `conversationId`, reemplazando la que tenías. Una conversación vuelve a venir cada vez que cambia, con todos sus tiempos al día.

Manda siempre `to` fijo, el mismo en todas las páginas de un barrido. Si una conversación cambia mientras paginas, pasa a la ventana siguiente y vuelve a venir ahí.

## La respuesta

`200` con `data`, `limit`, `offset` y `hasMore`. Cada fila de `data` trae:

| Campo | Qué es |
|---|---|
| `conversationId` | El id de la conversación. |
| `pipelineId`, `pipelineName` | El embudo. |
| `status`, `controlStatus`, `outcome` | Cómo está ahora: su estado, quién la tiene (`agent`, `escalated`, `human`) y el motivo de cierre, si lo hay. |
| `createdAt` | Cuándo entró. |
| `escalatedAt` | La primera vez que el agente la derivó a una persona, o `null`. |
| `takenAt`, `takenBy` | La primera vez que una persona la tomó, y quién (`null` si la tomaron desde el celular). |
| `closedAt` | Cuándo se cerró, o `null` si sigue abierta. |
| `closedBy` | Quién la cerró: `ai` (el agente), `human` (una persona) o `system` (cierre por inactividad o seguimiento agotado). |
| `resolvedByAi` | `true` si la cerró el agente sin derivarla ni que nadie la tomara. |
| `waitSeconds` | Segundos entre la última derivación y que una persona la tomara, la primera vez que eso pasó. `null` si nadie la tomó después de una derivación. |
| `aiSeconds`, `humanSeconds` | Segundos que la atendió el agente y que la atendió una persona. El tiempo esperando a una persona no cuenta en ninguno. En una conversación abierta corren hasta su último cambio. |
| `updatedAt` | Su último cambio. Es el campo por el que filtra el rango. |

Con eso salen, por ejemplo:

- **Chats entrados:** las filas con `createdAt` en el período, contadas sobre tu tabla completa (no sobre lo que bajaste en la última hora).
- **Resueltos por el agente:** las que tienen `resolvedByAi` en `true`.
- **Pasados a una persona:** las que tienen `takenAt`.
- **Espera:** el promedio de `waitSeconds`.

## Errores

- `400` si falta `from`, si una fecha no es ISO 8601, si `to` no es posterior a `from` o si el rango pasa de 31 días.
- `401` sin credencial o con una revocada, y `403` si la credencial no tiene `conversations:read`.
