
# API di Analisi e Report

Questi endpoint di sola lettura ti consentono di estrarre l'attività del tuo account nei tuoi dashboard e report: conteggi degli eventi dei messaggi, consumo di crediti, spesa AI e gli stessi grafici e approfondimenti mostrati nel dashboard in-app. Questa guida copre:

- **Riepilogo** — contatori del volume dei messaggi (inviati, consegnati, letti, risposti, prenotati, contatti creati, crediti).
- **Crediti** — un registro dettagliato e impaginato dell'utilizzo dei crediti con totali e suddivisioni.
- **Costo AI** — un riepilogo giornaliero della spesa AI.
- **Serie di metriche** — una serie temporale pronta per il grafico per una o più metriche, raggruppate per campagna, canale, Agente AI o numero.
- **Esiti delle conversazioni** — come sono terminate le conversazioni, in base al tag di esito assegnato dall'AI.
- **Approfondimenti dashboard** e **Approfondimenti AI dashboard** — i dati completi dietro il dashboard in-app, inclusi i riepiloghi scritti dall'AI.
- **Attività dell'entità** — la cronologia di un singolo contatto, trattativa o attività.
- **Conteggi aggregati degli eventi** — una forma legacy camelCase del Riepilogo mantenuta per le integrazioni esistenti.

Ogni endpoint in questa pagina richiede un ambito esatto, non entrambi: passa al massimo uno tra `campaign_id` (legacy) o `agent_id` dove l'endpoint lo accetta. L'invio di entrambi restituisce `400`, e un id che non è presente nel tuo account restituisce `404` anziché `403`, in modo che gli id degli altri account rimangano non indovinabili.

Tutti i percorsi seguenti sono relativi all'URL di base dell'API:

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

Ogni richiesta deve essere autenticata. Consulta [Autenticazione](authentication.md) per i quattro metodi accettati. Gli esempi qui utilizzano l'intestazione `X-API-Key` (e una forma di parametro di query per cURL).

---

## Intervallo di date

Tutti e tre gli endpoint accettano gli stessi filtri di data opzionali:

| Parametro | Descrizione |
|---|---|
| `from` | Inizio dell'intervallo, `YYYY-MM-DD`, inclusivo. L'impostazione predefinita è 30 giorni fa. |
| `to` | Fine dell'intervallo, `YYYY-MM-DD`, inclusivo. L'impostazione predefinita è oggi. |

Le date sono interpretate in UTC. L'intervallo è impostato per impostazione predefinita sugli **ultimi 30 giorni** ed è limitato a **366 giorni**: un intervallo più ampio restituisce `400`. `from` non deve essere successivo a `to`.

### Il flag `truncated`

Gli endpoint **Riepilogo** e **Crediti** limitano il numero di record che una singola richiesta può scansionare. Se il tuo intervallo è abbastanza intenso da raggiungere tale limite, la risposta include `"truncated": true`. Quando lo vedi, i numeri si basano su una scansione parziale: restringi l'intervallo di date (o scorri le pagine con una finestra più piccola) per ottenere cifre complete.

::: note
**Nota:** Le cifre relative a costi e token sono incluse solo per le chiamate AI fatturate tramite le proprie chiavi API del provider. Quando le cifre dei costi sono nascoste per il proprio account, la risposta imposta `"costs_redacted": true` e i campi relativi ai costi vengono restituiti come zero.
:::


---

## Riepilogo volume messaggi

Restituisce i contatori aggregati degli eventi dei messaggi per il tuo account, sia come totali dell'intervallo che come serie giornaliera. Ogni giorno nell'intervallo appare in `by_date`: i giorni di inattività sono riempiti con zero. Filtra facoltativamente per una singola campagna con `campaign_id`.

`GET /analytics/summary`

| Parametro | Obbligatorio | Descrizione |
|---|---|---|
| `from` | No | Inizio intervallo, `YYYY-MM-DD`. |
| `to` | No | Fine intervallo, `YYYY-MM-DD`. |
| `campaign_id` | No | Conta solo gli eventi appartenenti a questa campagna. |

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

**Risposta**

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

Ogni voce in `by_date` presenta gli stessi campi contatore di `totals`, più un `date`.

Se si passa un `campaign_id` che non appartiene al proprio account, la risposta sarà `404` con `{ "success": false, "error": "Campaign not found" }`.

---

## Utilizzo crediti

Restituisce l'utilizzo dei crediti nell'intervallo specificato: un elenco paginato di record individuali, oltre ai totali dell'intervallo e alle suddivisioni per motivo e per campagna.

`GET /analytics/credits`

| Parametro | Obbligatorio | Descrizione |
|---|---|---|
| `from` | No | Inizio intervallo, `YYYY-MM-DD`. |
| `to` | No | Fine intervallo, `YYYY-MM-DD`. |
| `campaign_id` | No | Includi solo l'utilizzo attribuito a questa campagna. |
| `limit` | No | Dimensione pagina per `records`, 1–100. Il valore predefinito è 50. |
| `cursor` | No | Passare il `next_cursor` della pagina precedente per recuperare la pagina successiva. |

> **Rettifiche vs. consumo:** Le variazioni di saldo come bonus, rinnovi del piano e correzioni sono **escluse** da `totals` e dalle suddivisioni: non rappresentano un consumo reale. Compaiono comunque nell'elenco `records`, contrassegnate con `"is_adjustment": true`.

**I totali e le suddivisioni appaiono solo nella prima pagina** (quando non viene fornito alcun `cursor`). Nelle pagine successive, `totals`, `by_reason`, `by_reason_cost` e `by_campaign` vengono restituiti come `null`: solo l'array `records` continua. Ciò evita di riesaminare l'intero intervallo per ogni pagina.

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

**Risposta** (prima pagina)

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

**Note sul campo:**

- `amount` — crediti addebitati per il record. Zero per i record fatturati alla propria chiave API del provider.
- `is_adjustment` — `true` per le variazioni di saldo (escluse dai totali/suddivisioni).
- `cost_usd`, `input_tokens`, `output_tokens`, `cache_read_tokens`, `cache_creation_tokens`, `ai_model`, `request_id` — popolati solo nei record fatturati alla propria chiave API del provider; zero o `null` altrimenti.
- `is_test` — `true` per esecuzioni di prova/playground, che non vengono mai fatturate.
- `next_cursor` — il cursore per la pagina successiva, o `null` quando non ci sono più record.

---

## Riepilogo costi IA

Restituisce il riepilogo della spesa IA giornaliera per il proprio account. Legge i totali giornalieri pre-aggregati, quindi è veloce anche su intervalli lunghi. Ogni giorno nell'intervallo appare in `days`: i giorni senza attività sono riempiti con zero.

`GET /analytics/ai-cost`

| Parametro | Obbligatorio | Descrizione |
|---|---|---|
| `from` | No | Inizio dell'intervallo, `YYYY-MM-DD`. |
| `to` | No | Fine dell'intervallo, `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()
```

**Risposta**

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

**Note sul campo:**

- `byok_usd` — spesa addebitata sulle chiavi API del tuo provider.
- `platform_usd` — la parte di spesa eseguita sulla piattaforma anziché tramite la tua chiave.
- `input_usd`, `output_usd`, `cache_creation_usd`, `cache_read_usd` — le componenti di costo che costituiscono `total_usd`.
- `by_provider` — spesa in USD suddivisa per nome del provider AI.
- Le cifre in USD vengono restituite solo agli account che utilizzano la propria chiave del provider. Per gli account che pagano tramite crediti, ogni campo USD è zero e `costs_redacted` è `true` (il conteggio delle chiamate rimane visibile).

---

## Serie di metriche

Restituisce una o più serie temporali di metriche in un'unica chiamata, raggruppate facoltativamente fino a due dimensioni: l'endpoint a cui associare un grafico. Una singola richiesta può rispondere a "inviati e risposti al giorno, per canale, per questa campagna" senza una chiamata per campagna.

`GET /analytics/series`

Ogni risposta contiene un array `labels` (l'asse temporale, riempito con zeri sull'intero intervallo) e una voce in `series` per gruppo, ciascuna contenente un array per ogni metrica richiesta allineata a `labels`. Le serie oltre `limit` non vengono eliminate: si comprimono in `other_bucket`, calcolato come il totale dell'intervallo meno le serie restituite, in modo che un grafico renderizzato corrisponda sempre ai tuoi numeri reali; `truncated` è `true` ogni volta che ciò accade.

Da dove provengono i numeri: `sent`, `delivered`, `read` e `replied` provengono dai record dei messaggi, che contengono il canale e il numero di invio. `booked`, `contact_created` e `credits_spent` provengono dal flusso di eventi, che non contiene alcun numero di invio, quindi tali metriche finiscono nel bucket `null`-number quando raggruppi per `number`.

| Parametro | Obbligatorio | Descrizione |
|---|---|---|
| `from` | No | Inizio intervallo, `YYYY-MM-DD`. Il valore predefinito è 30 giorni fa. |
| `to` | No | Fine intervallo, `YYYY-MM-DD`. Il valore predefinito è oggi. |
| `metrics` | No | Elenco separato da virgole da `sent`, `ai_sent`, `human_sent`, `delivered`, `read`, `replied`, `booked`, `contact_created`, `credits_spent`. Il valore predefinito è `sent,replied`. Una metrica sconosciuta restituisce `400`. |
| `group_by` | No | Elenco separato da virgole di un massimo di due dimensioni da `date`, `campaign`, `channel`, `agent`, `number`. `date` è accettato ma non ha alcun effetto: ogni risposta contiene già l'asse temporale. Ometti per una singola serie a livello di account. |
| `granularity` | No | `day` (predefinito), `week` o `month`. I bucket settimanali iniziano il lunedì, quelli mensili il 1°. |
| `limit` | No | Quante serie restituire prima che le restanti si comprimano in `other_bucket`, 1–50. Il valore predefinito è 12. |
| `campaign_id` | No | Conta solo l'attività appartenente a questa campagna. Legacy; preferisci `agent_id`. |
| `agent_id` | No | Conta solo l'attività appartenente a questo Agente AI. |
| `channel` | No | Conta solo l'attività su questo canale, ad esempio `whatsapp`. |

L'intervallo di date di questo endpoint è limitato a **92 giorni** (più restrittivo rispetto al limite di 366 giorni utilizzato altrove in questa pagina).

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

**Risposta**

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

**Note sul campo:**

- `key` — l'identità di una serie. Sono presenti solo le chiavi per le dimensioni `group_by` richieste; una dimensione il cui valore è sconosciuto per una riga (un messaggio senza campagna, un evento senza canale) viene restituita come `null` anziché essere eliminata, in modo che le serie si sommino comunque ai totali.
- `other_bucket` — `null` quando nulla è stato compresso.
- Questo endpoint restituisce `503` con `"error_code": "analytics_unavailable"` quando il database di reportistica non può rispondere per il tuo account, anziché un `200` pieno di zeri: un grafico azzerato verrebbe interpretato come un fatto.

---

## Esiti delle conversazioni

Restituisce come sono terminate le conversazioni in un intervallo di date: un conteggio giornaliero per ogni tag di esito assegnato dall'AI, più i totali dell'intervallo per risposte, prenotazioni, trasferimenti a un operatore umano e conversazioni che l'AI non ha mai classificato.

`GET /analytics/outcomes`

Passa `group_by=tag` per comprimere l'asse temporale e ottenere solo i totali dell'intervallo per tag: in quella modalità `labels` è vuoto e l'array `counts` di ogni tag è vuoto, mentre `total` è ancora popolato.

| Parametro | Obbligatorio | Descrizione |
|---|---|---|
| `from` | No | Inizio intervallo, `YYYY-MM-DD`. Predefinito a 30 giorni fa. |
| `to` | No | Fine intervallo, `YYYY-MM-DD`. Predefinito a oggi. |
| `campaign_id` | No | Conta solo le conversazioni con i contatti attualmente in questa campagna. Legacy; preferire `agent_id`. |
| `agent_id` | No | Conta solo i risultati appartenenti a questo Agente AI. |
| `group_by` | No | `date` (predefinito) mantiene i conteggi giornalieri; `tag` raggruppa i totali dell'intervallo. |

L'intervallo di date di questo endpoint è limitato a **92 giorni**.

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

**Risposta**

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

**Note sul campo:**

- `by_tag[].tag` — `null` per le conversazioni a cui l'AI non ha mai assegnato un tag di risultato.
- `totals.human_alerted` — conversazioni trasferite a un operatore umano; questo viene scritto a ogni trasferimento e non era precedentemente mostrato da alcun endpoint.
- Stessa postura `503`/`analytics_unavailable` della serie Metric quando il database di reportistica non è in grado di rispondere.

---

## Approfondimenti della dashboard

Restituisce il payload completo della dashboard per un intervallo di date in un'unica chiamata: una mappa di calore del tasso di risposta per giorno della settimana e ora, la classifica delle campagne, il volume per canale, i totali esatti per connessione, le suddivisioni delle metriche giornaliere (a livello di account, per canale e per numero), la provenienza dei contatti, il tempo di risposta della posta in arrivo e un feed delle attività recenti. Questo è il payload di reportistica più ricco dell'API: alimenta direttamente la dashboard in-app.

`GET /analytics/dashboard-insights`

| Parametro | Obbligatorio | Descrizione |
|---|---|---|
| `startDate` | Sì | Inizio intervallo, `YYYY-MM-DD`. |
| `endDate` | Sì | Fine intervallo, `YYYY-MM-DD`. |
| `campaignId` | No | Include solo l'attività appartenente a questa campagna (accettato anche `campaign_id`). Legacy; preferire `agent_id`. |
| `agent_id` | No | Include solo l'attività appartenente a questo Agente AI (accettato anche `agentId`). Sotto l'ambito di un agente, la classifica delle campagne viene creata solo dall'attività di quell'agente. |

Questo endpoint utilizza `startDate`/`endDate` (non `from`/`to`) perché condivide la sua implementazione con la dashboard in-app. L'intervallo è limitato a 92 giorni e viene **troncato, non rifiutato**, quando è più ampio.

> **Null significa non disponibile, non zero.** Diversi blocchi (`numberStats`, `channelDailySeries`, `metricDailyBreakdown`, `contactsByCountry`) sono calcolati dal database di reportistica e restituiscono `null` quando non è in grado di rispondere per il tuo account. Non visualizzare un blocco `null` come un grafico vuoto.

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

**Risposta** (abbreviata — questo payload è grande; consulta il [Riferimento API](reference.md) per lo schema 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
  }
}
```

**Note sul campo:**

- `heatmap.buckets[].weekday` — `0` va da domenica a `6` che è sabato.
- `numberStats`, `channelDailySeries`, `metricDailyBreakdown`, `contactsByCountry`, `ai_human_split` — ognuno è indipendentemente `null` quando il database di reportistica non è disponibile per il tuo account; ogni altro blocco viene comunque restituito.

---

## Approfondimenti AI della dashboard

Restituisce tre brevi approfondimenti scritti dall'AI sulla messaggistica dell'account in un intervallo di date: un successo, un aspetto da monitorare e un suggerimento — frasi che puoi incollare direttamente in un report invece di numeri che dovresti ancora interpretare. Generato solo dalle metriche dei messaggi dell'account.

`GET /analytics/dashboard-ai-insights`

| Parametro | Obbligatorio | Descrizione |
|---|---|---|
| `startDate` | Sì | Inizio intervallo, `YYYY-MM-DD`. |
| `endDate` | Sì | Fine intervallo, `YYYY-MM-DD`. |

Questo endpoint è valido per l'intero account: non richiede l'ambito di una campagna o di un 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()
```

**Risposta**

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

Se mancano `startDate` o `endDate`, viene restituito `400`.

---

## Cronologia delle attività dell'entità

Restituisce l'attività di un singolo contatto, trattativa o attività come un'unica cronologia, dalla più recente alla meno recente: cosa è successo e quando, tra messaggi, appuntamenti, note e cambi di stato. Usalo per rispondere alla domanda "cosa è successo con questa persona" senza dover unire diversi endpoint di elenco.

`GET /analytics/entity-activity`

| Parametro | Obbligatorio | Descrizione |
|---|---|---|
| `entityType` | Sì | `contact`, `deal` o `task`. |
| `entityId` | Sì | ID del record di cui restituire la cronologia. |

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

**Risposta**

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

Se `entityType`/`entityId` mancano o non sono validi, viene restituito `400`. Un'entità che non esiste nel tuo account restituisce `404`, in modo che gli ID di altri account rimangano impossibili da indovinare.

---

## Conteggi aggregati degli eventi (legacy)

Restituisce gli stessi conteggi aggregati degli eventi di [Riepilogo volume messaggi](#message-volume-summary), ma nel formato camelCase (`contactCreated` invece di `contact_created`, `byDate` invece di `by_date`) su cui sono state costruite alcune integrazioni meno recenti. Preferisci `/analytics/summary` per le nuove integrazioni: questo endpoint esiste solo affinché la dashboard in-app e l'API condividano la stessa implementazione.

`GET /analytics/aggregate`

| Parametro | Obbligatorio | Descrizione |
|---|---|---|
| `startDate` | No | Inizio dell'intervallo, data o data-ora ISO. Per impostazione predefinita utilizza la stessa finestra di `/analytics/summary`. |
| `endDate` | No | Fine dell'intervallo, data o data-ora ISO. |
| `campaignId` | No | Conta solo gli eventi appartenenti a questa campagna (accettato anche `campaign_id`). Legacy; preferisci `agent_id`. |
| `agent_id` | No | Conta solo gli eventi appartenenti a questo Agente IA (accettato anche `agentId`). |

**cURL**

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

**Risposta**

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

---

## Rollup dei sub-account dell'agenzia


---

## Errori dell'API Analytics

Gli endpoint di Analytics restituiscono il formato di errore standard:

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

Su un endpoint di analisi, un formato data non valido o una finestra fuori intervallo restituiscono `400`, mentre un `campaign_id` o `agent_id` sconosciuto restituisce `404`. Inviare sia `campaign_id` che `agent_id` su un endpoint che ne accetta solo uno è anch'esso un `400`: passane al massimo uno. Gli endpoint di reportistica solo PG (Serie di metriche, Esiti conversazione, Rollup agenzia) restituiscono `503` con `"error_code": "analytics_unavailable"` invece di un `200` pieno di zeri quando il database di reportistica non può rispondere per il tuo account: riprova a breve. I codici condivisi che ogni endpoint può restituire — `401`, `403` (il tuo piano non include l'accesso API o, nel rollup agenzia, il tuo account non è Agenzia/Sviluppatore), `429` (limite di frequenza) e `500` — sono elencati con indicazioni su come riprovare in [Errori e Paginazione](errors-and-pagination.md).

---

## Passaggi successivi

- [Autenticazione](authentication.md) — i quattro modi per autenticare una richiesta.
- [Errori e limiti di frequenza](errors-and-pagination.md) — codici di stato e il limite di 300 richieste/min.
- [API Campagne](campaigns.md) — le campagne in base alle quali è possibile filtrare questi dati.
