---
title: "Query analytics metrics"
method: GET
path: "/analytics/query"
tags: ["Analytics"]
---

# Query analytics metrics

`GET /analytics/query`

## Request

- Base URL: `https://api.commonroom.io/api/v2`
- URL: `https://api.commonroom.io/api/v2/analytics/query`
- Auth: HTTP bearer
- TypeScript: <https://skmtc.dev/commonroom/apis/common-room-api-v2/docs/analytics/query/get.ts> (a function with typed inputs; its response is checked against the schema)

Computes catalog metrics for the reps on a set of teams, as one total or broken down by
`groupBy`, over a window (`range`, or `start` and `end`) or on a date (`asOf`, snapshot
metrics only). Every request names who it covers with `personaIds` (teams, including their
sub-teams), `memberIds` (reps), or both. Admins can query every team, and managers with Editor
permission the teams they manage and their sub-teams. A team or rep outside the caller's scope
fails the whole request.

`groupBy=action` lists the actions behind `repAction` metrics, newest first, in pages: pass
`meta.nextCursor` back as `cursor` for the next page. Other results come whole in one response.
The token must grant `analytics:read` (or the encompassing `read` scope); action rows carry
contact emails and Salesforce ids, so `groupBy=action` also needs `contacts:read`.

Example request, completed tasks per rep on two teams over the last 7 days, as in the app:

```sh
curl --get 'https://api.commonroom.io/api/v2/analytics/query' \
  --header "Authorization: Bearer $COMMON_ROOM_API_TOKEN" \
  --data-urlencode 'metrics=tasksMarkedDone' \
  --data-urlencode 'groupBy=rep' \
  --data-urlencode 'personaIds=p_31' \
  --data-urlencode 'personaIds=p_32' \
  --data-urlencode 'range=P7D' \
  --data-urlencode 'timeZone=America/Los_Angeles'
```

## Query parameters

- `metrics` string[], required
- `groupBy` string[]
- `range` string
- `start` string, date-time
- `end` string, date-time
- `asOf` string, date
- `timeZone` string
- `personaIds` string[]
- `memberIds` string[]
- `segmentIds` string[]
- `sepDestinations` string[]
- `repMetrics` string[]
- `sort` string
- `direction` 'asc' | 'desc'
- `limit` integer
- `cursor` string

## Response `200`

OK

- AnalyticsQueryResponse
  - `success` true, required
  - `data` object[], required: One object per row: the grouped dimensions' columns, then the requested metrics, then `snapshotDate` when a snapshot metric is requested. Each value is computed for the requested grouping, so adding rows doesn't reproduce a coarser total; request the coarser `groupBy` instead.
  - `meta` object, required
    - `entity` string, required: The population the metrics describe, `rep` or `repAction`.
    - `groupBy` string[], required
    - `time` object, required: The resolved window (`start`, `end` and `timeZone`), or `asOf`.
      - `start` string, date-time
      - `end` string, date-time
      - `timeZone` string
      - `asOf` string, date
    - `scope` object, required
      - `teams` object[], required: The teams the request covers.
        - `id` string, required
        - `name` string, required
      - `repCount` integer, required: The number of reps counted.
    - `columns` AnalyticsColumn[], required: One entry per row column, in row order.
      - `name` string, required: The column's key in each row.
      - `role` string, required: `dimension` for the columns that identify a row, `attribute` for columns that describe its dimension, and `metric` for computed values.
      - `type` string: Set on `timestamp`, `date` and `list` columns. New values may be added.
      - `unit` string: Metrics only. What one unit counts, such as `task`, `record`, `contact` or `rep`.
      - `temporality` string: Metrics only. `window` counts within the window. `snapshot` is the state at the latest daily snapshot up to the window's end, or on `asOf`; the snapshot's date is in the row's `snapshotDate`.
      - `nullable` boolean
    - `rowCount` integer, required
    - `totalRows` integer, required: Rows before `limit` was applied; for action rows, every row across the pages.
    - `nextCursor` string: Action rows only, when more pages follow. Pass it back as `cursor` with the same parameters.
    - `notes` string[], required: Caveats about the result, such as a missing snapshot that leaves snapshot metrics null.

## Other responses

- `400`: `invalid_parameters`: an unknown parameter or metric, a `groupBy` a metric doesn't support, a missing or conflicting time form, neither `personaIds` nor `memberIds`, a malformed or unknown id, a rep not on the requested teams, an invalid `sort`, `limit` or `cursor`, more reps than one request can cover, or more than 5,000 rows. The message says what to change.
- `403`: `insufficient_scope` when the token lacks `analytics:read`, or `contacts:read` with `groupBy=action`. `insufficient_capability` when the caller can't view team reporting, or a requested team or rep is outside their scope; the message lists only the ids the request sent.
- `429`: Rate Limited

---

[API](https://skmtc.dev/commonroom/apis/common-room-api-v2.md) - [All operations](https://skmtc.dev/commonroom/apis/common-room-api-v2/llms.txt) - [OpenAPI document](https://skmtc.dev/commonroom/apis/common-room-api-v2/revisions/865d4d43dadf?raw)
