
# API analityki i raportów

Te punkty końcowe tylko do odczytu pozwalają na pobieranie aktywności Twojego konta do własnych pulpitów nawigacyjnych i raportów: liczby zdarzeń wiadomości, zużycia kredytów, wydatków na AI oraz tych samych wykresów i analiz, które wyświetla pulpit nawigacyjny w aplikacji. Ten przewodnik obejmuje:

- **Podsumowanie** — liczniki wolumenu wiadomości (wysłane, dostarczone, przeczytane, odpowiedzi, umówione spotkania, utworzone kontakty, kredyty).
- **Kredyty** — szczegółowa, paginowana księga zużycia kredytów z sumami i zestawieniami.
- **Koszt AI** — dzienne podsumowanie wydatków na AI.
- **Serie metryk** — gotowe do użycia na wykresach szeregi czasowe dla jednej lub wielu metryk, pogrupowane według kampanii, kanału, agenta AI lub numeru.
- **Wyniki konwersacji** — sposób zakończenia konwersacji według tagu wyniku przypisanego przez AI.
- **Analizy pulpitu** i **Analizy AI pulpitu** — pełne dane stojące za pulpitem nawigacyjnym w aplikacji, w tym podsumowania napisane przez AI.
- **Aktywność jednostki** — oś czasu pojedynczego kontaktu, transakcji lub zadania.
- **Zagregowane liczby zdarzeń** — starsza forma (camelCase) podsumowania zachowana dla istniejących integracji.

Każdy punkt końcowy na tej stronie wymaga dokładnego zakresu, a nie obu: przekaż co najwyżej jeden z `campaign_id` (starszy) lub `agent_id` tam, gdzie punkt końcowy go akceptuje. Wysłanie obu zwraca `400`, a identyfikator, którego nie ma na Twoim koncie, zwraca `404` zamiast `403`, dzięki czemu identyfikatory innych kont pozostają niemożliwe do odgadnięcia.

Wszystkie poniższe ścieżki są względne względem bazowego adresu URL API:

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

Każde żądanie musi zostać uwierzytelnione. Zobacz [Uwierzytelnianie](authentication.md), aby poznać cztery akceptowane metody. Przykłady tutaj używają nagłówka `X-API-Key` (oraz jednej formy parametru zapytania dla cURL).

---

## Zakres dat

Wszystkie trzy punkty końcowe akceptują te same opcjonalne filtry dat:

| Parametr | Opis |
|---|---|
| `from` | Początek zakresu, `YYYY-MM-DD`, włącznie. Domyślnie 30 dni temu. |
| `to` | Koniec zakresu, `YYYY-MM-DD`, włącznie. Domyślnie dzisiaj. |

Daty są interpretowane w czasie UTC. Zakres domyślnie obejmuje **ostatnie 30 dni** i jest ograniczony do **366 dni** — szerszy zakres zwróci `400`. `from` nie może przypadać po `to`.

### Flaga `truncated`

Punkty końcowe **Podsumowanie** i **Kredyty** ograniczają liczbę rekordów skanowanych przez pojedyncze żądanie. Jeśli Twój zakres jest na tyle duży, że osiągnie ten limit, odpowiedź będzie zawierać `"truncated": true`. Gdy go zobaczysz, liczby będą oparte na częściowym skanowaniu — zawęź zakres dat (lub przeglądaj strony w mniejszym oknie), aby uzyskać pełne dane.

::: note
**Uwaga:** Dane dotyczące kosztów i tokenów są uwzględniane tylko dla wywołań AI rozliczanych za pomocą własnych kluczy API dostawcy. Gdy dane o kosztach są ukryte dla Twojego konta, odpowiedź ustawia `"costs_redacted": true`, a pola kosztów są zwracane jako zero.
:::


---

## Podsumowanie wolumenu wiadomości

Zwraca zagregowane liczniki zdarzeń wiadomości dla Twojego konta, zarówno jako sumy zakresu, jak i serie dzienne. Każdy dzień w zakresie pojawia się w `by_date` — dni bez aktywności są wypełnione zerami. Opcjonalnie przefiltruj do pojedynczej kampanii za pomocą `campaign_id`.

`GET /analytics/summary`

| Parametr | Wymagany | Opis |
|---|---|---|
| `from` | Nie | Początek zakresu, `YYYY-MM-DD`. |
| `to` | Nie | Koniec zakresu, `YYYY-MM-DD`. |
| `campaign_id` | Nie | Zliczaj tylko zdarzenia należące do tej kampanii. |

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

**Odpowiedź**

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

Każdy wpis w `by_date` posiada te same pola licznika co `totals` oraz dodatkowo `date`.

Jeśli przekażesz `campaign_id`, który nie należy do Twojego konta, odpowiedź będzie miała status `404` z `{ "success": false, "error": "Campaign not found" }`.

---

## Wykorzystanie kredytów

Zwraca wykorzystanie kredytów w danym zakresie: stronicowaną listę poszczególnych rekordów oraz sumy dla zakresu i podziały według przyczyny oraz kampanii.

`GET /analytics/credits`

| Parametr | Wymagany | Opis |
|---|---|---|
| `from` | Nie | Początek zakresu, `YYYY-MM-DD`. |
| `to` | Nie | Koniec zakresu, `YYYY-MM-DD`. |
| `campaign_id` | Nie | Uwzględnij tylko wykorzystanie przypisane do tej kampanii. |
| `limit` | Nie | Rozmiar strony dla `records`, 1–100. Domyślnie 50. |
| `cursor` | Nie | Przekaż `next_cursor` z poprzedniej strony, aby pobrać następną stronę. |

> **Korekty a zużycie:** Zmiany salda, takie jak bonusy, odnowienia planów i korekty, są **wykluczone** z `totals` i podziałów — nie stanowią rzeczywistego zużycia. Nadal pojawiają się na liście `records`, oznaczone jako `"is_adjustment": true`.

**Sumy i podziały pojawiają się tylko na pierwszej stronie** (gdy nie podano `cursor`). Na kolejnych stronach `totals`, `by_reason`, `by_reason_cost` oraz `by_campaign` są zwracane jako `null` — kontynuowana jest tylko tablica `records`. Pozwala to uniknąć ponownego skanowania całego zakresu dla każdej strony.

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

**Odpowiedź** (pierwsza strona)

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

**Uwagi terenowe:**

- `amount` — kredyty pobrane za rekord. Zero dla rekordów rozliczanych przy użyciu własnego klucza API dostawcy.
- `is_adjustment` — `true` dla zmian salda (wykluczone z sum/podziałów).
- `cost_usd`, `input_tokens`, `output_tokens`, `cache_read_tokens`, `cache_creation_tokens`, `ai_model`, `request_id` — wypełnione tylko dla rekordów rozliczanych przy użyciu własnego klucza API dostawcy; w przeciwnym razie zero lub `null`.
- `is_test` — `true` dla uruchomień w środowisku testowym (playground), które nigdy nie są rozliczane.
- `next_cursor` — kursor dla następnej strony lub `null`, gdy nie ma więcej rekordów.

---

## Podsumowanie kosztów AI

Zwraca dzienne podsumowanie wydatków na AI dla Twojego konta. Odczytuje wstępnie zagregowane sumy dzienne, dzięki czemu działa szybko nawet w długich zakresach. Każdy dzień w zakresie pojawia się w `days` — dni bez aktywności są wypełnione zerami.

`GET /analytics/ai-cost`

| Parametr | Wymagany | Opis |
|---|---|---|
| `from` | Nie | Początek zakresu, `YYYY-MM-DD`. |
| `to` | Nie | Koniec zakresu, `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()
```

**Odpowiedź**

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

**Uwagi terenowe:**

- `byok_usd` — wydatki rozliczone przy użyciu własnych kluczy API dostawcy.
- `platform_usd` — część wydatków, która została poniesiona na platformie, a nie przy użyciu własnego klucza.
- `input_usd`, `output_usd`, `cache_creation_usd`, `cache_read_usd` — składniki kosztów, które tworzą `total_usd`.
- `by_provider` — wydatki w USD według nazwy dostawcy AI.
- Kwoty w USD są zwracane tylko dla kont korzystających z własnego klucza dostawcy. W przypadku kont opłacanych kredytami każde pole USD wynosi zero, a `costs_redacted` to `true` (liczba wywołań pozostaje widoczna).

---

## Serie metryk

Zwraca jedną lub więcej szeregów czasowych metryk w jednym wywołaniu, opcjonalnie pogrupowanych według maksymalnie dwóch wymiarów — punkt końcowy do powiązania z wykresem. Pojedyncze żądanie może odpowiedzieć na pytanie „ile wysłano i ile otrzymano odpowiedzi dziennie, według kanału, dla tej kampanii” bez konieczności wykonywania jednego wywołania na kampanię.

`GET /analytics/series`

Każda odpowiedź zawiera tablicę `labels` (oś czasu, wypełnioną zerami w całym zakresie) oraz jeden wpis w `series` na grupę, z których każdy zawiera jedną tablicę na żądaną metrykę wyrównaną do `labels`. Serie wykraczające poza `limit` nie są odrzucane — zwijają się do `other_bucket`, obliczanego jako suma zakresu minus zwrócone serie, dzięki czemu wygenerowany wykres zawsze sumuje się do Twoich rzeczywistych liczb; `truncated` to `true`, gdy tylko to nastąpi.

Skąd pochodzą liczby: `sent`, `delivered`, `read` i `replied` pochodzą z rekordów wiadomości, które zawierają kanał i numer wysyłający. `booked`, `contact_created` i `credits_spent` pochodzą ze strumienia zdarzeń, który nie zawiera numeru wysyłającego, więc te metryki trafiają do zasobnika `null`-number podczas grupowania według `number`.

| Parametr | Wymagany | Opis |
|---|---|---|
| `from` | Nie | Początek zakresu, `YYYY-MM-DD`. Domyślnie 30 dni temu. |
| `to` | Nie | Koniec zakresu, `YYYY-MM-DD`. Domyślnie dzisiaj. |
| `metrics` | Nie | Rozdzielana przecinkami lista z `sent`, `ai_sent`, `human_sent`, `delivered`, `read`, `replied`, `booked`, `contact_created`, `credits_spent`. Domyślnie `sent,replied`. Nieznana metryka zwraca `400`. |
| `group_by` | Nie | Rozdzielana przecinkami lista maksymalnie dwóch wymiarów z `date`, `campaign`, `channel`, `agent`, `number`. `date` jest akceptowany, ale nie ma wpływu — każda odpowiedź już zawiera oś czasu. Pomiń dla pojedynczej serii dla całego konta. |
| `granularity` | Nie | `day` (domyślnie), `week` lub `month`. Zasobniki tygodniowe zaczynają się w poniedziałek, miesięczne 1. dnia miesiąca. |
| `limit` | Nie | Ile serii zwrócić, zanim reszta zwinie się do `other_bucket`, 1–50. Domyślnie 12. |
| `campaign_id` | Nie | Zliczaj tylko aktywność należącą do tej kampanii. Starsze; preferuj `agent_id`. |
| `agent_id` | Nie | Zliczaj tylko aktywność należącą do tego agenta AI. |
| `channel` | Nie | Zliczaj tylko aktywność na tym kanale, na przykład `whatsapp`. |

Zakres dat dla tego punktu końcowego jest ograniczony do **92 dni** (bardziej rygorystycznie niż limit 366 dni stosowany w innych miejscach na tej stronie).

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

**Odpowiedź**

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

**Uwagi terenowe:**

- `key` — tożsamość jednej serii. Obecne są tylko klucze dla żądanych wymiarów `group_by`; wymiar, którego wartość jest nieznana dla wiersza (wiadomość bez kampanii, zdarzenie bez kanału), powraca jako `null` zamiast zostać odrzucony, więc serie nadal sumują się do całości.
- `other_bucket` — `null`, gdy nic nie zostało zwinięte.
- Ten punkt końcowy zwraca `503` z `"error_code": "analytics_unavailable"`, gdy baza danych raportowania nie może odpowiedzieć dla Twojego konta, zamiast `200` pełnego zer — wykres z samymi zerami byłby odczytany jako fakt.

---

## Wyniki konwersacji

Zwraca sposób zakończenia konwersacji w danym zakresie dat: dzienne zliczenia dla każdego tagu wyniku przypisanego przez AI, plus sumy zakresu dla odpowiedzi, umówionych spotkań, przekazań do człowieka oraz konwersacji, których AI nigdy nie sklasyfikowało.

`GET /analytics/outcomes`

Przekaż `group_by=tag`, aby zwinąć oś czasu i uzyskać tylko sumy zakresu dla każdego tagu — w tym trybie `labels` jest puste, a tablica `counts` każdego tagu jest pusta, podczas gdy `total` jest nadal wypełnione.

| Parametr | Wymagany | Opis |
|---|---|---|
| `from` | Nie | Początek zakresu, `YYYY-MM-DD`. Domyślnie 30 dni temu. |
| `to` | Nie | Koniec zakresu, `YYYY-MM-DD`. Domyślnie dzisiaj. |
| `campaign_id` | Nie | Zliczaj tylko konwersacje z kontaktami aktualnie objętymi tą kampanią. Starsza wersja; preferuj `agent_id`. |
| `agent_id` | Nie | Zliczaj tylko wyniki należące do tego agenta AI. |
| `group_by` | Nie | `date` (domyślnie) zachowuje zliczenia dzienne; `tag` sumuje dane do wartości całkowitych dla zakresu. |

Zakres dat dla tego punktu końcowego jest ograniczony do **92 dni**.

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

**Odpowiedź**

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

**Uwagi terenowe:**

- `by_tag[].tag` — `null` dla konwersacji, do których AI nigdy nie przypisało tagu wyniku.
- `totals.human_alerted` — konwersacje przekazane człowiekowi; jest to zapisywane przy każdym przekazaniu i wcześniej nie było dostępne w żadnym punkcie końcowym.
- Ta sama postawa `503`/`analytics_unavailable` co w serii metryk, gdy baza danych raportowania nie może udzielić odpowiedzi.

---

## Wnioski z pulpitu nawigacyjnego

Zwraca pełny ładunek pulpitu nawigacyjnego dla zakresu dat w jednym wywołaniu: mapę cieplną współczynnika odpowiedzi według dnia tygodnia i godziny, tabelę wyników kampanii, wolumen na kanał, dokładne sumy na połączenie, dzienne zestawienia metryk (dla całego konta, na kanał i na numer), pochodzenie kontaktów, czas odpowiedzi w skrzynce odbiorczej oraz kanał ostatniej aktywności. Jest to najbogatszy ładunek raportowy w API — bezpośrednio zasila pulpit nawigacyjny w aplikacji.

`GET /analytics/dashboard-insights`

| Parametr | Wymagany | Opis |
|---|---|---|
| `startDate` | Tak | Początek zakresu, `YYYY-MM-DD`. |
| `endDate` | Tak | Koniec zakresu, `YYYY-MM-DD`. |
| `campaignId` | Nie | Uwzględnij tylko aktywność należącą do tej kampanii (akceptowane jest również `campaign_id`). Starsza wersja; preferuj `agent_id`. |
| `agent_id` | Nie | Uwzględnij tylko aktywność należącą do tego agenta AI (akceptowane jest również `agentId`). W zakresie agenta tabela wyników kampanii jest budowana wyłącznie na podstawie aktywności tego agenta. |

Ten punkt końcowy używa `startDate`/`endDate` (a nie `from`/`to`), ponieważ współdzieli implementację z pulpitem nawigacyjnym w aplikacji. Zakres jest ograniczony do 92 dni i jest **przycinany, a nie odrzucany**, gdy jest szerszy.

> **Null oznacza brak dostępności, a nie zero.** Kilka bloków (`numberStats`, `channelDailySeries`, `metricDailyBreakdown`, `contactsByCountry`) jest obliczanych z bazy danych raportowania i zwraca `null`, gdy nie może ona udzielić odpowiedzi dla Twojego konta. Nie renderuj bloku `null` jako pustego wykresu.

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

**Odpowiedź** (skrócona — ten ładunek jest duży; zobacz [Dokumentację API](reference.md), aby uzyskać pełny schemat)

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

**Uwagi terenowe:**

- `heatmap.buckets[].weekday` — `0` to niedziela, a `6` to sobota.
- `numberStats`, `channelDailySeries`, `metricDailyBreakdown`, `contactsByCountry`, `ai_human_split` — każdy z nich niezależnie zwraca `null`, gdy baza danych raportowania jest niedostępna dla Twojego konta; wszystkie pozostałe bloki nadal zwracają dane.

---

## Wnioski AI z pulpitu nawigacyjnego

Zwraca trzy krótkie, napisane przez AI wnioski dotyczące komunikacji na koncie w danym zakresie dat: jeden sukces, jedna rzecz do obserwacji i jedna wskazówka — zdania, które można wkleić bezpośrednio do raportu, zamiast liczb, które trzeba jeszcze zinterpretować. Generowane wyłącznie na podstawie własnych metryk wiadomości konta.

`GET /analytics/dashboard-ai-insights`

| Parametr | Wymagany | Opis |
|---|---|---|
| `startDate` | Tak | Początek zakresu, `YYYY-MM-DD`. |
| `endDate` | Tak | Koniec zakresu, `YYYY-MM-DD`. |

Ten punkt końcowy dotyczy całego konta — nie wymaga określenia zakresu kampanii ani agenta.

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

**Odpowiedź**

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

Brak `startDate` lub `endDate` zwraca `400`.

---

## Oś czasu aktywności obiektu

Zwraca aktywność pojedynczego kontaktu, transakcji lub zadania jako jedną oś czasu, od najnowszej: co się wydarzyło i kiedy, w podziale na wiadomości, spotkania, notatki i zmiany statusu. Użyj tego, aby odpowiedzieć na pytanie „co się stało z tą osobą” bez łączenia wielu punktów końcowych listy.

`GET /analytics/entity-activity`

| Parametr | Wymagany | Opis |
|---|---|---|
| `entityType` | Tak | `contact`, `deal` lub `task`. |
| `entityId` | Tak | Identyfikator rekordu, którego oś czasu ma zostać zwrócona. |

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

**Odpowiedź**

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

Brakujący lub nieprawidłowy `entityType`/`entityId` zwraca `400`. Obiekt, który nie istnieje na Twoim koncie, zwraca `404`, dzięki czemu identyfikatory innych kont pozostają niemożliwe do odgadnięcia.

---

## Zagregowane liczby zdarzeń (starsza wersja)

Zwraca te same zagregowane liczby zdarzeń co [Podsumowanie wolumenu wiadomości](#message-volume-summary), ale w formacie camelCase (`contactCreated` zamiast `contact_created`, `byDate` zamiast `by_date`), z którym współpracowały niektóre starsze integracje. W przypadku nowych integracji preferuj `/analytics/summary` — ten punkt końcowy istnieje tylko po to, aby pulpit nawigacyjny w aplikacji i interfejs API korzystały z jednej implementacji.

`GET /analytics/aggregate`

| Parametr | Wymagany | Opis |
|---|---|---|
| `startDate` | Nie | Początek zakresu, data lub data-godzina w formacie ISO. Domyślnie przyjmuje to samo okno, którego używa `/analytics/summary`. |
| `endDate` | Nie | Koniec zakresu, data lub data-godzina w formacie ISO. |
| `campaignId` | Nie | Zliczaj tylko zdarzenia należące do tej kampanii (akceptowane jest również `campaign_id`). Starsza wersja; preferuj `agent_id`. |
| `agent_id` | Nie | Zliczaj tylko zdarzenia należące do tego agenta AI (akceptowane jest również `agentId`). |

**cURL**

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

**Odpowiedź**

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

---

## Podsumowanie subkont agencji


---

## Błędy API analityki

Punkty końcowe analityki zwracają standardową kopertę błędu:

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

W punkcie końcowym analityki nieprawidłowy format daty lub okno poza zakresem zwraca `400`, a nieznany `campaign_id` lub `agent_id` zwraca `404`. Przesłanie zarówno `campaign_id`, jak i `agent_id` do punktu końcowego, który akceptuje tylko jeden z nich, również skutkuje `400` — przekaż maksymalnie jeden. Punkty końcowe raportowania tylko dla PG (serie metryk, wyniki konwersacji, podsumowanie agencji) zwracają `503` z `"error_code": "analytics_unavailable"` zamiast `200` pełnego zer, gdy baza danych raportowania nie może odpowiedzieć dla Twojego konta — spróbuj ponownie za chwilę. Wspólne kody, które może zwrócić każdy punkt końcowy — `401`, `403` (Twój plan nie obejmuje dostępu do API lub, w przypadku podsumowania agencji, Twoje konto nie ma roli Agencja/Deweloper), `429` (limit szybkości) i `500` — zostały wymienione wraz ze wskazówkami dotyczącymi ponawiania prób w sekcji [Błędy i stronicowanie](errors-and-pagination.md).

---

## Następne kroki

- [Uwierzytelnianie](authentication.md) — cztery sposoby uwierzytelniania żądania.
- [Błędy i limity szybkości](errors-and-pagination.md) — kody statusu oraz limit 300 żądań/min.
- [API kampanii](campaigns.md) — kampanie, według których można filtrować te dane.
