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

# Analytics Insights

> Conversation-shaped analytics for the Tuco AI iMessage API: channel and direction split, a cadence-step funnel with reply attribution, and per-day/hour series.

<Note>
  The companion to [Analytics](/api-reference/analytics). Where that endpoint answers *"how many messages"*, this one answers *"what happened across the conversation"*.

  Every send is classified by its role in the thread — a **net-new** first touch, a cold **follow-up nudge** (the lead hasn't replied yet), or a **response** (you replied to their reply). Each conversation's first reply is credited to the cadence **step** that earned it, and later inbound messages are counted as **reply-to-reply** turns.

  Roles are computed over each conversation's **entire history**, then counted inside your window — so a step-4 send still reads as step 4 even when you only look at a single day.

  Scope is a single workspace (the one behind your key). Agency roll-ups are not offered here yet.
</Note>

## Authentication

```bash theme={null}
Authorization: Bearer tuco_sk_xxxxxxxxxxxxx
```

## Query parameters

<ParamField query="dateFrom" type="string">Inclusive start of the window — an ISO 8601 timestamp (`2026-08-01T00:00:00Z`) or a calendar day (`2026-08-01`). Date-only bounds cover whole calendar days in the workspace timezone. Defaults to the trailing 30 days.</ParamField>
<ParamField query="dateTo" type="string">Inclusive end of the window — ISO timestamp or `YYYY-MM-DD`.</ParamField>
<ParamField query="lineId" type="string">Restrict to messages sent on a single Tuco line (24-char ObjectId hex).</ParamField>
<ParamField query="source" type="string">Restrict to one attributed origin (`gohighlevel`, `campaign`, `api`, `dashboard`, `autopilot`, `unattributed`, …). The `sources` breakdown always lists every origin so you can switch.</ParamField>
<ParamField query="timezone" type="string">IANA zone to cut days and hours in (e.g. `America/New_York`). Defaults to the workspace timezone. `tz` is accepted as an alias.</ParamField>

***

## Example

<CodeGroup>
  ```bash Last 35 days, one line theme={null}
  curl "https://app.tuco.ai/api/analytics/insights?dateFrom=2026-07-13&dateTo=2026-08-17&lineId=6a550c00d3c70557446422af" \
    -H "Authorization: Bearer tuco_sk_xxxxxxxxxxxxx"
  ```
</CodeGroup>

## Success response (200)

```json theme={null}
{
  "success": true,
  "filter": {
    "lineId": "6a550c00d3c70557446422af",
    "source": null,
    "dateFrom": "2026-07-13T04:00:00.000Z",
    "dateTo": "2026-08-18T03:59:59.999Z",
    "timezone": "America/New_York"
  },
  "insights": {
    "channel": { "attempted": 1986, "imessageDelivered": 948, "smsFallbackSent": 0, "notOnImessage": 1038, "notReached": 1038, "failed": 0, "reached": 948, "imessageReplied": 418, "smsReplied": 0, "totalReplied": 418 },
    "unique": { "attempted": 586, "reached": 254, "notOnImessage": 332, "replied": 148 },
    "cadence": {
      "netNew": 329, "nudge": 491, "response": 480,
      "sentByStep": [329, 154, 137, 85, 115],
      "firstReplyByStep": [149, 14, 23, 9, 6],
      "inboundFirst": 4, "firstReplies": 205, "laterReplies": 484,
      "avgThreadLength": 5.96
    },
    "engagement": { "delivered": 389, "read": 177, "voiceNotes": 150, "attachments": 150, "scheduled": 84, "failed": 13 },
    "conversations": 333,
    "daily": [{ "day": "2026-07-13", "imessageDelivered": 2, "smsFallbackSent": 0, "notReached": 0, "replied": 2, "activeConversations": 2 }],
    "hourly": [{ "hour": 0, "sent": 23, "replied": 10 }],
    "truncated": false
  },
  "sources": [{ "source": "gohighlevel", "sent": 495, "reached": 210 }],
  "explainer": { "netNew": "First outbound message ever sent to a lead …" }
}
```

<ResponseField name="insights.channel" type="object">Delivery-aware split. `attempted` = all sends; `imessageDelivered` = reached over iMessage; `smsFallbackSent` = fell back **and** an SMS was actually dispatched; `notOnImessage` = recipient has no iMessage (status fallback), a list-quality signal distinct from `failed` (technical); `notReached` = notOnImessage with no SMS dispatched (reached nobody); `reached` = delivered + dispatched SMS. Plus `imessageReplied` / `smsReplied` / `totalReplied`.</ResponseField>
<ResponseField name="insights.unique" type="object">Distinct recipients, not message counts: `attempted` = tried, `reached` = a message actually got to, `notOnImessage` = leads never delivered an iMessage (the headline when there is no SMS fallback), `replied` = replied. Reply rate should use `replied / reached` so it's comparable across workspaces regardless of iMessage delivery.</ResponseField>
<ResponseField name="insights.cadence.netNew" type="number">First outbound message ever sent to a lead (their first touch).</ResponseField>
<ResponseField name="insights.cadence.nudge" type="number">Cold follow-up sends — outbound to a lead who has not replied yet (cadence step 2+).</ResponseField>
<ResponseField name="insights.cadence.response" type="number">Outbound sent after the lead had already replied ("I replied to their reply").</ResponseField>
<ResponseField name="insights.cadence.sentByStep" type="number[]">Cold outbound sends by cadence step — index 0..4 = step 1, 2, 3, 4, 5+.</ResponseField>
<ResponseField name="insights.cadence.firstReplyByStep" type="number[]">Each conversation's first reply, credited to the step that earned it (same 1..5+ index).</ResponseField>
<ResponseField name="insights.cadence.firstReplies" type="number">Conversations that opened — one per lead that replied at least once.</ResponseField>
<ResponseField name="insights.cadence.laterReplies" type="number">Reply-to-reply turns — inbound after the conversation had already opened.</ResponseField>
<ResponseField name="insights.cadence.avgThreadLength" type="number">Average messages per conversation touched in the window.</ResponseField>
<ResponseField name="insights.conversations" type="number">Distinct leads with at least one message in the window.</ResponseField>
<ResponseField name="insights.daily" type="object[]">Per-day iMessage delivered / SMS fallback / not-reached / replies, plus that day's distinct `activeConversations` (drives the [day drill-down](/api-reference/endpoint/analytics-conversations)).</ResponseField>
<ResponseField name="insights.hourly" type="object[]">Sent and replies by hour of day (0..23) in the workspace timezone.</ResponseField>
<ResponseField name="insights.engagement" type="object">Delivery/read receipts, voice notes, attachments, scheduled sends.</ResponseField>
<ResponseField name="insights.truncated" type="boolean">`true` when the workspace history was too large to replay for this request; cadence and daily fields are then empty. Narrow the window or filter by line.</ResponseField>
<ResponseField name="sources" type="object[]">Where the sending came from. A message carrying a GoHighLevel location counts as GoHighLevel even when sent through the API. Messages with no marker are reported as `unattributed`.</ResponseField>

***

## Error responses

| Status | When                            |
| ------ | ------------------------------- |
| `401`  | Missing or invalid API key      |
| `500`  | Server error computing insights |
