
# API de analíticas e informes

Estos endpoints de solo lectura le permiten extraer la actividad de su cuenta a sus propios paneles e informes: recuentos de eventos de mensajes, consumo de créditos, gasto en IA y los mismos gráficos e información que muestra el panel dentro de la aplicación. Esta guía cubre:

- **Resumen** — contadores de volumen de mensajes (enviados, entregados, leídos, respondidos, reservados, contactos creados, créditos).
- **Créditos** — un libro mayor detallado y paginado del uso de créditos con totales y desgloses.
- **Coste de IA** — un resumen diario del gasto en IA.
- **Series de métricas** — una serie temporal lista para gráficos para una o más métricas, agrupadas por campaña, canal, Agente de IA o número.
- **Resultados de las conversaciones** — cómo terminaron las conversaciones, según la etiqueta de resultado asignada por la IA.
- **Información del panel** e **Información de IA del panel** — todos los datos detrás del panel de la aplicación, incluidos los resúmenes escritos por la IA.
- **Actividad de la entidad** — la cronología de un contacto, trato o tarea individual.
- **Recuentos de eventos agregados** — una forma heredada en camelCase del Resumen que se mantiene para integraciones existentes.

Cada endpoint en esta página necesita un ámbito exacto, no ambos: pase como máximo uno de `campaign_id` (heredado) o `agent_id` donde el endpoint lo acepte. Enviar ambos devuelve `400`, y un id que no está en su cuenta devuelve `404` en lugar de `403`, por lo que los ids de otras cuentas permanecen imposibles de adivinar.

Todas las rutas a continuación son relativas a la URL base de la API:

```
https://api.youraiconnector.com/v1
```

Cada solicitud debe estar autenticada. Consulte [Autenticación](authentication.md) para conocer los cuatro métodos aceptados. Los ejemplos aquí utilizan el encabezado `X-API-Key` (y una forma de parámetro de consulta para cURL).

---

## Rango de fechas

Los tres endpoints aceptan los mismos filtros de fecha opcionales:

| Parámetro | Descripción |
|---|---|
| `from` | Inicio del rango, `YYYY-MM-DD`, inclusivo. Por defecto, hace 30 días. |
| `to` | Fin del rango, `YYYY-MM-DD`, inclusivo. Por defecto, hoy. |

Las fechas se interpretan en UTC. El rango es, por defecto, los **últimos 30 días** y tiene un límite de **366 días**; un rango más amplio devuelve `400`. `from` no debe ser posterior a `to`.

### El indicador `truncated`

Los endpoints de **Resumen** y **Créditos** limitan la cantidad de registros que escanea una sola solicitud. Si su rango es lo suficientemente activo como para alcanzar ese límite, la respuesta incluye `"truncated": true`. Cuando lo vea, los números se basan en un escaneo parcial; reduzca su rango de fechas (o navegue por páginas con una ventana más pequeña) para obtener cifras completas.

::: note
**Nota:** Las cifras de coste y tokens solo se incluyen para las llamadas a la IA facturadas a través de sus propias claves de API de proveedor. Cuando las cifras de coste están ocultas para su cuenta, la respuesta establece `"costs_redacted": true` y los campos de coste se devuelven como cero.
:::


---

## Resumen del volumen de mensajes

Devuelve contadores de eventos de mensajes agregados para su cuenta, tanto como totales de rango como una serie diaria. Cada día en el rango aparece en `by_date`; los días sin actividad se rellenan con ceros. Opcionalmente, filtre por una sola campaña con `campaign_id`.

`GET /analytics/summary`

| Parámetro | Requerido | Descripción |
|---|---|---|
| `from` | No | Inicio del rango, `YYYY-MM-DD`. |
| `to` | No | Fin del rango, `YYYY-MM-DD`. |
| `campaign_id` | No | Solo contar eventos que pertenezcan a esta campaña. |

**cURL**

```bash
curl "https://api.youraiconnector.com/v1/analytics/summary?from=2026-05-01&to=2026-05-31&apiKey=YOUR_API_KEY"
```

**JavaScript**

```javascript
const params = new URLSearchParams({ from: "2026-05-01", to: "2026-05-31" });
const res = await fetch(`https://api.youraiconnector.com/v1/analytics/summary?${params}`, {
  headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
```

**Python**

```python
import requests

res = requests.get(
    "https://api.youraiconnector.com/v1/analytics/summary",
    headers={"X-API-Key": "YOUR_API_KEY"},
    params={"from": "2026-05-01", "to": "2026-05-31"},
)
data = res.json()
```

**Respuesta**

```json
{
  "success": true,
  "from": "2026-05-01",
  "to": "2026-05-31",
  "totals": {
    "total": 1240,
    "sent": 800,
    "delivered": 760,
    "read": 540,
    "replied": 210,
    "booked": 35,
    "contact_created": 120,
    "credits_spent": 412.5,
    "credits_recharged": 500
  },
  "by_date": [
    {
      "date": "2026-05-01",
      "total": 40,
      "sent": 25,
      "delivered": 24,
      "read": 18,
      "replied": 7,
      "booked": 1,
      "contact_created": 4,
      "credits_spent": 13.5,
      "credits_recharged": 0
    }
  ],
  "truncated": false
}
```

Cada entrada en `by_date` tiene los mismos campos de contador que `totals`, además de un `date`.

Si proporciona un `campaign_id` que no pertenece a su cuenta, la respuesta será `404` con `{ "success": false, "error": "Campaign not found" }`.

---

## Uso de créditos

Devuelve el uso de créditos durante el rango: una lista paginada de registros individuales, además de totales del rango y desgloses por motivo y por campaña.

`GET /analytics/credits`

| Parámetro | Requerido | Descripción |
|---|---|---|
| `from` | No | Inicio del rango, `YYYY-MM-DD`. |
| `to` | No | Fin del rango, `YYYY-MM-DD`. |
| `campaign_id` | No | Solo incluir el uso atribuido a esta campaña. |
| `limit` | No | Tamaño de página para `records`, de 1 a 100. El valor predeterminado es 50. |
| `cursor` | No | Proporcione el `next_cursor` de la página anterior para obtener la página siguiente. |

> **Ajustes frente a consumo:** Los cambios de saldo, como bonificaciones, renovaciones de planes y correcciones, están **excluidos** de `totals` y de los desgloses; no son consumo real. Aún aparecen en la lista `records`, marcados con `"is_adjustment": true`.

**Los totales y desgloses solo aparecen en la primera página** (cuando no se proporciona `cursor`). En las páginas siguientes, `totals`, `by_reason`, `by_reason_cost` y `by_campaign` se devuelven como `null`; solo continúa la matriz `records`. Esto evita volver a analizar todo el rango para cada página.

**cURL**

```bash
curl "https://api.youraiconnector.com/v1/analytics/credits?from=2026-05-01&to=2026-05-31&limit=50&apiKey=YOUR_API_KEY"
```

**JavaScript**

```javascript
const params = new URLSearchParams({
  from: "2026-05-01",
  to: "2026-05-31",
  limit: "50",
});
const res = await fetch(`https://api.youraiconnector.com/v1/analytics/credits?${params}`, {
  headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();

// To page: pass data.next_cursor as ?cursor on the next request, until it is null.
```

**Python**

```python
import requests

res = requests.get(
    "https://api.youraiconnector.com/v1/analytics/credits",
    headers={"X-API-Key": "YOUR_API_KEY"},
    params={"from": "2026-05-01", "to": "2026-05-31", "limit": 50},
)
data = res.json()

# To page: pass data["next_cursor"] as cursor on the next request, until it is None.
```

**Respuesta** (primera página)

```json
{
  "success": true,
  "from": "2026-05-01",
  "to": "2026-05-31",
  "totals": {
    "credits_used": 412.5,
    "cost_usd": 1.284512,
    "records": 318
  },
  "by_reason": {
    "AI Message": 380.0,
    "Campaign Message": 32.5
  },
  "by_reason_cost": {
    "AI Message": 1.284512,
    "Campaign Message": 0
  },
  "by_campaign": {
    "Spring Promo": 250.0,
    "Reactivation": 162.5
  },
  "records": [
    {
      "id": "rec_abc123",
      "amount": 1,
      "timestamp": "2026-05-31T14:02:11.000Z",
      "reason": "AI Message",
      "is_adjustment": false,
      "campaign_id": "campaign123",
      "campaign_name": "Spring Promo",
      "contact_id": "contact456",
      "contact_name": "Jane Smith",
      "credit_type": "ai",
      "custom_keys_used": false,
      "description": null,
      "cost_usd": 0,
      "input_tokens": 0,
      "output_tokens": 0,
      "cache_read_tokens": 0,
      "cache_creation_tokens": 0,
      "ai_model": null,
      "request_id": null,
      "is_test": false
    }
  ],
  "next_cursor": "rec_abc123",
  "costs_redacted": false,
  "truncated": false
}
```

**Notas de campo:**

- `amount` — créditos cargados por el registro. Cero para registros facturados a su propia clave de API de proveedor.
- `is_adjustment` — `true` para cambios de saldo (excluidos de totales/desgloses).
- `cost_usd`, `input_tokens`, `output_tokens`, `cache_read_tokens`, `cache_creation_tokens`, `ai_model`, `request_id` — completados solo en registros facturados a su propia clave de API de proveedor; de lo contrario, cero o `null`.
- `is_test` — `true` para ejecuciones de prueba o en el entorno de pruebas (playground), que nunca se facturan.
- `next_cursor` — el cursor para la página siguiente, o `null` cuando no hay más registros.

---

## Resumen de costes de IA

Devuelve el resumen del gasto diario en IA de su cuenta. Esto lee totales diarios pre-agregados, por lo que es rápido incluso en rangos largos. Cada día en el rango aparece en `days`; los días sin actividad se rellenan con cero.

`GET /analytics/ai-cost`

| Parámetro | Obligatorio | Descripción |
|---|---|---|
| `from` | No | Inicio del rango, `YYYY-MM-DD`. |
| `to` | No | Fin del rango, `YYYY-MM-DD`. |

**cURL**

```bash
curl "https://api.youraiconnector.com/v1/analytics/ai-cost?from=2026-05-01&to=2026-05-31&apiKey=YOUR_API_KEY"
```

**JavaScript**

```javascript
const params = new URLSearchParams({ from: "2026-05-01", to: "2026-05-31" });
const res = await fetch(`https://api.youraiconnector.com/v1/analytics/ai-cost?${params}`, {
  headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
```

**Python**

```python
import requests

res = requests.get(
    "https://api.youraiconnector.com/v1/analytics/ai-cost",
    headers={"X-API-Key": "YOUR_API_KEY"},
    params={"from": "2026-05-01", "to": "2026-05-31"},
)
data = res.json()
```

**Respuesta**

```json
{
  "success": true,
  "from": "2026-05-01",
  "to": "2026-05-31",
  "totals": {
    "total_usd": 12.4821,
    "byok_usd": 12.4821,
    "platform_usd": 0,
    "calls": 4210
  },
  "days": [
    {
      "date": "2026-05-01",
      "total_usd": 0.4012,
      "byok_usd": 0.4012,
      "platform_usd": 0,
      "input_usd": 0.18,
      "output_usd": 0.19,
      "cache_creation_usd": 0.02,
      "cache_read_usd": 0.0112,
      "calls": 140,
      "by_provider": { "anthropic": 0.4012 }
    }
  ],
  "costs_redacted": false
}
```

**Notas de campo:**

- `byok_usd` — gasto facturado a las claves de API de su propio proveedor.
- `platform_usd` — la parte del gasto que se ejecutó en la plataforma en lugar de con su propia clave.
- `input_usd`, `output_usd`, `cache_creation_usd`, `cache_read_usd` — los componentes de coste que conforman `total_usd`.
- `by_provider` — gasto en USD clasificado por nombre de proveedor de IA.
- Las cifras en USD solo se devuelven a las cuentas que utilizan su propia clave de proveedor. Para las cuentas que pagan con crédito, todos los campos de USD son cero y `costs_redacted` es `true` (los recuentos de llamadas permanecen visibles).

---

## Series de métricas

Devuelve una o más series temporales de métricas en una sola llamada, opcionalmente agrupadas por hasta dos dimensiones: el endpoint para vincular un gráfico. Una sola solicitud puede responder "enviados y respondidos por día, por canal, para esta campaña" sin necesidad de una llamada por campaña.

`GET /analytics/series`

Cada respuesta lleva una matriz `labels` (el eje temporal, relleno con ceros en todo el rango) y una entrada en `series` por grupo, cada una con una matriz por métrica solicitada alineada con `labels`. Las series posteriores a `limit` no se descartan: se colapsan en `other_bucket`, calculado como el total del rango menos las series devueltas, por lo que un gráfico renderizado siempre suma sus números reales; `truncated` es `true` siempre que eso sucede.

De dónde provienen los números: `sent`, `delivered`, `read` y `replied` provienen de los registros de mensajes, que llevan el canal y el número de envío. `booked`, `contact_created` y `credits_spent` provienen del flujo de eventos, que no lleva número de envío, por lo que esas métricas aterrizan en el depósito de número `null` cuando agrupa por `number`.

| Parámetro | Requerido | Descripción |
|---|---|---|
| `from` | No | Inicio del rango, `YYYY-MM-DD`. El valor predeterminado es hace 30 días. |
| `to` | No | Fin del rango, `YYYY-MM-DD`. El valor predeterminado es hoy. |
| `metrics` | No | Lista separada por comas de `sent`, `ai_sent`, `human_sent`, `delivered`, `read`, `replied`, `booked`, `contact_created`, `credits_spent`. El valor predeterminado es `sent,replied`. Una métrica desconocida devuelve `400`. |
| `group_by` | No | Lista separada por comas de hasta dos dimensiones de `date`, `campaign`, `channel`, `agent`, `number`. `date` se acepta pero no tiene efecto: cada respuesta ya lleva el eje temporal. Omítalo para una sola serie de toda la cuenta. |
| `granularity` | No | `day` (predeterminado), `week` o `month`. Los depósitos semanales comienzan el lunes, los mensuales el día 1. |
| `limit` | No | Cuántas series devolver antes de que el resto se colapse en `other_bucket`, 1–50. El valor predeterminado es 12. |
| `campaign_id` | No | Solo contar la actividad que pertenece a esta campaña. Heredado; prefiera `agent_id`. |
| `agent_id` | No | Solo contar la actividad que pertenece a este Agente de IA. |
| `channel` | No | Solo contar la actividad en este canal, por ejemplo `whatsapp`. |

El rango de fechas de este endpoint está limitado a **92 días** (más estricto que el límite de 366 días utilizado en otras partes de esta página).

**cURL**

```bash
curl "https://api.youraiconnector.com/v1/analytics/series?from=2026-05-01&to=2026-05-31&metrics=sent,replied,booked&group_by=campaign,channel&limit=10&apiKey=YOUR_API_KEY"
```

**JavaScript**

```javascript
const params = new URLSearchParams({
  from: "2026-05-01",
  to: "2026-05-31",
  metrics: "sent,replied,booked",
  group_by: "campaign,channel",
  limit: "10",
});
const res = await fetch(`https://api.youraiconnector.com/v1/analytics/series?${params}`, {
  headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
```

**Python**

```python
import requests

res = requests.get(
    "https://api.youraiconnector.com/v1/analytics/series",
    headers={"X-API-Key": "YOUR_API_KEY"},
    params={
        "from": "2026-05-01",
        "to": "2026-05-31",
        "metrics": "sent,replied,booked",
        "group_by": "campaign,channel",
        "limit": 10,
    },
)
data = res.json()
```

**Respuesta**

```json
{
  "success": true,
  "from": "2026-05-01",
  "to": "2026-05-31",
  "granularity": "day",
  "labels": ["2026-05-01", "2026-05-02"],
  "group_by": ["campaign", "channel"],
  "metrics": ["sent", "replied", "booked"],
  "series": [
    {
      "key": {
        "campaign_id": "campaign123",
        "campaign_name": "Spring Promo",
        "channel": "whatsapp"
      },
      "total": 812,
      "metrics": {
        "sent": [40, 35],
        "replied": [12, 9],
        "booked": [2, 1]
      }
    }
  ],
  "other_bucket": {
    "series_count": 6,
    "total": 340,
    "metrics": {
      "sent": [18, 20],
      "replied": [5, 6],
      "booked": [0, 1]
    }
  },
  "truncated": true
}
```

**Notas de campo:**

- `key` — la identidad de una serie. Solo están presentes las claves de las dimensiones `group_by` solicitadas; una dimensión cuyo valor es desconocido para una fila (un mensaje sin campaña, un evento sin canal) vuelve como `null` en lugar de ser descartada, por lo que las series aún suman los totales.
- `other_bucket` — `null` cuando no se colapsó nada.
- Este endpoint devuelve `503` con `"error_code": "analytics_unavailable"` cuando la base de datos de informes no puede responder por su cuenta, en lugar de un `200` lleno de ceros: un gráfico con ceros se leería como un hecho.

---

## Resultados de las conversaciones

Devuelve cómo terminaron las conversaciones durante un rango de fechas: un recuento diario para cada etiqueta de resultado que la IA asignó, más los totales del rango para respuestas, reservas, transferencias a un humano y conversaciones que la IA nunca clasificó.

`GET /analytics/outcomes`

Pase `group_by=tag` para colapsar el eje temporal y obtener solo los totales del rango por etiqueta; en ese modo, `labels` está vacío y la matriz `counts` de cada etiqueta está vacía, mientras que `total` sigue estando poblado.

| Parámetro | Obligatorio | Descripción |
|---|---|---|
| `from` | No | Inicio del rango, `YYYY-MM-DD`. El valor predeterminado es hace 30 días. |
| `to` | No | Fin del rango, `YYYY-MM-DD`. El valor predeterminado es hoy. |
| `campaign_id` | No | Solo cuenta las conversaciones con contactos actualmente en esta campaña. Legado; se prefiere `agent_id`. |
| `agent_id` | No | Solo cuenta los resultados que pertenecen a este Agente de IA. |
| `group_by` | No | `date` (predeterminado) mantiene los conteos por día; `tag` colapsa los totales del rango. |

El rango de fechas de este endpoint está limitado a **92 días**.

**cURL**

```bash
curl "https://api.youraiconnector.com/v1/analytics/outcomes?from=2026-05-01&to=2026-05-31&apiKey=YOUR_API_KEY"
```

**JavaScript**

```javascript
const params = new URLSearchParams({ from: "2026-05-01", to: "2026-05-31" });
const res = await fetch(`https://api.youraiconnector.com/v1/analytics/outcomes?${params}`, {
  headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
```

**Python**

```python
import requests

res = requests.get(
    "https://api.youraiconnector.com/v1/analytics/outcomes",
    headers={"X-API-Key": "YOUR_API_KEY"},
    params={"from": "2026-05-01", "to": "2026-05-31"},
)
data = res.json()
```

**Respuesta**

```json
{
  "success": true,
  "from": "2026-05-01",
  "to": "2026-05-31",
  "group_by": "date",
  "labels": ["2026-05-01", "2026-05-02"],
  "by_tag": [
    { "tag": "interested", "total": 84, "counts": [3, 5] },
    { "tag": "not_interested", "total": 40, "counts": [1, 2] },
    { "tag": null, "total": 12, "counts": [0, 1] }
  ],
  "totals": {
    "sessions": 260,
    "replied": 210,
    "booked": 35,
    "human_alerted": 18,
    "unresolved": 12
  }
}
```

**Notas de campo:**

- `by_tag[].tag` — `null` para conversaciones a las que la IA nunca asignó una etiqueta de resultado.
- `totals.human_alerted` — conversaciones transferidas a un humano; esto se registra en cada transferencia y no se mostraba anteriormente en ningún endpoint.
- Misma postura `503`/`analytics_unavailable` que la serie de métricas cuando la base de datos de informes no puede responder.

---

## Información del panel

Devuelve la carga útil completa del panel para un rango de fechas en una sola llamada: un mapa de calor de tasa de respuesta por día de la semana y hora, la tabla de clasificación de campañas, el volumen por canal, los totales exactos por conexión, los desgloses de métricas por día (a nivel de cuenta, por canal y por número), el origen de los contactos, el tiempo de respuesta de la bandeja de entrada y un feed de actividad reciente. Esta es la carga útil de informes más completa de la API: impulsa directamente el panel de control de la aplicación.

`GET /analytics/dashboard-insights`

| Parámetro | Obligatorio | Descripción |
|---|---|---|
| `startDate` | Sí | Inicio del rango, `YYYY-MM-DD`. |
| `endDate` | Sí | Fin del rango, `YYYY-MM-DD`. |
| `campaignId` | No | Solo incluir la actividad que pertenece a esta campaña (también se acepta `campaign_id`). Legado; se prefiere `agent_id`. |
| `agent_id` | No | Solo incluir la actividad que pertenece a este Agente de IA (también se acepta `agentId`). Bajo el alcance de un agente, la tabla de clasificación de campañas se construye solo a partir de la actividad de ese agente. |

Este endpoint utiliza `startDate`/`endDate` (no `from`/`to`) porque comparte su implementación con el panel de control de la aplicación. El rango está limitado a 92 días y se **ajusta, no se rechaza**, cuando es más amplio.

> **Nulo significa no disponible, no cero.** Varios bloques (`numberStats`, `channelDailySeries`, `metricDailyBreakdown`, `contactsByCountry`) se calculan a partir de la base de datos de informes y devuelven `null` cuando no puede responder para su cuenta. No renderice un bloque `null` como un gráfico vacío.

**cURL**

```bash
curl "https://api.youraiconnector.com/v1/analytics/dashboard-insights?startDate=2026-05-01&endDate=2026-05-31&apiKey=YOUR_API_KEY"
```

**JavaScript**

```javascript
const params = new URLSearchParams({ startDate: "2026-05-01", endDate: "2026-05-31" });
const res = await fetch(`https://api.youraiconnector.com/v1/analytics/dashboard-insights?${params}`, {
  headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
```

**Python**

```python
import requests

res = requests.get(
    "https://api.youraiconnector.com/v1/analytics/dashboard-insights",
    headers={"X-API-Key": "YOUR_API_KEY"},
    params={"startDate": "2026-05-01", "endDate": "2026-05-31"},
)
data = res.json()
```

**Respuesta** (abreviada: esta carga útil es grande; consulte la [Referencia de la API](reference.md) para ver el esquema completo)

```json
{
  "success": true,
  "data": {
    "heatmap": {
      "buckets": [
        { "weekday": 1, "hour": 9, "sent": 12, "replied": 5, "replyRate": 0.42 }
      ]
    },
    "topCampaigns": [
      { "campaignId": "campaign123", "name": "Spring Promo", "sent": 420, "replied": 180, "booked": 22, "replyRate": 0.43, "creditsSpent": 210.5 }
    ],
    "channelVolume": [
      { "channel": "whatsapp", "sent": 800, "received": 540, "lastMessageAt": "2026-05-31T14:02:11.000Z" }
    ],
    "inboxSla": { "medianFirstResponseMs": 92000, "sampleSize": 140 },
    "activityFeed": [
      { "id": "evt_1", "kind": "booked", "at": "2026-05-31T14:02:11.000Z", "contactId": "contact456", "contactName": "Jane Smith", "campaignId": "campaign123", "campaignName": "Spring Promo", "label": "Jane Smith booked an appointment" }
    ],
    "numberStats": null,
    "channelDailySeries": null,
    "metricDailyBreakdown": null,
    "contactsByCountry": null,
    "ai_human_split": null
  }
}
```

**Notas de campo:**

- `heatmap.buckets[].weekday` — `0` es domingo hasta `6` es sábado.
- `numberStats`, `channelDailySeries`, `metricDailyBreakdown`, `contactsByCountry`, `ai_human_split` — cada uno devuelve `null` de forma independiente cuando la base de datos de informes no está disponible para su cuenta; todos los demás bloques siguen respondiendo.

---

## Información de IA del panel

Devuelve tres breves perspectivas redactadas por IA sobre la mensajería de la cuenta durante un rango de fechas: un logro, algo a tener en cuenta y un consejo; frases que puede pegar directamente en un informe en lugar de números que aún debe interpretar. Generado únicamente a partir de las métricas de mensajes de la propia cuenta.

`GET /analytics/dashboard-ai-insights`

| Parámetro | Obligatorio | Descripción |
|---|---|---|
| `startDate` | Sí | Inicio del rango, `YYYY-MM-DD`. |
| `endDate` | Sí | Fin del rango, `YYYY-MM-DD`. |

Este endpoint es a nivel de cuenta; no requiere un ámbito de campaña o agente.

**cURL**

```bash
curl "https://api.youraiconnector.com/v1/analytics/dashboard-ai-insights?startDate=2026-05-01&endDate=2026-05-31&apiKey=YOUR_API_KEY"
```

**JavaScript**

```javascript
const params = new URLSearchParams({ startDate: "2026-05-01", endDate: "2026-05-31" });
const res = await fetch(`https://api.youraiconnector.com/v1/analytics/dashboard-ai-insights?${params}`, {
  headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
```

**Python**

```python
import requests

res = requests.get(
    "https://api.youraiconnector.com/v1/analytics/dashboard-ai-insights",
    headers={"X-API-Key": "YOUR_API_KEY"},
    params={"startDate": "2026-05-01", "endDate": "2026-05-31"},
)
data = res.json()
```

**Respuesta**

```json
{
  "success": true,
  "data": {
    "insights": [
      { "tone": "win", "title": "Reply rate is up", "detail": "Your reply rate climbed to 43% this period, up from 36% the period before." },
      { "tone": "watch", "title": "Bookings slowed midweek", "detail": "Wednesday bookings dropped to a third of Monday's, worth a look at your Wednesday follow-up timing." },
      { "tone": "tip", "title": "Re-send to non-repliers", "detail": "212 contacts received a message but never replied — a short follow-up template often recovers 10-15% of them." }
    ]
  }
}
```

Si falta `startDate` o `endDate`, se devuelve `400`.

---

## Cronología de actividad de la entidad

Devuelve la actividad de un único contacto, trato o tarea como una sola cronología, de la más reciente a la más antigua: qué sucedió y cuándo, a través de mensajes, citas, notas y cambios de estado. Úselo para responder a "qué ha pasado con esta persona" sin tener que combinar varios endpoints de lista.

`GET /analytics/entity-activity`

| Parámetro | Requerido | Descripción |
|---|---|---|
| `entityType` | Sí | `contact`, `deal` o `task`. |
| `entityId` | Sí | ID del registro cuya cronología se desea obtener. |

**cURL**

```bash
curl "https://api.youraiconnector.com/v1/analytics/entity-activity?entityType=contact&entityId=contact456&apiKey=YOUR_API_KEY"
```

**JavaScript**

```javascript
const params = new URLSearchParams({ entityType: "contact", entityId: "contact456" });
const res = await fetch(`https://api.youraiconnector.com/v1/analytics/entity-activity?${params}`, {
  headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
```

**Python**

```python
import requests

res = requests.get(
    "https://api.youraiconnector.com/v1/analytics/entity-activity",
    headers={"X-API-Key": "YOUR_API_KEY"},
    params={"entityType": "contact", "entityId": "contact456"},
)
data = res.json()
```

**Respuesta**

```json
{
  "success": true,
  "data": {
    "items": [
      {
        "id": "evt_9",
        "kind": "appointment_booked",
        "at": "2026-05-31T14:02:11.000Z",
        "label": "Booked an appointment for June 3",
        "detail": "Consultation call, 30 minutes"
      },
      {
        "id": "evt_8",
        "kind": "message_replied",
        "at": "2026-05-31T13:58:02.000Z",
        "label": "Replied: \"Yes, that time works\""
      }
    ]
  }
}
```

Si falta `entityType`/`entityId` o es inválido, se devuelve `400`. Una entidad que no existe en su cuenta devuelve `404`, por lo que los ID de otras cuentas no se pueden adivinar.

---

## Recuentos de eventos agregados (heredado)

Devuelve los mismos recuentos de eventos agregados que el [Resumen de volumen de mensajes](#message-volume-summary), pero en el formato camelCase (`contactCreated` en lugar de `contact_created`, `byDate` en lugar de `by_date`) con el que se crearon algunas integraciones antiguas. Prefiera `/analytics/summary` para nuevas integraciones; este endpoint existe solo para que el panel de control de la aplicación y la API compartan una misma implementación.

`GET /analytics/aggregate`

| Parámetro | Requerido | Descripción |
|---|---|---|
| `startDate` | No | Inicio del rango, fecha o fecha-hora ISO. Por defecto, usa la misma ventana que `/analytics/summary`. |
| `endDate` | No | Fin del rango, fecha o fecha-hora ISO. |
| `campaignId` | No | Solo contar eventos que pertenecen a esta campaña (también se acepta `campaign_id`). Heredado; prefiera `agent_id`. |
| `agent_id` | No | Solo contar eventos que pertenecen a este Agente de IA (también se acepta `agentId`). |

**cURL**

```bash
curl "https://api.youraiconnector.com/v1/analytics/aggregate?startDate=2026-05-01&endDate=2026-05-31&apiKey=YOUR_API_KEY"
```

**Respuesta**

```json
{
  "success": true,
  "data": {
    "from": "2026-05-01",
    "to": "2026-05-31",
    "total": 1240,
    "byAnalyticType": {
      "total": 1240,
      "sent": 800,
      "delivered": 760,
      "read": 540,
      "replied": 210,
      "booked": 35,
      "contactCreated": 120,
      "creditsSpent": 412.5,
      "creditsRecharged": 500
    },
    "byDate": [
      { "date": "2026-05-01", "byAnalyticType": { "total": 40, "sent": 25, "delivered": 24, "read": 18, "replied": 7, "booked": 1, "contactCreated": 4, "creditsSpent": 13.5, "creditsRecharged": 0 } }
    ]
  }
}
```

---

## Resumen de subcuentas de agencia


---

## Errores de la API de Analytics

Los endpoints de Analytics devuelven el sobre de error estándar:

```json
{
  "success": false,
  "error": "Date range too large. Maximum is 366 days."
}
```

En un endpoint de análisis, un formato de fecha no válido o una ventana fuera de rango devuelve `400`, y un `campaign_id` o `agent_id` desconocido devuelve `404`. Enviar tanto `campaign_id` como `agent_id` en un endpoint que acepta cualquiera de los dos también es un `400`; pase como máximo uno. Los endpoints de informes exclusivos de PG (Series de métricas, Resultados de conversaciones, Resumen de agencia) devuelven `503` con `"error_code": "analytics_unavailable"` en lugar de un `200` lleno de ceros cuando la base de datos de informes no puede responder para su cuenta; vuelva a intentarlo en breve. Los códigos compartidos que puede devolver cualquier endpoint — `401`, `403` (su plan no incluye acceso a la API o, en el resumen de agencia, su cuenta no es de tipo Agencia/Desarrollador), `429` (límite de tasa) y `500` — se enumeran con orientación sobre reintentos en [Errores y paginación](errors-and-pagination.md).

---

## Próximos pasos

- [Autenticación](authentication.md) — las cuatro formas de autenticar una solicitud.
- [Errores y límites de tasa](errors-and-pagination.md) — códigos de estado y el límite de 300 solicitudes/min.
- [API de campañas](campaigns.md) — las campañas por las que se pueden filtrar estas cifras.
