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

# Get Statistics

> Returns the same numbers as the Statistics page of the app, for any period, with filters and breakdowns.

# Get Statistics

Returns totals for your account and optional breakdowns by day, campaign, agent, disposition or workspace. The numbers are calculated exactly like the Statistics page of the app.

By default: last 7 days, outbound and inbound calls together, timezone `Europe/Paris`. Days are calendar days in the chosen timezone and the end day is included.

## Request

`GET /v1/stats`

### Query Parameters

| Parameter | Type | Required | Description |
| - | - | - | - |
| `period` | string | No | Preset period: `today`, `yesterday`, `this_week`, `last_week`, `this_month`, `last_month`, `last_7_days`, `last_30_days`, `all_time` (default: `last_7_days`) |
| `date_from` | string | No | Custom start day (`YYYY-MM-DD`, included). Cannot be combined with `period` |
| `date_to` | string | No | Custom end day (`YYYY-MM-DD`, included). Defaults to today |
| `timezone` | string | No | Timezone used to cut days, as an IANA name (default: `Europe/Paris`) |
| `direction` | string | No | `all` (default), `outbound` or `inbound` |
| `campaign_id` | string | No | Only count these campaigns. One UUID or several separated by commas (max 50) |
| `agent_id` | uuid | No | Only count calls made or received by this agent |
| `workspace_id` | string | No | Only count this workspace. Use `none` for calls outside any workspace |
| `group_by` | string | No | Breakdowns to include, separated by commas: `day`, `campaign`, `agent`, `disposition`, `workspace` |

## Example

```bash cURL theme={null}
curl -X GET \
  "https://kdjmltmhxvvmiuehafgl.supabase.co/functions/v1/api-gateway/v1/stats?period=last_7_days&group_by=day,campaign,agent,disposition,workspace" \
  -H "Authorization: Bearer rchd_live_xxxxxxxxxxxx"
```

```javascript JavaScript theme={null}
const params = new URLSearchParams({
  period: "last_7_days",
  group_by: "day,campaign,agent,disposition,workspace"
});

const response = await fetch(
  `https://kdjmltmhxvvmiuehafgl.supabase.co/functions/v1/api-gateway/v1/stats?${params}`,
  {
    headers: {
      "Authorization": "Bearer rchd_live_xxxxxxxxxxxx"
    }
  }
);
const { data } = await response.json();
```

```python Python theme={null}
import requests

response = requests.get(
    "https://kdjmltmhxvvmiuehafgl.supabase.co/functions/v1/api-gateway/v1/stats",
    headers={"Authorization": "Bearer rchd_live_xxxxxxxxxxxx"},
    params={
        "period": "last_7_days",
        "group_by": "day,campaign,agent,disposition,workspace"
    }
)
data = response.json()["data"]
```

### Custom date range for one agent

```bash cURL theme={null}
curl -X GET \
  "https://kdjmltmhxvvmiuehafgl.supabase.co/functions/v1/api-gateway/v1/stats?date_from=2026-03-01&date_to=2026-03-15&agent_id=u1a2b3c4-...&direction=outbound" \
  -H "Authorization: Bearer rchd_live_xxxxxxxxxxxx"
```

```javascript JavaScript theme={null}
const params = new URLSearchParams({
  date_from: "2026-03-01",
  date_to: "2026-03-15",
  agent_id: "u1a2b3c4-...",
  direction: "outbound"
});

const response = await fetch(
  `https://kdjmltmhxvvmiuehafgl.supabase.co/functions/v1/api-gateway/v1/stats?${params}`,
  { headers: { "Authorization": "Bearer rchd_live_xxxxxxxxxxxx" } }
);
const { data } = await response.json();
```

## Response

**200 OK**

```json theme={null}
{
  "data": {
    "period": {
      "preset": "last_7_days",
      "date_from": "2026-03-14",
      "date_to": "2026-03-21",
      "timezone": "Europe/Paris"
    },
    "filters": {
      "direction": "all",
      "campaign_ids": null,
      "agent_id": null,
      "workspace_id": null
    },
    "totals": {
      "total_calls": 412,
      "sessions": 300,
      "calls_per_session": 1.37,
      "connected_calls": 96,
      "connection_rate": 32.0,
      "conversations": 41,
      "appointments": 9,
      "conversion_rate": 9.4,
      "talk_time_seconds": 9540,
      "avg_talk_time_seconds": 92,
      "voicemails_reached": 38,
      "voicemails_avoided": 71,
      "called_leads": 280,
      "callback_leads": 18,
      "callback_rate": 6.4
    },
    "breakdowns": {
      "day": [
        { "date": "2026-03-20", "total_calls": 75, "sessions": 54, "connected_calls": 18, "connection_rate": 33.3, "conversations": 8, "appointments": 2 }
      ],
      "campaign": [
        { "campaign_id": "c1d2e3f4-...", "campaign_name": "Q1 Outreach", "total_calls": 398, "sessions": 290, "connected_calls": 92 },
        { "campaign_id": null, "campaign_name": "Calls without campaign", "total_calls": 14, "sessions": 10, "connected_calls": 4 }
      ],
      "agent": [
        { "agent_id": "u1a2b3c4-...", "agent_name": "Sophie Bernard", "agent_email": "sophie@company.com", "total_calls": 210 },
        { "agent_id": null, "agent_name": "Unassigned", "agent_email": null, "total_calls": 3 }
      ],
      "workspace": [
        { "workspace_id": "w1x2y3z4-...", "workspace_name": "Paris team", "total_calls": 300 },
        { "workspace_id": null, "workspace_name": "Default workspace", "total_calls": 112 }
      ],
      "disposition": [
        { "disposition": "no-answer", "label_en": "No Answer", "label_fr": "Pas de réponse", "calls": 214, "percentage": 51.9 },
        { "disposition": "appointment-scheduled", "label_en": "Appointment Scheduled", "label_fr": "Rendez-vous pris", "calls": 9, "percentage": 2.2 }
      ]
    }
  }
}
```

**400 Bad Request**

```json theme={null}
{
  "error": {
    "code": "bad_request",
    "message": "Use either period or date_from/date_to, not both."
  }
}
```

> [!NOTE]
>
> The example above is shortened. Each line of the `day`, `campaign`, `agent` and `workspace` breakdowns contains the same metrics as `totals`. A breakdown is only returned when it is requested in `group_by`.

### Top-level Fields

| Field | Type | Description |
| - | - | - |
| `period` | object | The period actually used: `preset` (or `null` for a custom range), `date_from`, `date_to`, `timezone` |
| `filters` | object | The filters actually applied: `direction`, `campaign_ids`, `agent_id`, `workspace_id` |
| `totals` | object | Metrics for everything matching the period and filters |
| `breakdowns` | object | The breakdowns requested in `group_by` |

### Metrics

| Field | Type | Description |
| - | - | - |
| `total_calls` | integer | Every line dialed |
| `sessions` | integer | Dialing attempts. With parallel dialing, several lines dialed together count as one session |
| `calls_per_session` | float | `total_calls / sessions` |
| `connected_calls` | integer | Sessions where a real person was put through to the agent (voicemails and answering machines excluded) |
| `connection_rate` | float | `connected_calls / sessions`, in % |
| `conversations` | integer | Connected calls lasting 60 seconds or more |
| `appointments` | integer | Calls with the `appointment-scheduled` disposition |
| `conversion_rate` | float | `appointments / connected_calls`, in % |
| `talk_time_seconds` | integer | Time spent talking on connected calls |
| `avg_talk_time_seconds` | integer | Average talk time per connected call |
| `voicemails_reached` | integer | Calls that ended on a voicemail (`voicemail`, `voicemail-left`) |
| `voicemails_avoided` | integer | Voicemails or answering machines detected and skipped automatically |
| `called_leads` | integer | Distinct leads called at least once |
| `callback_leads` | integer | Called leads who called back afterwards |
| `callback_rate` | float | `callback_leads / called_leads`, in % |

Rates are percentages rounded to one decimal.

### Breakdowns

| Breakdown | Identifying fields | Notes |
| - | - | - |
| `day` | `date` | One line per calendar day in the chosen timezone |
| `campaign` | `campaign_id`, `campaign_name` | Calls without a campaign appear on a `Calls without campaign` line (`campaign_id: null`) |
| `agent` | `agent_id`, `agent_name`, `agent_email` | Calls without an agent appear on an `Unassigned` line (`agent_id: null`) |
| `workspace` | `workspace_id`, `workspace_name` | Calls outside any workspace appear on a `Default workspace` line (`workspace_id: null`) |
| `disposition` | `disposition`, `label_en`, `label_fr` | Contains `calls` and `percentage` (share of `total_calls`) instead of the full metrics |

Each breakdown adds up to the totals. Inbound calls without a campaign are linked to the campaign the caller belongs to when there is one.

## Errors

| Status | Code | Description |
| - | - | - |
| `400` | `bad_request` | Invalid period, dates, timezone, direction, filter or `group_by` value |
| `401` | `unauthorized` | Missing or invalid API key |
| `500` | `internal` | Unexpected server error |

> [!NOTE]
>
> To get the statistics of a single campaign with its per-agent performance, you can also use [Get Campaign Statistics](https://docs.reachedapp.com/rest-api/campaigns/get-campaign-stats). To go down to individual calls, use [List Call Logs](https://docs.reachedapp.com/rest-api/call-logs/list-call-logs).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.