---
title: "Aggregate call volume, talk time, and spend over one or more date windows"
method: GET
path: "/v1/calls/stats"
---

# Aggregate call volume, talk time, and spend over one or more date windows

`GET /v1/calls/stats`

## Request

- Base URL: `https://api.skysay.ai`
- URL: `https://api.skysay.ai/v1/calls/stats`
- Auth: HTTP bearer

Aggregation runs in SQL over the whole call history for the organization/project, not just a bounded list page, so the figures stay exact however long that history grows. Pass organization_id (and optionally project_id) as query parameters the same way GET /v1/calls does. window is repeated, each in the form <key>:<since-timestamp> (an RFC3339 UTC timestamp); at least one is required and at most 8 may be requested in one call. until is an optional exclusive upper bound (RFC3339 UTC, defaults to now) shared by every window. Pass agent_window naming one of the requested window keys to additionally receive a per-agent breakdown over that one window. That breakdown is a bounded page ordered by agent_id: check agents_has_more and continue with agent_after=<agents_next_cursor> rather than reading one page as the organization's whole agent list. The window totals themselves are never truncated -- they are aggregated in SQL over the entire history in scope.

## Query parameters

- `organization_id` string, required
- `project_id` string
- `until` string, date-time
- `window` string[], required
- `agent_window` string
- `agent_limit` integer
- `agent_after` string

## Response `200`

Call stats

- CallStats
  - `agent_window` string: Present only when you requested one.
  - `agents` CallStatsAgent[]: Present only when agent_window was requested: one bounded page of agents that have placed or received a call in this scope, ordered by agent_id. Read agents_has_more before treating it as the whole set.
    - `agent_id` string, required
    - `calls` integer, required: Calls for this agent within agent_window.
    - `last_call_at` string, date-time, required: Most recent call for this agent across the whole history, not just agent_window.
    - `spend_minor` integer, required: Same estimated_cost_minor sum as CallStatsWindow.spend_minor, scoped to this agent within agent_window.
  - `agents_has_more` boolean: Present only when agent_window was requested. True when the organization has more agents than this page holds; the page is NOT the whole set unless this is false.
  - `agents_limit` integer: Present only when agent_window was requested: the page size actually applied, after clamping.
  - `agents_next_cursor` string: Present only when agent_window was requested. Non-empty only when agents_has_more is true: pass it as agent_after to continue. Empty string on the last page.
  - `agents_returned` integer: Present only when agent_window was requested: agents in this page.
  - `organization_id` string, required
  - `project_id` string, required: Empty string when the request was not scoped to one project.
  - `until` string, date-time, required
  - `windows` object, required: Keyed by the window key you supplied in the repeated window=<key>:<since> query parameter.

## Other responses

- `400`: Missing/duplicate/malformed window, a malformed until, unknown agent_window, or more than 8 windows requested.

---

[API](https://skmtc.dev/skysay/apis/skysay-api.md) · [All operations](https://skmtc.dev/skysay/apis/skysay-api/llms.txt) · [OpenAPI document](https://skmtc.dev/skysay/apis/skysay-api/revisions/148c7e111260?raw)
