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

# Analytics API

> Получайте аналитику ваших диалогов: агрегированные метрики по агентам и каналам, а также подробные данные по каждому диалогу

Analytics API — это эндпоинт только для чтения, возвращающий данные о диалогах вашей компании. Он работает в двух режимах:

* **`type=metrics`**: агрегированные показатели по агентам и каналам (диалоги, переводы на оператора, доля диалогов, закрытых ИИ, длительность звонков, уведомления WhatsApp, повторные обращения, а также посуточные и почасовые ряды). Используйте для отчётов и дашбордов.
* **`type=chats`**: одна строка на диалог со всеми его параметрами, с постраничной выдачей. Используйте для экспорта или сверки исходных данных.

## 🔑 Аутентификация

Каждый запрос требует API-ключ с разрешением **`analytics_api`**. Запросите его у команды Lovi; он отличается от ключа, который используется веб-виджетом.

Передавайте ключ в заголовке `x-api-key` (рекомендуется) или в параметре запроса `access_key`.

```bash theme={null}
curl -H "x-api-key: YOUR_API_KEY" \
  "https://cloud.lovi.ai/functions/v1/analytics?type=metrics&date_from=2026-10-01&date_to=2026-10-31"
```

> [!NOTE]
>
> Компания всегда определяется по ключу. Ключ может читать только данные своей компании, и параметра для выбора другой компании нет.

## Эндпоинт

```
GET https://cloud.lovi.ai/functions/v1/analytics
```

### Параметры запроса

| Параметр | Обязательный | Описание |
| - | - | - |
| `type` | Да | `metrics` или `chats`. |
| `date_from` | Да | Первый день, `YYYY-MM-DD`, включительно. |
| `date_to` | Да | Последний день, `YYYY-MM-DD`, включительно. Диапазон может охватывать до **31 дня**. |
| `tz` | Нет | Часовой пояс IANA, в котором интерпретируются дни и строятся посуточные и почасовые ряды. По умолчанию `Europe/Madrid`. Примеры: `UTC`, `America/Bogota`. |
| `channels` | Нет | Каналы через запятую: `voice`, `whatsapp`, `web`, `instagram`, `facebook`… |
| `agents` | Нет | Идентификаторы агентов (UUID) через запятую. |
| `languages` | Нет | Коды языков пользователя через запятую, например `es,pt`. |
| `limit` | Нет | Только для `chats`. Количество диалогов на странице, 1–100. По умолчанию 100. |
| `cursor` | Нет | Только для `chats`. Значение `next_cursor`, полученное на предыдущей странице. |

Дни интерпретируются в `tz`: `date_from=2026-10-01&date_to=2026-10-31` с `tz=Europe/Madrid` охватывает период с 00:00 1 октября до 00:00 1 ноября по мадридскому времени. Переходы на летнее и зимнее время учитываются автоматически.

Все временные метки в ответах указаны в **UTC** (ISO 8601 с окончанием `Z`).

## Метрики (`type=metrics`)

Возвращает одну запись на каждого агента и канал, отсортированную по количеству диалогов.

```bash theme={null}
curl -H "x-api-key: YOUR_API_KEY" \
  "https://cloud.lovi.ai/functions/v1/analytics?type=metrics&date_from=2026-10-01&date_to=2026-10-31&channels=voice"
```

```json theme={null}
{
  "tz": "Europe/Madrid",
  "from": "2026-09-30T22:00:00.000Z",
  "to": "2026-10-31T23:00:00.000Z",
  "data": [
    {
      "agent": { "id": "2fef9696-0662-4e49-bb83-7564ff25c7ef", "name": "Voice assistant" },
      "channel": "voice",
      "conversations": 12480,
      "escalated": 4120,
      "contained_pct": 67.0,
      "avg_duration_s": { "all": 109, "without_transfer": 120, "with_transfer": 86 },
      "whatsapp_notifications": 1210,
      "unique_users": 7950,
      "recontacts": 2480,
      "daily": [
        { "date": "2026-10-01", "conversations": 410, "escalated": 151 }
      ],
      "hourly": [
        { "hour": 9, "conversations": 1320 },
        { "hour": 10, "conversations": 1544 }
      ]
    }
  ]
}
```

| Поле | Описание |
| - | - |
| `agent` | ИИ-агент, обработавший диалоги (`id`, `name`). `null`, если у диалога нет агента. |
| `channel` | Канал диалога. `n/a`, если он не был записан. |
| `conversations` | Диалоги, начатые в течение диапазона (для голоса — звонки). |
| `escalated` | Диалоги, переведённые на оператора (у них есть событие `chat_escalated`). |
| `contained_pct` | `(conversations − escalated) / conversations × 100`. Доля диалогов, обработанных ИИ без перевода. **Это не показатель решённых обращений.** |
| `avg_duration_s` | Средняя длительность звонка в секундах: общая, без перевода и с переводом. `null` для каналов без длительности (её записывает только голос). |
| `whatsapp_notifications` | Уведомления WhatsApp, отправленные из этих диалогов (события `notification_sent`). |
| `unique_users` | Уникальные пользователи (для голоса — уникальные номера телефонов). |
| `recontacts` | Пользователи с 2 и более диалогами в течение диапазона. Доля повторных обращений = `recontacts / unique_users`. |
| `daily` | Диалоги и переводы по дням, в `tz`. Дни без диалогов не включаются. |
| `hourly` | Диалоги по часам суток (0–23), в `tz`. Часы без диалогов не включаются. |

> [!TIP]
>
> **Сравнение с предыдущим месяцем**: вызовите эндпоинт дважды, по одному разу на каждый месяц, и вычислите разницу.
> **Доля диалогов, закрытых ИИ, только в дни с операторами**: используйте `daily` и оставьте дни с `escalated > 0`.

## Диалоги (`type=chats`)

Возвращает диалоги диапазона по одному, начиная с самых старых; по умолчанию 100 на страницу.

```bash theme={null}
curl -H "x-api-key: YOUR_API_KEY" \
  "https://cloud.lovi.ai/functions/v1/analytics?type=chats&date_from=2026-10-01&date_to=2026-10-01&channels=voice&limit=100"
```

```json theme={null}
{
  "data": [
    {
      "id": "29d67962-119b-406c-b172-d66cf179975e",
      "created_at": "2026-10-01T05:58:40.4431Z",
      "ended_at": "2026-10-01T05:58:48Z",
      "last_message_at": null,
      "status": "aiagent",
      "channel": "voice",
      "language": "es",
      "agent": { "id": "2fef9696-0662-4e49-bb83-7564ff25c7ef", "name": "Voice assistant" },
      "escalated_to_human": true,
      "escalated_at": "2026-10-01T05:58:45.12Z",
      "attended_by_human": false,
      "human_agents": [],
      "whatsapp_notifications": 0,
      "parameters": {
        "channel": "voice",
        "call_length": 8,
        "phone_call": "+34600000000",
        "voice_inbound": true,
        "conversation_recording_url": "https://…"
      }
    }
  ],
  "next_cursor": "MjAyNi0xMC0wMVQwNjowMjoxMS4xMjM0NTZ8…"
}
```

| Поле | Описание |
| - | - |
| `id` | Идентификатор диалога. |
| `created_at`, `ended_at`, `last_message_at` | Начало, окончание и последнее сообщение, в UTC. |
| `status` | С кем ведётся диалог: `aiagent`, `human`, `queue` (ожидает оператора) или `push` (начат по уведомлению). |
| `channel`, `language` | Скопированы из `parameters.channel` и `parameters.lang_user` для удобства. |
| `agent` | ИИ-агент диалога (`id`, `name`). |
| `escalated_to_human`, `escalated_at` | Был ли диалог переведён на оператора и когда (первый перевод). |
| `attended_by_human` | Написал ли оператор-человек хотя бы одно сообщение. |
| `human_agents` | Операторы-люди, писавшие в диалоге (`id`, `name`). Может быть пустым, даже если `attended_by_human` равно `true`: сообщения, отправленные из внешней CRM, не привязываются к конкретному человеку. |
| `whatsapp_notifications` | Уведомления WhatsApp, отправленные из диалога. |
| `parameters` | **Все** параметры, сохранённые для диалога, без фильтрации. Ключи зависят от канала и от конфигурации вашего агента (для голоса: `call_length`, `phone_call`, `voice_inbound`, `session_call_id`, `conversation_recording_url`…; а также любые пользовательские параметры, которые сохраняет ваш агент). |

### Постраничная выдача

Пока `next_cursor` не равен `null`, запрашивайте следующую страницу с теми же параметрами плюс `cursor=<next_cursor>`. Диалоги упорядочены по `created_at` и `id`, поэтому между страницами ни один диалог не повторяется и не пропускается.

```python theme={null}
import requests

URL = "https://cloud.lovi.ai/functions/v1/analytics"
HEADERS = {"x-api-key": "YOUR_API_KEY"}
params = {"type": "chats", "date_from": "2026-10-01", "date_to": "2026-10-31", "channels": "voice"}

chats = []
while True:
    page = requests.get(URL, headers=HEADERS, params=params, timeout=60).json()
    chats.extend(page["data"])
    if not page["next_cursor"]:
        break
    params["cursor"] = page["next_cursor"]

print(len(chats), "conversations")
```

## Ошибки

Ошибки возвращают тело JSON `{ "success": false, "message": "…" }`.

| Код | Когда |
| - | - |
| `400` | Отсутствует ключ (`Missing access_key parameter`), недопустимый `type`, недопустимые даты, диапазон более 31 дня, недопустимые `tz`, `limit`, `agents`, `channels` или `cursor`. |
| `403` | Ключ существует, но не имеет разрешения `analytics_api`. |
| `404` | Недействительный или отозванный ключ. |
| `405` | Метод, отличный от `GET`. |
| `500` | Внутренняя ошибка. Повторите запрос через несколько секунд; если ошибка сохраняется, обратитесь в поддержку, указав время запроса. |

## Ограничения и рекомендации

* До **31 дня** за запрос и **100 диалогов** на страницу.
* Запрос `metrics` за целый месяц занимает несколько секунд. Для месячного или суточного отчёта достаточно одного вызова на период: опрашивать эндпоинт постоянно не нужно.
* Чтобы экспортировать диалоги за целый месяц, обходите страницы последовательно, а не параллельно.
* Храните ключ в секрете и используйте его только на стороне сервера. Не используйте его в браузере или мобильном приложении.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.