
# API de Analytics e Relatórios

Esses endpoints somente leitura permitem que você extraia a atividade da sua conta para seus próprios painéis e relatórios: contagens de eventos de mensagens, consumo de créditos, gastos com IA e os mesmos gráficos e insights que o painel no aplicativo exibe. Este guia cobre:

- **Resumo** — contadores de volume de mensagens (enviadas, entregues, lidas, respondidas, agendadas, contatos criados, créditos).
- **Créditos** — um registro detalhado e paginado do uso de créditos com totais e detalhamentos.
- **Custo de IA** — um consolidado diário dos gastos com IA.
- **Série de métricas** — uma série temporal pronta para gráficos para uma ou mais métricas, agrupadas por campanha, canal, Agente de IA ou número.
- **Resultados de conversas** — como as conversas terminaram, por tag de resultado atribuída pela IA.
- **Insights do painel** e **Insights de IA do painel** — todos os dados por trás do painel no aplicativo, incluindo resumos escritos por IA.
- **Atividade da entidade** — a linha do tempo de um único contato, negócio ou tarefa.
- **Contagens de eventos agregados** — uma forma legada em camelCase do Resumo mantida para integrações existentes.

Cada endpoint nesta página precisa de um escopo exato, não ambos: passe no máximo um entre `campaign_id` (legado) ou `agent_id` onde o endpoint aceitar. Enviar ambos retorna `400`, e um id que não está na sua conta retorna `404` em vez de `403`, para que os ids de outras contas permaneçam impossíveis de adivinhar.

Todos os caminhos abaixo são relativos à URL base da API:

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

Cada solicitação deve ser autenticada. Consulte [Autenticação](authentication.md) para os quatro métodos aceitos. Os exemplos aqui usam o cabeçalho `X-API-Key` (e uma forma de parâmetro de consulta para cURL).

---

## Intervalo de datas

Todos os três endpoints aceitam os mesmos filtros de data opcionais:

| Parâmetro | Descrição |
|---|---|
| `from` | Início do intervalo, `YYYY-MM-DD`, inclusivo. O padrão é 30 dias atrás. |
| `to` | Fim do intervalo, `YYYY-MM-DD`, inclusivo. O padrão é hoje. |

As datas são interpretadas em UTC. O intervalo tem como padrão os **últimos 30 dias** e é limitado a **366 dias** — um intervalo maior retorna `400`. `from` não deve ser posterior a `to`.

### A flag `truncated`

Os endpoints de **Resumo** e **Créditos** limitam quantos registros uma única solicitação analisa. Se o seu intervalo for movimentado o suficiente para atingir esse limite, a resposta incluirá `"truncated": true`. Quando você o vir, os números serão baseados em uma análise parcial — reduza seu intervalo de datas (ou pagine com uma janela menor) para obter números completos.

::: note
**Nota:** Os valores de custo e tokens são incluídos apenas para chamadas de IA cobradas em suas próprias chaves de API de provedor. Quando os valores de custo estão ocultos para sua conta, a resposta define `"costs_redacted": true` e os campos de custo são retornados como zero.
:::


---

## Resumo do volume de mensagens

Retorna contadores de eventos de mensagens agregados para sua conta, tanto como totais de intervalo quanto como uma série diária. Cada dia no intervalo aparece em `by_date` — dias sem atividade são preenchidos com zero. Opcionalmente, filtre para uma única campanha com `campaign_id`.

`GET /analytics/summary`

| Parâmetro | Obrigatório | Descrição |
|---|---|---|
| `from` | Não | Início do intervalo, `YYYY-MM-DD`. |
| `to` | Não | Fim do intervalo, `YYYY-MM-DD`. |
| `campaign_id` | Não | Contar apenas eventos pertencentes a esta campanha. |

**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()
```

**Resposta**

```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 em `by_date` possui os mesmos campos de contador que `totals`, além de um `date`.

Se você passar um `campaign_id` que não pertence à sua conta, a resposta será `404` com `{ "success": false, "error": "Campaign not found" }`.

---

## Uso de créditos

Retorna o uso de créditos ao longo do intervalo: uma lista paginada de registros individuais, além de totais do intervalo e detalhamentos por motivo e por campanha.

`GET /analytics/credits`

| Parâmetro | Obrigatório | Descrição |
|---|---|---|
| `from` | Não | Início do intervalo, `YYYY-MM-DD`. |
| `to` | Não | Fim do intervalo, `YYYY-MM-DD`. |
| `campaign_id` | Não | Incluir apenas o uso atribuído a esta campanha. |
| `limit` | Não | Tamanho da página para `records`, 1–100. O padrão é 50. |
| `cursor` | Não | Passe o `next_cursor` da página anterior para buscar a próxima página. |

> **Ajustes vs. consumo:** Alterações de saldo, como bônus, renovações de plano e correções, são **excluídas** de `totals` e dos detalhamentos — elas não são consumo real. Elas ainda aparecem na lista `records`, marcadas com `"is_adjustment": true`.

**Totais e detalhamentos aparecem apenas na primeira página** (quando nenhum `cursor` é fornecido). Nas páginas seguintes, `totals`, `by_reason`, `by_reason_cost` e `by_campaign` são retornados como `null` — apenas a matriz `records` continua. Isso evita reexaminar todo o intervalo 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.
```

**Resposta** (primeira 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 cobrados pelo registro. Zero para registros faturados na sua própria chave de API de provedor.
- `is_adjustment` — `true` para alterações de saldo (excluídas dos totais/detalhamentos).
- `cost_usd`, `input_tokens`, `output_tokens`, `cache_read_tokens`, `cache_creation_tokens`, `ai_model`, `request_id` — preenchidos apenas em registros faturados na sua própria chave de API de provedor; zero ou `null` caso contrário.
- `is_test` — `true` para execuções de playground/teste, que nunca são cobradas.
- `next_cursor` — o cursor para a próxima página, ou `null` quando não houver mais registros.

---

## Resumo de custos de IA

Retorna o resumo de gastos diários com IA para sua conta. Isso lê totais diários pré-agregados, portanto é rápido mesmo em longos intervalos. Cada dia no intervalo aparece em `days` — dias sem atividade são preenchidos com zero.

`GET /analytics/ai-cost`

| Parâmetro | Obrigatório | Descrição |
|---|---|---|
| `from` | Não | Início do intervalo, `YYYY-MM-DD`. |
| `to` | Não | Fim do intervalo, `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()
```

**Resposta**

```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` — gastos cobrados nas suas próprias chaves de API de provedor.
- `platform_usd` — a parcela dos gastos que foi executada na plataforma em vez de na sua própria chave.
- `input_usd`, `output_usd`, `cache_creation_usd`, `cache_read_usd` — os componentes de custo que compõem `total_usd`.
- `by_provider` — gastos em USD classificados pelo nome do provedor de IA.
- Os valores em USD são retornados apenas para contas que usam sua própria chave de provedor. Para contas que pagam com créditos, todos os campos de USD são zero e `costs_redacted` é `true` (as contagens de chamadas permanecem visíveis).

---

## Série de métricas

Retorna uma ou mais séries temporais de métricas em uma única chamada, opcionalmente agrupadas por até duas dimensões — o endpoint para vincular a um gráfico. Uma única solicitação pode responder "enviadas e respondidas por dia, por canal, para esta campanha" sem precisar de uma chamada por campanha.

`GET /analytics/series`

Cada resposta carrega um array `labels` (o eixo do tempo, preenchido com zero em todo o intervalo) e uma entrada em `series` por grupo, cada uma contendo um array por métrica solicitada alinhado a `labels`. Séries após `limit` não são descartadas — elas são colapsadas em `other_bucket`, calculado como o total do intervalo menos as séries retornadas, para que um gráfico renderizado sempre some seus números reais; `truncated` é `true` sempre que isso acontece.

De onde vêm os números: `sent`, `delivered`, `read` e `replied` vêm de registros de mensagens, que carregam o canal e o número de envio. `booked`, `contact_created` e `credits_spent` vêm do fluxo de eventos, que não carrega número de envio, então essas métricas caem no bucket de número `null` quando você agrupa por `number`.

| Parâmetro | Obrigatório | Descrição |
|---|---|---|
| `from` | Não | Início do intervalo, `YYYY-MM-DD`. O padrão é 30 dias atrás. |
| `to` | Não | Fim do intervalo, `YYYY-MM-DD`. O padrão é hoje. |
| `metrics` | Não | Lista separada por vírgulas de `sent`, `ai_sent`, `human_sent`, `delivered`, `read`, `replied`, `booked`, `contact_created`, `credits_spent`. O padrão é `sent,replied`. Uma métrica desconhecida retorna `400`. |
| `group_by` | Não | Lista separada por vírgulas de até duas dimensões de `date`, `campaign`, `channel`, `agent`, `number`. `date` é aceito, mas não tem efeito — toda resposta já carrega o eixo do tempo. Omitir para uma única série de toda a conta. |
| `granularity` | Não | `day` (padrão), `week` ou `month`. Buckets semanais começam na segunda-feira, buckets mensais no dia 1º. |
| `limit` | Não | Quantas séries retornar antes que o restante seja colapsado em `other_bucket`, de 1 a 50. O padrão é 12. |
| `campaign_id` | Não | Contar apenas a atividade pertencente a esta campanha. Legado; prefira `agent_id`. |
| `agent_id` | Não | Contar apenas a atividade pertencente a este Agente de IA. |
| `channel` | Não | Contar apenas a atividade neste canal, por exemplo `whatsapp`. |

O intervalo de datas deste endpoint é limitado a **92 dias** (mais restrito que o limite de 366 dias usado em outros lugares nesta 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()
```

**Resposta**

```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` — a identidade de uma série. Apenas as chaves para as dimensões `group_by` solicitadas estão presentes; uma dimensão cujo valor é desconhecido para uma linha (uma mensagem sem campanha, um evento sem canal) retorna como `null` em vez de ser descartada, para que as séries ainda somem os totais.
- `other_bucket` — `null` quando nada foi colapsado.
- Este endpoint retorna `503` com `"error_code": "analytics_unavailable"` quando o banco de dados de relatórios não consegue responder pela sua conta, em vez de um `200` cheio de zeros — um gráfico zerado seria interpretado como fato.

---

## Resultados de conversas

Retorna como as conversas terminaram em um intervalo de datas: uma contagem diária para cada tag de resultado que a IA atribuiu, mais totais do intervalo para respostas, agendamentos, transferências para um humano e conversas que a IA nunca classificou.

`GET /analytics/outcomes`

Passe `group_by=tag` para colapsar o eixo do tempo e obter apenas os totais do intervalo por tag — nesse modo, `labels` fica vazio e o array `counts` de cada tag fica vazio, enquanto `total` ainda é preenchido.

| Parâmetro | Obrigatório | Descrição |
|---|---|---|
| `from` | Não | Início do intervalo, `YYYY-MM-DD`. O padrão é 30 dias atrás. |
| `to` | Não | Fim do intervalo, `YYYY-MM-DD`. O padrão é hoje. |
| `campaign_id` | Não | Conta apenas conversas com contatos atualmente nesta campanha. Legado; prefira `agent_id`. |
| `agent_id` | Não | Conta apenas resultados pertencentes a este Agente de IA. |
| `group_by` | Não | `date` (padrão) mantém as contagens por dia; `tag` agrupa em totais do intervalo. |

O intervalo de datas deste endpoint é limitado a **92 dias**.

**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()
```

**Resposta**

```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 conversas às quais a IA nunca atribuiu uma tag de resultado.
- `totals.human_alerted` — conversas transferidas para um humano; isso é registrado em cada transferência e não era exibido anteriormente por nenhum endpoint.
- Mesma postura de `503`/`analytics_unavailable` que a série de Métricas quando o banco de dados de relatórios não pode responder.

---

## Insights do painel

Retorna o payload completo do painel para um intervalo de datas em uma única chamada: um mapa de calor da taxa de resposta por dia da semana e hora, o ranking de campanhas, volume por canal, totais exatos por conexão, detalhamentos de métricas por dia (em toda a conta, por canal e por número), origem dos contatos, tempo de resposta da caixa de entrada e um feed de atividades recentes. Este é o payload de relatórios mais rico da API — ele alimenta diretamente o painel no aplicativo.

`GET /analytics/dashboard-insights`

| Parâmetro | Obrigatório | Descrição |
|---|---|---|
| `startDate` | Sim | Início do intervalo, `YYYY-MM-DD`. |
| `endDate` | Sim | Fim do intervalo, `YYYY-MM-DD`. |
| `campaignId` | Não | Inclui apenas atividades pertencentes a esta campanha (`campaign_id` também aceito). Legado; prefira `agent_id`. |
| `agent_id` | Não | Inclui apenas atividades pertencentes a este Agente de IA (`agentId` também aceito). Sob o escopo de um agente, o ranking de campanhas é construído apenas a partir da atividade desse agente. |

Este endpoint usa `startDate`/`endDate` (não `from`/`to`) porque compartilha sua implementação com o painel no aplicativo. O intervalo é limitado a 92 dias e é **ajustado, não rejeitado**, quando é maior que isso.

> **Nulo significa indisponível, não zero.** Vários blocos (`numberStats`, `channelDailySeries`, `metricDailyBreakdown`, `contactsByCountry`) são calculados a partir do banco de dados de relatórios e retornam `null` quando ele não pode responder pela sua conta. Não renderize um bloco `null` como um gráfico vazio.

**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()
```

**Resposta** (resumida — este payload é grande; consulte a [Referência da API](reference.md) para o 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` é domingo até `6` é sábado.
- `numberStats`, `channelDailySeries`, `metricDailyBreakdown`, `contactsByCountry`, `ai_human_split` — cada um fica `null` independentemente quando o banco de dados de relatórios está indisponível para sua conta; todos os outros blocos ainda retornam.

---

## Insights de IA do painel

Retorna três insights curtos, escritos por IA, sobre as mensagens da conta em um intervalo de datas: uma vitória, um ponto de atenção e uma dica — frases que você pode colar diretamente em um relatório, em vez de números que você ainda precisa interpretar. Gerado apenas a partir das métricas de mensagens da própria conta.

`GET /analytics/dashboard-ai-insights`

| Parâmetro | Obrigatório | Descrição |
|---|---|---|
| `startDate` | Sim | Início do intervalo, `YYYY-MM-DD`. |
| `endDate` | Sim | Fim do intervalo, `YYYY-MM-DD`. |

Este endpoint é de nível de conta — ele não aceita escopo de campanha ou 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()
```

**Resposta**

```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." }
    ]
  }
}
```

A ausência de `startDate` ou `endDate` retorna `400`.

---

## Linha do tempo de atividade da entidade

Retorna a atividade de um único contato, negócio ou tarefa como uma linha do tempo, do mais recente para o mais antigo: o que aconteceu e quando, incluindo mensagens, agendamentos, notas e mudanças de status. Use-o para responder "o que aconteceu com esta pessoa" sem precisar combinar vários endpoints de lista.

`GET /analytics/entity-activity`

| Parâmetro | Obrigatório | Descrição |
|---|---|---|
| `entityType` | Sim | `contact`, `deal` ou `task`. |
| `entityId` | Sim | ID do registro cuja linha do tempo deve ser retornada. |

**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()
```

**Resposta**

```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\""
      }
    ]
  }
}
```

Um `entityType`/`entityId` ausente ou inválido retorna `400`. Uma entidade que não existe em sua conta retorna `404`, para que os IDs de outras contas permaneçam impossíveis de adivinhar.

---

## Contagens de eventos agregados (legado)

Retorna as mesmas contagens de eventos agregados que o [Resumo de volume de mensagens](#message-volume-summary), mas no formato camelCase (`contactCreated` em vez de `contact_created`, `byDate` em vez de `by_date`) que algumas integrações mais antigas utilizam. Prefira `/analytics/summary` para novas integrações — este endpoint existe apenas para que o painel do aplicativo e a API compartilhem a mesma implementação.

`GET /analytics/aggregate`

| Parâmetro | Obrigatório | Descrição |
|---|---|---|
| `startDate` | Não | Início do intervalo, data ou data-hora ISO. O padrão é a mesma janela que `/analytics/summary` usa. |
| `endDate` | Não | Fim do intervalo, data ou data-hora ISO. |
| `campaignId` | Não | Contar apenas eventos pertencentes a esta campanha (`campaign_id` também aceito). Legado; prefira `agent_id`. |
| `agent_id` | Não | Contar apenas eventos pertencentes a este Agente de IA (`agentId` também aceito). |

**cURL**

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

**Resposta**

```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 } }
    ]
  }
}
```

---

## Consolidação de subcontas de agência


---

## Erros da API de Analytics

Os endpoints de Analytics retornam o envelope de erro padrão:

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

Em um endpoint de análise, um formato de data inválido ou uma janela fora do intervalo retorna `400`, e um `campaign_id` ou `agent_id` desconhecido retorna `404`. Enviar tanto `campaign_id` quanto `agent_id` em um endpoint que aceita apenas um deles também é um `400` — passe no máximo um. Os endpoints de relatório exclusivos do PG (Série de métricas, Resultados de conversas, Consolidação de agência) retornam `503` com `"error_code": "analytics_unavailable"` em vez de um `200` cheio de zeros quando o banco de dados de relatórios não consegue responder pela sua conta — tente novamente em breve. Os códigos compartilhados que todo endpoint pode retornar — `401`, `403` (seu plano não inclui acesso à API ou, na consolidação de agência, sua conta não é Agência/Dev), `429` (limite de taxa) e `500` — estão listados com orientações de nova tentativa em [Erros e Paginação](errors-and-pagination.md).

---

## Próximos passos

- [Autenticação](authentication.md) — as quatro maneiras de autenticar uma solicitação.
- [Erros e Limites de Taxa](errors-and-pagination.md) — códigos de status e o limite de 300 req/min.
- [API de Campanhas](campaigns.md) — as campanhas pelas quais esses números podem ser filtrados.
