
# Analytics & Reports API

Disse skrivebeskyttede slutpunkter lader dig trække din kontos aktivitet ind i dine egne dashboards og rapporter: antal beskedhændelser, kreditforbrug, AI-forbrug og de samme grafer og indsigter, som dashboardet i appen viser. Denne guide dækker:

- **Oversigt** — tællere for beskedvolumen (sendt, leveret, læst, besvaret, booket, kontakter oprettet, kreditter).
- **Kreditter** — en detaljeret, pagineret hovedbog over kreditforbrug med totaler og opdelinger.
- **AI-omkostninger** — en daglig oversigt over AI-forbrug.
- **Metrikserier** — en grafklar tidsserie for en eller flere metrikker, grupperet efter kampagne, kanal, AI-agent eller nummer.
- **Samtaleresultater** — hvordan samtaler sluttede, efter AI-tildelt resultat-tag.
- **Dashboard-indsigter** og **Dashboard AI-indsigter** — de fulde data bag dashboardet i appen, inklusive AI-skrevne resuméer.
- **Enhedsaktivitet** — tidslinjen for en enkelt kontakt, aftale eller opgave.
- **Aggregerede hændelsestællinger** — en ældre, camelCase-form af Oversigt, der er bevaret til eksisterende integrationer.

Hvert slutpunkt på denne side kræver et præcist scope, ikke begge: angiv højst ét af `campaign_id` (ældre) eller `agent_id`, hvor slutpunktet accepterer det. Hvis du sender begge, returneres `400`, og et id, der ikke findes på din konto, returnerer `404` i stedet for `403`, så andre kontos id'er forbliver umulige at gætte.

Alle stier herunder er relative til API'ets base-URL:

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

Enhver anmodning skal godkendes. Se [Godkendelse](authentication.md) for de fire accepterede metoder. Eksemplerne her bruger `X-API-Key`-headeren (og én forespørgselsparameter-form til cURL).

---

## Datointerval

Alle tre slutpunkter accepterer de samme valgfrie datofiltre:

| Parameter | Beskrivelse |
|---|---|
| `from` | Start på intervallet, `YYYY-MM-DD`, inklusive. Standard er 30 dage siden. |
| `to` | Slut på intervallet, `YYYY-MM-DD`, inklusive. Standard er i dag. |

Datoer tolkes i UTC. Intervallet er som standard de **sidste 30 dage** og er begrænset til **366 dage** — et bredere interval returnerer `400`. `from` må ikke være efter `to`.

### `truncated`-flaget

**Summary**- og **Credits**-slutpunkterne begrænser, hvor mange poster en enkelt anmodning scanner. Hvis dit interval er travlt nok til at ramme denne grænse, inkluderer svaret `"truncated": true`. Når du ser det, er tallene baseret på en delvis scanning — indsnæv dit datointerval (eller side igennem med et mindre vindue) for at få komplette tal.

::: note
**Bemærk:** Omkostnings- og tokental er kun inkluderet for AI-kald, der faktureres til dine egne udbyder-API-nøgler. Når omkostningstal er skjult for din konto, sætter svaret `"costs_redacted": true`, og omkostningsfelterne returneres som nul.
:::


---

## Oversigt over beskedvolumen

Returnerer aggregerede tællere for beskedhændelser for din konto, både som totaler for intervallet og som en daglig serie. Hver dag i intervallet vises i `by_date` — stille dage udfyldes med nul. Filtrer eventuelt til en enkelt kampagne med `campaign_id`.

`GET /analytics/summary`

| Parameter | Påkrævet | Beskrivelse |
|---|---|---|
| `from` | Nej | Områdestart, `YYYY-MM-DD`. |
| `to` | Nej | Områdeslut, `YYYY-MM-DD`. |
| `campaign_id` | Nej | Tæl kun hændelser, der tilhører denne kampagne. |

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

**Svar**

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

Hver post i `by_date` har de samme tællerfelter som `totals`, plus en `date`.

Hvis du sender en `campaign_id`, der ikke tilhører din konto, er svaret `404` med `{ "success": false, "error": "Campaign not found" }`.

---

## Kreditforbrug

Returnerer kreditforbrug over området: en pagineret liste over individuelle poster, plus områdets totaler og opdelinger efter årsag og kampagne.

`GET /analytics/credits`

| Parameter | Påkrævet | Beskrivelse |
|---|---|---|
| `from` | Nej | Områdestart, `YYYY-MM-DD`. |
| `to` | Nej | Områdeslut, `YYYY-MM-DD`. |
| `campaign_id` | Nej | Medtag kun forbrug, der er tilskrevet denne kampagne. |
| `limit` | Nej | Sidestørrelse for `records`, 1–100. Standard er 50. |
| `cursor` | Nej | Send den forrige sides `next_cursor` for at hente den næste side. |

> **Justeringer vs. forbrug:** Saldoforandringer såsom bonusser, abonnementsfornyelser og rettelser er **ekskluderet** fra `totals` og opdelingerne – de er ikke reelt forbrug. De vises stadig i `records`-listen, markeret med `"is_adjustment": true`.

**Totaler og opdelinger vises kun på den første side** (når ingen `cursor` er angivet). På efterfølgende sider returneres `totals`, `by_reason`, `by_reason_cost` og `by_campaign` som `null` – kun `records`-arrayet fortsætter. Dette undgår at gen-scanne hele området for hver side.

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

**Svar** (første side)

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

**Feltnoter:**

- `amount` — kreditter debiteret for posten. Nul for poster faktureret til din egen udbyder-API-nøgle.
- `is_adjustment` — `true` for saldoforandringer (ekskluderet fra totaler/opdelinger).
- `cost_usd`, `input_tokens`, `output_tokens`, `cache_read_tokens`, `cache_creation_tokens`, `ai_model`, `request_id` — udfyldes kun på poster faktureret til din egen udbyder-API-nøgle; ellers nul eller `null`.
- `is_test` — `true` for legeplads-/testkørsler, som aldrig faktureres.
- `next_cursor` — markøren for den næste side, eller `null` når der ikke er flere poster.

---

## AI-omkostningsopgørelse

Returnerer den daglige AI-omkostningsopgørelse for din konto. Dette læser præ-aggregerede daglige totaler, så det er hurtigt selv over lange områder. Hver dag i området vises i `days` – stille dage er udfyldt med nul.

`GET /analytics/ai-cost`

| Parameter | Påkrævet | Beskrivelse |
|---|---|---|
| `from` | Nej | Områdestart, `YYYY-MM-DD`. |
| `to` | Nej | Områdeslut, `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()
```

**Svar**

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

**Feltnoter:**

- `byok_usd` — forbrug faktureret til dine egne udbyder-API-nøgler.
- `platform_usd` — den del af forbruget, der kørte på platformen i stedet for din egen nøgle.
- `input_usd`, `output_usd`, `cache_creation_usd`, `cache_read_usd` — de omkostningskomponenter, der udgør `total_usd`.
- `by_provider` — USD-forbrug grupperet efter AI-udbydernavn.
- USD-tal returneres kun til konti, der bruger deres egen udbydernøgle. For konti, der betaler med kredit, er hvert USD-felt nul, og `costs_redacted` er `true` (opkaldstællinger forbliver synlige).

---

## Metrikserier

Returnerer en eller flere metrik-tidsserier i ét kald, eventuelt grupperet efter op til to dimensioner — slutpunktet til at binde en graf til. En enkelt forespørgsel kan besvare "sendt og besvaret pr. dag, pr. kanal, for denne kampagne" uden at skulle foretage ét kald pr. kampagne.

`GET /analytics/series`

Hvert svar indeholder et `labels`-array (tidsaksen, nul-udfyldt over hele intervallet) og én post i `series` pr. gruppe, hvor hver indeholder ét array pr. anmodet metrik, der er justeret til `labels`. Serier efter `limit` bliver ikke droppet — de kollapser til `other_bucket`, beregnet som intervallets total minus den returnerede serie, så en gengivet graf altid summerer op til dine reelle tal; `truncated` er `true`, når det sker.

Hvor tallene kommer fra: `sent`, `delivered`, `read` og `replied` kommer fra beskedposter, som indeholder kanal og afsendernummer. `booked`, `contact_created` og `credits_spent` kommer fra hændelsesstrømmen, som ikke indeholder noget afsendernummer, så disse metrikker lander i `null`-nummer-bucket, når du grupperer efter `number`.

| Parameter | Påkrævet | Beskrivelse |
|---|---|---|
| `from` | Nej | Intervalstart, `YYYY-MM-DD`. Standard er 30 dage siden. |
| `to` | Nej | Intervalslut, `YYYY-MM-DD`. Standard er i dag. |
| `metrics` | Nej | Komma-separeret liste fra `sent`, `ai_sent`, `human_sent`, `delivered`, `read`, `replied`, `booked`, `contact_created`, `credits_spent`. Standard er `sent,replied`. En ukendt metrik returnerer `400`. |
| `group_by` | Nej | Komma-separeret liste af op til to dimensioner fra `date`, `campaign`, `channel`, `agent`, `number`. `date` accepteres, men har ingen effekt — hvert svar indeholder allerede tidsaksen. Udelad for en enkelt kontodækkende serie. |
| `granularity` | Nej | `day` (standard), `week` eller `month`. Uge-buckets starter mandag, måneds-buckets den 1. |
| `limit` | Nej | Hvor mange serier der skal returneres, før resten kollapser til `other_bucket`, 1–50. Standard er 12. |
| `campaign_id` | Nej | Tæl kun aktivitet, der tilhører denne kampagne. Ældre; foretræk `agent_id`. |
| `agent_id` | Nej | Tæl kun aktivitet, der tilhører denne AI-agent. |
| `channel` | Nej | Tæl kun aktivitet på denne kanal, for eksempel `whatsapp`. |

Dette slutpunkts datointerval er begrænset til **92 dage** (strammere end 366-dages grænsen, der bruges andre steder på denne side).

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

**Svar**

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

**Feltnoter:**

- `key` — identiteten på én serie. Kun nøglerne for de anmodede `group_by`-dimensioner er til stede; en dimension, hvis værdi er ukendt for en række (en besked uden kampagne, en hændelse uden kanal), kommer tilbage som `null` i stedet for at blive droppet, så serier stadig summerer op til totalerne.
- `other_bucket` — `null` når intet blev kollapset.
- Dette slutpunkt returnerer `503` med `"error_code": "analytics_unavailable"`, når rapporteringsdatabasen ikke kan svare for din konto, i stedet for en `200` fuld af nuller — en nulstillet graf ville blive læst som fakta.

---

## Samtaleresultater

Returnerer hvordan samtaler sluttede over et datointerval: en daglig tælling for hvert resultat-tag, som AI'en tildelte, plus intervaltotaler for svar, bookinger, overdragelser til et menneske og samtaler, som AI'en aldrig klassificerede.

`GET /analytics/outcomes`

Angiv `group_by=tag` for at kollapse tidsaksen og kun få intervaltotaler pr. tag — i den tilstand er `labels` tom, og hvert tags `counts`-array er tomt, mens `total` stadig er udfyldt.

| Parameter | Påkrævet | Beskrivelse |
|---|---|---|
| `from` | Nej | Områdestart, `YYYY-MM-DD`. Standard er for 30 dage siden. |
| `to` | Nej | Områdeslut, `YYYY-MM-DD`. Standard er i dag. |
| `campaign_id` | Nej | Tæl kun samtaler med kontakter, der i øjeblikket er i denne kampagne. Legacy; foretræk `agent_id`. |
| `agent_id` | Nej | Tæl kun resultater, der tilhører denne AI-agent. |
| `group_by` | Nej | `date` (standard) beholder optællinger pr. dag; `tag` samler til områdets totaler. |

Dette endpunkts datointerval er begrænset til **92 dage**.

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

**Svar**

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

**Feltnoter:**

- `by_tag[].tag` — `null` for samtaler, som AI'en aldrig tildelte et resultat-tag.
- `totals.human_alerted` — samtaler overdraget til et menneske; dette skrives ved hver overdragelse og blev tidligere ikke vist af noget endpunkt.
- Samme `503`/`analytics_unavailable`-holdning som Metric-serien, når rapporteringsdatabasen ikke kan svare.

---

## Dashboard-indsigt

Returnerer den fulde dashboard-nyttelast for et datointerval i ét kald: et heatmap for svarprocent pr. ugedag og time, kampagne-ranglisten, volumen pr. kanal, nøjagtige totaler pr. forbindelse, opdeling af metrikker pr. dag (konto-dækkende, pr. kanal og pr. nummer), hvor kontakter kommer fra, svartid i indbakken og et feed med nylig aktivitet. Dette er den mest omfattende rapporteringsnyttelast på API'et — den driver dashboardet direkte i appen.

`GET /analytics/dashboard-insights`

| Parameter | Påkrævet | Beskrivelse |
|---|---|---|
| `startDate` | Ja | Områdestart, `YYYY-MM-DD`. |
| `endDate` | Ja | Områdeslut, `YYYY-MM-DD`. |
| `campaignId` | Nej | Inkluder kun aktivitet, der tilhører denne kampagne (`campaign_id` accepteres også). Legacy; foretræk `agent_id`. |
| `agent_id` | Nej | Inkluder kun aktivitet, der tilhører denne AI-agent (`agentId` accepteres også). Under et agent-scope bygges kampagne-ranglisten kun ud fra denne agents aktivitet. |

Dette endpunkt bruger `startDate`/`endDate` (ikke `from`/`to`), fordi det deler implementering med dashboardet i appen. Intervallet er begrænset til 92 dage og bliver **beskåret, ikke afvist**, hvis det er bredere.

> **Null betyder utilgængelig, ikke nul.** Flere blokke (`numberStats`, `channelDailySeries`, `metricDailyBreakdown`, `contactsByCountry`) beregnes ud fra rapporteringsdatabasen og returneres som `null`, når den ikke kan svare for din konto. Gengiv ikke en `null`-blok som et tomt diagram.

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

**Svar** (forkortet — denne nyttelast er stor; se [API-reference](reference.md) for det fulde skema)

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

**Feltnoter:**

- `heatmap.buckets[].weekday` — `0` er søndag til `6` er lørdag.
- `numberStats`, `channelDailySeries`, `metricDailyBreakdown`, `contactsByCountry`, `ai_human_split` — hver især uafhængigt `null`, når rapporteringsdatabasen er utilgængelig for din konto; alle andre blokke returneres stadig.

---

## AI-indsigt for dashboard

Returnerer tre korte, AI-skrevne indsigter om kontoens beskeder over et datointerval: én sejr, én ting at holde øje med og ét tip — sætninger, du kan indsætte direkte i en rapport i stedet for tal, som du stadig selv skal fortolke. Genereret udelukkende ud fra kontoens egne beskedmetrikker.

`GET /analytics/dashboard-ai-insights`

| Parameter | Påkrævet | Beskrivelse |
|---|---|---|
| `startDate` | Ja | Områdestart, `YYYY-MM-DD`. |
| `endDate` | Ja | Områdeslut, `YYYY-MM-DD`. |

Dette slutpunkt er konto-dækkende — det kræver ikke kampagne- eller agent-omfang.

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

**Svar**

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

Manglende `startDate` eller `endDate` returnerer `400`.

---

## Tidslinje for enhedsaktivitet

Returnerer en enkelt kontakts, aftales eller opgaves aktivitet som én tidslinje, nyeste først: hvad skete der og hvornår, på tværs af beskeder, aftaler, noter og statusændringer. Brug det til at besvare "hvad er der sket med denne person" uden at skulle sammensætte flere listeslutpunkter.

`GET /analytics/entity-activity`

| Parameter | Påkrævet | Beskrivelse |
|---|---|---|
| `entityType` | Ja | `contact`, `deal` eller `task`. |
| `entityId` | Ja | ID på den post, hvis tidslinje der skal returneres. |

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

**Svar**

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

Et manglende eller ugyldigt `entityType`/`entityId` returnerer `400`. En enhed, der ikke findes på din konto, returnerer `404`, så andre kontos id'er forbliver umulige at gætte.

---

## Aggregerede begivenhedstællinger (legacy)

Returnerer de samme aggregerede begivenhedstællinger som [Beskedvolumen-oversigt](#message-volume-summary), men i camelCase-format (`contactCreated` i stedet for `contact_created`, `byDate` i stedet for `by_date`), som nogle ældre integrationer er bygget op omkring. Foretræk `/analytics/summary` til nye integrationer — dette slutpunkt findes kun, så dashboardet i appen og API'et deler én implementering.

`GET /analytics/aggregate`

| Parameter | Påkrævet | Beskrivelse |
|---|---|---|
| `startDate` | Nej | Områdestart, ISO-dato eller dato-tid. Standard er det samme vindue, som `/analytics/summary` bruger. |
| `endDate` | Nej | Områdeslut, ISO-dato eller dato-tid. |
| `campaignId` | Nej | Tæl kun begivenheder, der tilhører denne kampagne (`campaign_id` accepteres også). Legacy; foretræk `agent_id`. |
| `agent_id` | Nej | Tæl kun begivenheder, der tilhører denne AI-agent (`agentId` accepteres også). |

**cURL**

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

**Svar**

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

---

## Agency-underkonto-rollup


---

## Analytics API-fejl

Analytics-slutpunkter returnerer standardfejl-konvolutten:

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

På et analyseslutpunkt returnerer et ugyldigt datoformat eller et vindue uden for rækkevidde `400`, og et ukendt `campaign_id` eller `agent_id` returnerer `404`. At sende både `campaign_id` og `agent_id` på et slutpunkt, der accepterer begge, er også en `400` — send højst én. De PG-specifikke rapporteringsslutpunkter (Metrik-serier, Samtaleudfald, Agency-rollup) returnerer `503` med `"error_code": "analytics_unavailable"` i stedet for en `200` fuld af nuller, når rapporteringsdatabasen ikke kan svare for din konto — prøv igen kort efter. De delte koder, som ethvert slutpunkt kan returnere — `401`, `403` (din plan inkluderer ikke API-adgang, eller på bureau-rollup, din konto er ikke Agency/Dev), `429` (rate limit) og `500` — er angivet med vejledning til genforsøg i [Fejl & Sidetal](errors-and-pagination.md).

---

## Næste skridt

- [Godkendelse](authentication.md) — de fire måder at godkende en anmodning på.
- [Fejl og hastighedsbegrænsninger](errors-and-pagination.md) — statuskoder og grænsen på 300 anmodninger/min.
- [Kampagne-API](campaigns.md) — de kampagner, som disse tal kan filtreres efter.
