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

# Get Aggregated Stats

> Get call volume, pickup rate, duration, and transfers across agents and campaigns for a date range

**What it does:** Returns **aggregated** call metrics for a date range: total calls, connected calls, pickup rate, average duration, and transfers to a human agent. You can bucket results by hour, day, week, or month, split them by agent, campaign, or both, and filter by agent, campaign, call direction, or call status.

It is built for dashboards and operational reporting. You get the totals directly instead of paging through [Get Conversation Logs](/Platform/Get_Conversation_Logs) and counting calls yourself.

**You need:** An API key with the `conversations` permission that belongs to a user with the `org_admin` or `developer` role. To filter by agent, get `botId` values from [List Agents](/Platform/List_Agents).

<Tip>
  To get the outcome or transcript of a **single** call, use [Get Conversation Statistics](/Platform/Get_Conversation_Stats) (`GET /v1/conversations/{conversationId}/stats`). This endpoint returns totals only. It does not return per-call data.
</Tip>

<Note>
  Only **production** calls are counted. Calls in `development` or `staging` are excluded, and there is no `environment` parameter.
</Note>

## Required Permission

`conversations`

## Required Role

`org_admin` or `developer`. API keys that belong to any other role, such as QA, receive `403`.

## Request Body

| Field | Type | Required | Description |
| - | - | - | - |
| `startDate` | string | Yes | First day of the range, `YYYY-MM-DD`. Starts at 00:00:00 IST. |
| `endDate` | string | Yes | Last day of the range, `YYYY-MM-DD`. Ends at 23:59:59 IST. Must be on or after `startDate`. Maximum span: 93 days. |
| `granularity` | string | No | Time bucket: `hour`, `day`, `week`, `month`, or `total`. Default: `total`. |
| `groupBy` | array of strings | No | Split results by `botId`, `campaignId`, or both. Maximum 2 values. |
| `filter.botId` | string \| array | No | Count only calls handled by these agents. |
| `filter.campaignId` | string \| array | No | Count only calls from these campaigns. |
| `filter.type` | string | No | Call direction, for example `Inbound` or `Outbound`. |
| `filter.callStatus` | string \| array | No | Telephony status, for example `ANSWERED`, `NO ANSWER`, `BUSY`, `FAILED`. Use `"NA"` to match calls with no status recorded. |
| `pageNo` | integer | No | Page number, 1-based. Default: `1`. |
| `pageSize` | integer | No | Rows per page, `1`–`500`. Default: `100`. |

## Minimum working example

```bash theme={null}
curl -X POST "https://api.inya.ai/platform/v1/conversations/stats" \
  -H "x-api-key: <your_api_key>" \
  -H "Content-Type: application/json" \
  -d '{
    "startDate": "2026-03-18",
    "endDate": "2026-03-19",
    "granularity": "day"
  }'
```

This request returns one row per day, totalled across all agents and campaigns. If you omit `granularity`, you get a single row covering the whole range.

## How results are shaped

Three request fields decide what comes back:

```text theme={null}
filter       →  which calls are counted        (agent, campaign, direction, status)
granularity  →  how time is bucketed            (hour / day / week / month / total)
groupBy      →  how each bucket is split         (by agent, by campaign, or both)
```

Each row in `data` is one **time bucket × group** combination. For example, `granularity: "day"` over 7 days with `groupBy: ["botId"]` and 3 active agents returns up to 21 rows.

### Time buckets (`granularity`)

| Value | Time field on each row | Example label |
| - | - | - |
| `hour` | `date` | `"2026-03-18T14:00"` |
| `day` | `date` | `"2026-03-18"` |
| `week` | `week` | `"16-03-2026 to 22-03-2026"` |
| `month` | `month` | `"2026-03"` |
| `total` (default) | none | One row per group for the whole range |

All labels are in IST.

<Note>
  The `week` label uses `DD-MM-YYYY`. The other labels use `YYYY-MM-DD`, so parse week labels separately.
</Note>

### Grouping (`groupBy`)

| `groupBy` | You get |
| - | - |
| omitted | One row per time bucket, across all agents and campaigns |
| `["botId"]` | One row per agent, with `botId` and `botName` |
| `["campaignId"]` | One row per campaign. Calls that are not part of a campaign are grouped under `"no_campaign"`. |
| `["botId", "campaignId"]` | One row per agent and campaign pair |

### Filters

Each filter field accepts a single value or an array. Within an array, a call matches if it matches **any** of the values. Across fields, a call must match **all** of the filters. You can use any filter with any `groupBy`.

```json theme={null}
"filter": {
  "botId": ["fb79920229d144608ebf665a10e50275", "a3c1e0d9b2f84f6e9c7d5b4a3f2e1d0c"],
  "type": "Outbound",
  "callStatus": ["ANSWERED", "NO ANSWER"]
}
```

This filter counts outbound calls from either agent whose status is `ANSWERED` or `NO ANSWER`.

### Metrics on every row

| Field | Plain English | Use it for |
| - | - | - |
| `totalCalls` | How many calls matched? | Volume trends, capacity planning |
| `connected` | How many were picked up? (`callStatus` is `ANSWERED`) | Reach |
| `pickupRate` | `connected ÷ totalCalls`, as a decimal (`0.764` = 76.4%) | Comparing campaigns, best time to call |
| `avgDurationSec` | Average call length in seconds | Engagement, cost estimates |
| `callTransfers` | Calls handed off to a human agent | Escalation tracking |

## Response

### Success (200)

Response to the [minimum working example](#minimum-working-example):

```json theme={null}
{
  "status": "success",
  "requestId": "c3d4e5f6-a7b8-9012-cdef-345678901234",
  "message": "Conversation stats retrieved successfully.",
  "response": {
    "startDate": "2026-03-18",
    "endDate": "2026-03-19",
    "granularity": "day",
    "timezone": "IST",
    "groupBy": null,
    "pageNo": 1,
    "pageSize": 100,
    "totalCount": 2,
    "totalPages": 1,
    "data": [
      {
        "date": "2026-03-18",
        "totalCalls": 1402,
        "connected": 1071,
        "pickupRate": 0.764,
        "avgDurationSec": 137,
        "callTransfers": 33
      },
      {
        "date": "2026-03-19",
        "totalCalls": 1455,
        "connected": 1108,
        "pickupRate": 0.762,
        "avgDurationSec": 137,
        "callTransfers": 35
      }
    ]
  }
}
```

## All response fields

### `response`

| Field | Type | Description |
| - | - | - |
| `startDate` | string | Echo of the request. |
| `endDate` | string | Echo of the request. |
| `granularity` | string | Bucket size applied. `total` if you omitted it. |
| `timezone` | string | Always `"IST"`. All dates and labels use this timezone. |
| `groupBy` | array \| null | Dimensions applied, or `null` when ungrouped. |
| `pageNo` | integer | Current page. |
| `pageSize` | integer | Rows per page. |
| `totalCount` | integer | Total **rows** across all pages. This is not the total number of calls. |
| `totalPages` | integer | Total pages at the current `pageSize`. |
| `data` | array | Result rows. See below. |

### Each row in `data`

| Field | Type | Present when | Description |
| - | - | - | - |
| `date` | string | `granularity` is `hour` or `day` | Bucket label: `YYYY-MM-DD` or `YYYY-MM-DDTHH:00`. |
| `week` | string | `granularity` is `week` | Week range: `DD-MM-YYYY to DD-MM-YYYY`. |
| `month` | string | `granularity` is `month` | Month label: `YYYY-MM`. |
| `botId` | string | `groupBy` includes `botId` | Agent for this row. |
| `botName` | string | `groupBy` includes `botId` | Agent display name. |
| `campaignId` | string | `groupBy` includes `campaignId` | Campaign for this row, or `"no_campaign"`. |
| `totalCalls` | integer | Always | Calls matching the query in this bucket and group. |
| `connected` | integer | Always | Calls with `callStatus` = `ANSWERED`. |
| `pickupRate` | number | Always | `connected ÷ totalCalls`, from `0` to `1`. |
| `avgDurationSec` | number | Always | Average call duration in seconds. |
| `callTransfers` | integer | Always | Calls transferred to a human agent. |

## More examples

### Outbound calls by agent and campaign

```bash theme={null}
curl -X POST "https://api.inya.ai/platform/v1/conversations/stats" \
  -H "x-api-key: <your_api_key>" \
  -H "Content-Type: application/json" \
  -d '{
    "startDate": "2026-03-18",
    "endDate": "2026-03-18",
    "granularity": "day",
    "groupBy": ["botId", "campaignId"],
    "filter": { "type": "Outbound" }
  }'
```

```json theme={null}
{
  "status": "success",
  "requestId": "d4e5f6a7-b8c9-0123-def4-567890123456",
  "message": "Conversation stats retrieved successfully.",
  "response": {
    "startDate": "2026-03-18",
    "endDate": "2026-03-18",
    "granularity": "day",
    "timezone": "IST",
    "groupBy": ["botId", "campaignId"],
    "pageNo": 1,
    "pageSize": 100,
    "totalCount": 2,
    "totalPages": 1,
    "data": [
      {
        "date": "2026-03-18",
        "botId": "fb79920229d144608ebf665a10e50275",
        "botName": "Payment Reminder",
        "campaignId": "camp_9182",
        "totalCalls": 1200,
        "connected": 920,
        "pickupRate": 0.767,
        "avgDurationSec": 145,
        "callTransfers": 28
      },
      {
        "date": "2026-03-18",
        "botId": "fb79920229d144608ebf665a10e50275",
        "botName": "Payment Reminder",
        "campaignId": "no_campaign",
        "totalCalls": 202,
        "connected": 151,
        "pickupRate": 0.748,
        "avgDurationSec": 92,
        "callTransfers": 5
      }
    ]
  }
}
```

### Quarter total for one agent

```bash theme={null}
curl -X POST "https://api.inya.ai/platform/v1/conversations/stats" \
  -H "x-api-key: <your_api_key>" \
  -H "Content-Type: application/json" \
  -d '{
    "startDate": "2026-01-01",
    "endDate": "2026-03-31",
    "granularity": "total",
    "filter": { "botId": "fb79920229d144608ebf665a10e50275" }
  }'
```

```json theme={null}
{
  "status": "success",
  "requestId": "e5f6a7b8-c9d0-1234-ef56-789012345678",
  "message": "Conversation stats retrieved successfully.",
  "response": {
    "startDate": "2026-01-01",
    "endDate": "2026-03-31",
    "granularity": "total",
    "timezone": "IST",
    "groupBy": null,
    "pageNo": 1,
    "pageSize": 100,
    "totalCount": 1,
    "totalPages": 1,
    "data": [
      {
        "totalCalls": 42560,
        "connected": 31920,
        "pickupRate": 0.75,
        "avgDurationSec": 128,
        "callTransfers": 312
      }
    ]
  }
}
```

## Pagination

Pagination works on **rows**, not calls. Hourly buckets over a long range, especially with grouping, can produce more than 500 rows. Increase `pageNo` until it equals `totalPages`.

## Edge cases

| Scenario | What happens |
| - | - |
| `startDate` equals `endDate` | Valid. Returns that single day. |
| Range longer than 93 days | `400`. Split it into several requests and combine the results (see below). |
| Call is not part of a campaign | When grouping by campaign, it appears under `campaignId: "no_campaign"`. |
| `filter.callStatus` set to `"ANSWERED"` | `pickupRate` is always `1`, because only answered calls are counted. Leave `callStatus` unset to measure pickup rate. |
| Your business day is not on IST | Dates are always interpreted in IST, and there is no timezone parameter. Request `granularity: "hour"` and re-bucket the rows on your side. |

### Combining results across pages or requests

You can add up `totalCalls`, `connected`, and `callTransfers` directly. Do **not** average `pickupRate` or `avgDurationSec` across rows. Instead:

* `pickupRate` = sum of `connected` ÷ sum of `totalCalls`
* `avgDurationSec` = a weighted average across rows, not a simple average of the row values

## Errors

| Status | Condition | Message |
| - | - | - |
| `400` | `startDate` is after `endDate` | `'startDate' must be before 'endDate'.` |
| `400` | Range exceeds 93 days | `Date range exceeds the maximum allowed span of 93 days.` |
| `400` | Date is not `YYYY-MM-DD` | `Invalid date format. Expected: YYYY-MM-DD.` |
| `401` | API key missing or invalid | See [Authentication](/Platform/platform-introduction#authentication). |
| `403` | Key does not have the required role | `Access denied. Only org_admin and developer roles can access call statistics.` |
| `422` | Invalid `granularity` | `Input should be 'hour', 'day', 'week', 'month' or 'total'.` |
| `422` | Invalid `groupBy` value | `Input should be 'botId' or 'campaignId'.` |
| `422` | More than 2 `groupBy` values | `Maximum 2 groupBy dimensions allowed.` |
| `422` | `pageSize` above 500 | `Input should be less than or equal to 500.` |
| `422` | `startDate` or `endDate` missing | `Field required.` |
| `429` | Rate limit exceeded | Retry after the interval in the `Retry-After` header. |
| `500` | Server error | `An unexpected error occurred while computing call statistics.` |

**400 Bad Request**

```json theme={null}
{
  "status": "failure",
  "requestId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "message": "Date range exceeds the maximum allowed span of 93 days."
}
```

**403 Forbidden**

```json theme={null}
{
  "status": "failure",
  "requestId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "message": "Access denied. Only org_admin and developer roles can access call statistics."
}
```

<Note>
  Save the `requestId` from every response. You will need it if you contact Gnani support to trace a specific request.
</Note>


## OpenAPI

````yaml agents_openapi.yml POST /v1/conversations/stats
openapi: 3.0.3
info:
  title: Platform Agents API
  description: API endpoints for creating, managing, and interacting with voice agents
  version: 2.1.0
servers:
  - url: https://api.inya.ai/platform
    description: Production server
security:
  - ApiKeyAuth: []
tags:
  - name: Agents
    description: Agent management operations
  - name: AgentFAQ
    description: Agent FAQ management
  - name: AgentCallTriggers
    description: Outbound call triggers
  - name: ChatSDK
    description: Chat Widget configuration
  - name: Conversations
    description: Conversation logs, statistics, and audio
paths:
  /v1/conversations/stats:
    post:
      tags:
        - Conversations
      summary: Get Aggregated Stats
      description: >-
        Retrieve aggregated call statistics (volume, pickup rate, average
        duration, transfers) for production conversations in a date range. Dates
        are interpreted in IST. Requires the org_admin or developer role.
      operationId: getAggregatedStats
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - startDate
                - endDate
              properties:
                startDate:
                  type: string
                  format: date
                  description: First day of the range (YYYY-MM-DD), from 00:00:00 IST.
                  example: '2026-03-18'
                endDate:
                  type: string
                  format: date
                  description: >-
                    Last day of the range (YYYY-MM-DD), until 23:59:59 IST. Must
                    be on or after startDate. Maximum span 93 days.
                  example: '2026-03-19'
                granularity:
                  type: string
                  enum:
                    - hour
                    - day
                    - week
                    - month
                    - total
                  default: total
                  description: Time bucket size.
                groupBy:
                  type: array
                  maxItems: 2
                  description: Split results by agent, campaign, or both.
                  items:
                    type: string
                    enum:
                      - botId
                      - campaignId
                filter:
                  type: object
                  description: >-
                    Narrows which calls are counted. Each field accepts a single
                    value or an array.
                  properties:
                    botId:
                      description: One or more agent IDs.
                      oneOf:
                        - type: string
                        - type: array
                          items:
                            type: string
                    campaignId:
                      description: One or more campaign IDs.
                      oneOf:
                        - type: string
                        - type: array
                          items:
                            type: string
                    type:
                      type: string
                      description: Call direction, e.g. Inbound or Outbound.
                      example: Outbound
                    callStatus:
                      description: >-
                        Telephony status, e.g. ANSWERED, NO ANSWER, BUSY,
                        FAILED. Use "NA" for calls with no status recorded.
                      oneOf:
                        - type: string
                        - type: array
                          items:
                            type: string
                pageNo:
                  type: integer
                  minimum: 1
                  default: 1
                  description: Page number (1-based).
                pageSize:
                  type: integer
                  minimum: 1
                  maximum: 500
                  default: 100
                  description: Rows per page.
            examples:
              dailyTotals:
                summary: Daily totals
                value:
                  startDate: '2026-03-18'
                  endDate: '2026-03-19'
                  granularity: day
              byAgentAndCampaign:
                summary: Outbound calls by agent and campaign
                value:
                  startDate: '2026-03-18'
                  endDate: '2026-03-18'
                  granularity: day
                  groupBy:
                    - botId
                    - campaignId
                  filter:
                    type: Outbound
              quarterTotalForAgent:
                summary: Quarter total for one agent
                value:
                  startDate: '2026-01-01'
                  endDate: '2026-03-31'
                  granularity: total
                  filter:
                    botId: fb79920229d144608ebf665a10e50275
      responses:
        '200':
          description: Aggregated statistics retrieved successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: success
                  requestId:
                    type: string
                  message:
                    type: string
                    example: Conversation stats retrieved successfully.
                  response:
                    type: object
                    properties:
                      startDate:
                        type: string
                        format: date
                      endDate:
                        type: string
                        format: date
                      granularity:
                        type: string
                      timezone:
                        type: string
                        description: Always IST.
                        example: IST
                      groupBy:
                        type: array
                        nullable: true
                        items:
                          type: string
                      pageNo:
                        type: integer
                      pageSize:
                        type: integer
                      totalCount:
                        type: integer
                        description: Total rows across all pages (not total calls).
                      totalPages:
                        type: integer
                      data:
                        type: array
                        description: One row per time bucket and group combination.
                        items:
                          type: object
                          properties:
                            date:
                              type: string
                              description: >-
                                Present when granularity is hour or day.
                                YYYY-MM-DD or YYYY-MM-DDTHH:00.
                            week:
                              type: string
                              description: >-
                                Present when granularity is week. DD-MM-YYYY to
                                DD-MM-YYYY.
                            month:
                              type: string
                              description: Present when granularity is month. YYYY-MM.
                            botId:
                              type: string
                              description: Present when groupBy includes botId.
                            botName:
                              type: string
                              description: Present when groupBy includes botId.
                            campaignId:
                              type: string
                              description: >-
                                Present when groupBy includes campaignId.
                                "no_campaign" for calls without a campaign.
                            totalCalls:
                              type: integer
                              description: >-
                                Calls matching the query in this bucket and
                                group.
                            connected:
                              type: integer
                              description: Calls with callStatus ANSWERED.
                            pickupRate:
                              type: number
                              description: connected / totalCalls as a decimal (0 to 1).
                            avgDurationSec:
                              type: number
                              description: Average call duration in seconds.
                            callTransfers:
                              type: integer
                              description: Calls transferred to a human agent.
              example:
                status: success
                requestId: c3d4e5f6-a7b8-9012-cdef-345678901234
                message: Conversation stats retrieved successfully.
                response:
                  startDate: '2026-03-18'
                  endDate: '2026-03-19'
                  granularity: day
                  timezone: IST
                  groupBy: null
                  pageNo: 1
                  pageSize: 100
                  totalCount: 2
                  totalPages: 1
                  data:
                    - date: '2026-03-18'
                      totalCalls: 1402
                      connected: 1071
                      pickupRate: 0.764
                      avgDurationSec: 137
                      callTransfers: 33
                    - date: '2026-03-19'
                      totalCalls: 1455
                      connected: 1108
                      pickupRate: 0.762
                      avgDurationSec: 137
                      callTransfers: 35
        '400':
          description: >-
            Invalid dates (bad format, startDate after endDate, or range over 93
            days)
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: failure
                  requestId:
                    type: string
                  message:
                    type: string
                    example: Date range exceeds the maximum allowed span of 93 days.
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          description: >-
            Request body failed validation (invalid granularity or groupBy, more
            than 2 groupBy values, pageSize over 500, or missing dates)
        '500':
          $ref: '#/components/responses/ServerError'
      security:
        - ConversationsApiKeyAuth: []
components:
  responses:
    Forbidden:
      description: Permission denied
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    ServerError:
      description: Internal server error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
  schemas:
    ErrorResponse:
      type: object
      properties:
        status:
          type: string
          example: failure
        requestId:
          type: string
          example: a1b2c3d4-e5f6-7890-abcd-ef1234567890
        message:
          type: string
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: x-api-key
      description: API key with 'agents' permission
    ConversationsApiKeyAuth:
      type: apiKey
      in: header
      name: x-api-key
      description: API key with 'conversations' permission

````

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