---
title: "POST /metric-details-v7: Count calls and sum durations | Trellus Call Data API"
description: "POST https://rpt-2.trellus.ai/metric-details-v7. Calculate counts and numeric sums, optionally filtered or grouped by a reporting column. Authentication, parameters and a request example in cURL, JavaScript and Python."
source: "https://www.trellus.ai/developers/api/metrics"
note: "Text-only copy of the page for AI assistants and agents. Link to the source address, not this file."
site_summary: "https://www.trellus.ai/llms.txt"
---

# Count calls and sum durations

Calculate counts and numeric sums, optionally filtered or grouped by a reporting column.

POST `https://rpt-2.trellus.ai/metric-details-v7`

Send `start` and `selects` in a JSON body. Each select returns a count or sum. A `group_by` value becomes the first cell in each row.

Use `metric-details-v7` for totals across a date range. This avoids treating the limited rows from a list request as a total.

**Authentication:** send `Authorization: Bearer $TRELLUS_API_KEY`. The key inherits the user’s existing permissions. See [Authentication](https://www.trellus.ai/developers/api/authentication).

Request

```bash
curl https://rpt-2.trellus.ai/metric-details-v7 \
  -H "Authorization: Bearer $TRELLUS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "start": 1790812800000000,
    "end": 1791417600000000,
    "selects": [
      { "cnf": [] },
      { "column_name": "duration" },
      { "cnf": [[{ "column_name": "dial_metric.live_duration", "operator": "GE", "value_safe": 30 }]] }
    ],
    "cnf": [[{ "column_name": "conversation_type", "operator": "EQ", "value_safe": 1 }]],
    "group_by": { "column_name": "user_log.disposition" }
  }'
```

```javascript
const response = await fetch("https://rpt-2.trellus.ai/metric-details-v7", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${process.env.TRELLUS_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "start": 1790812800000000,
    "end": 1791417600000000,
    "selects": [
      { "cnf": [] },
      { "column_name": "duration" },
      { "cnf": [[{ "column_name": "dial_metric.live_duration", "operator": "GE", "value_safe": 30 }]] }
    ],
    "cnf": [[{ "column_name": "conversation_type", "operator": "EQ", "value_safe": 1 }]],
    "group_by": { "column_name": "user_log.disposition" }
  }),
});
console.log(await response.text());
```

```python
import os
import requests

response = requests.post(
    "https://rpt-2.trellus.ai/metric-details-v7",
    headers={
        "Authorization": f"Bearer {os.environ['TRELLUS_API_KEY']}",
        "Content-Type": "application/json",
    },
    json={
        "start": 1790812800000000,
        "end": 1791417600000000,
        "selects": [
            { "cnf": [] },
            { "column_name": "duration" },
            { "cnf": [[{ "column_name": "dial_metric.live_duration", "operator": "GE", "value_safe": 30 }]] }
        ],
        "cnf": [[{ "column_name": "conversation_type", "operator": "EQ", "value_safe": 1 }]],
        "group_by": { "column_name": "user_log.disposition" }
    },
)
print(response.text)
```

**Response 200.** JSON arrays in selects order; a group value is prepended when grouped.

## Headers

| Header | Description |
| --- | --- |
| `Authorization` Required | `Bearer $TRELLUS_API_KEY` The API key belonging to your Trellus user. |
| `Content-Type` Required | `application/json` Parameters go in the POST body as JSON. |

## Body parameters

Send a JSON object. [Requests and filters](https://www.trellus.ai/developers/api/requests) explains date units, filter groups and operators; the [field reference](https://www.trellus.ai/developers/api/fields) lists every column path.

| Parameter | Description |
| --- | --- |
| `start` integer, required | Inclusive UTC range start in Unix microseconds. Use Date.parse(ISO_WITH_TIMEZONE) \* 1000 in JavaScript. |
| `end` integer, optional | Exclusive UTC range end in Unix microseconds. Defaults to now. |
| `team_id` string, optional | One permitted team per request; defaults to the key owner’s team. This does not expand access. |
| `cnf` Filter[][], optional | AND of OR filter groups. Defaults to []. Do not use an empty inner group. |
| `selects` Aggregate[], required | Ordered count or sum definitions. Each select can include cnf, column_name, or both. Empty {} is invalid. |
| `group_by` object, optional | Reporting column_name. Prepends the group value to each result row. |
| `group_by.step_size_safe` optional | Bin width in the grouped column units; required for float/time grouping. |
| `group_by.step_start_safe` optional | Bin origin. Required when step_size_safe is supplied. |
| `group_by.step_modulus_safe` optional | Optional repeating period in the grouped column units. |

## Response

| Status | What you receive |
| --- | --- |
| 200 `application/json` | JSON arrays in selects order; a group value is prepended when grouped. |
| Any other status `text/plain` | Read the HTTP status and response text; on 429 honor Retry-After seconds. |

- Top-level request start and end use Unix microseconds. List started_at and started_at filter values use Unix seconds. Durations and transcript offsets are seconds.

More on rows, units and transcripts: [Responses and transcripts](https://www.trellus.ai/developers/api/responses).

## Choose aggregations and groups

Choose aggregations and groups

```
metric-details-v7 uses the reporting column paths from session-list-v6.

Each item in selects produces one numeric result cell:
- { "cnf": [] } counts every session in the time window.
- { "cnf": [[filter]] } counts sessions matching that filter.
- { "column_name": "duration" } sums a numeric or boolean column.
- A select may contain both column_name and cnf to sum only matching sessions.

group_by adds a group value as the first cell in every row:
- { "column_name": "resource_id" } gives one row per rep/resource.
- { "column_name": "user_log.disposition" } gives one row per disposition.
- { "column_name": "dial_metric.is_inbound" } separates inbound and non-inbound calls.

The remaining cells stay in the same order as selects. Use /visible to map resource_id values to user names. Use /bootstrap to discover exact disposition strings.
```

Each aggregation’s filters are additional to the top-level `cnf`. A sum can use a numeric or boolean column; summing a boolean counts true values. An empty aggregation object is invalid.

## Group numeric values into bins

- Use exact grouping for strings, booleans, bytes and enums. Do not supply step parameters for these types.
- Floating-point and started_at grouping require step_size_safe and step_start_safe. Integer grouping can use exact values or steps.
- step_size_safe is the bin width; step_start_safe is its origin; optional step_modulus_safe is a repeat period. Values use the grouped column’s units: started_at uses seconds.
- For stepped groups, the key is floor(((value - origin) modulo period, when supplied) / width). It is a bin index, not a date.
- Compatibility exception: the current metric-details-v7 endpoint scales a started_at group key by 1,000,000. Divide by 1,000,000 to recover the bin index before converting it to a time range.

## Rate limit

4 requests per 4 seconds per user by default. Shared by v6 and v7. See [Rate limits and exports](https://www.trellus.ai/developers/api/rate-limits).

## Errors

Error bodies can be plain text. Read the status and the response text.

### 400 or rejected phone, company, email or transcript field

Use the exact paths in the field guide. start and select are required for lists; metrics use selects. POST parameters belong in JSON, with Content-Type: application/json. Error responses can be plain text.

### 401 “not permissioned” or “not authorized”

The user behind the key cannot read that session or team. Check /visible and ask your team admin to review reporting access. A team_id parameter does not grant access. “inactive user” can also mean the key is invalid or the account is inactive.

### 429 Too Many Requests

Wait the Retry-After number of seconds, then retry with a bounded retry policy. Coordinate workers using the same user key. Default backend limits are per user, not per IP. If only your shared cloud host is blocked despite pacing, give support the UTC time, endpoint and response headers so upstream limits can be investigated.

Every documented case is on [Errors and troubleshooting](https://www.trellus.ai/developers/api/errors).
