Skip to main content
POST
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 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.
To get the outcome or transcript of a single call, use Get Conversation Statistics (GET /v1/conversations/{conversationId}/stats). This endpoint returns totals only. It does not return per-call data.
Only production calls are counted. Calls in development or staging are excluded, and there is no environment parameter.

Required Permission

conversations

Required Role

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

Request Body

Minimum working example

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:
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)

All labels are in IST.
The week label uses DD-MM-YYYY. The other labels use YYYY-MM-DD, so parse week labels separately.

Grouping (groupBy)

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.
This filter counts outbound calls from either agent whose status is ANSWERED or NO ANSWER.

Metrics on every row

Response

Success (200)

Response to the minimum working example:

All response fields

response

Each row in data

More examples

Outbound calls by agent and campaign

Quarter total for one agent

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

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

400 Bad Request
403 Forbidden
Save the requestId from every response. You will need it if you contact Gnani support to trace a specific request.

Authorizations

x-api-key
string
header
required

API key with 'conversations' permission

Body

application/json
startDate
string<date>
required

First day of the range (YYYY-MM-DD), from 00:00:00 IST.

Example:

"2026-03-18"

endDate
string<date>
required

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
enum<string>
default:total

Time bucket size.

Available options:
hour,
day,
week,
month,
total
groupBy
enum<string>[]

Split results by agent, campaign, or both.

Maximum array length: 2
Available options:
botId,
campaignId
filter
object

Narrows which calls are counted. Each field accepts a single value or an array.

pageNo
integer
default:1

Page number (1-based).

Required range: x >= 1
pageSize
integer
default:100

Rows per page.

Required range: 1 <= x <= 500

Response

Aggregated statistics retrieved successfully

status
string
Example:

"success"

requestId
string
message
string
Example:

"Conversation stats retrieved successfully."

response
object