Skip to content
Dashboard

Reports

Query your workspace analytics: conversation volume, response times, CSAT, SLA compliance, teammate performance, AI agent resolutions and more. Start with the datasets catalog to discover metrics and attributes, then run queries with filters, grouping and period comparison.

List report datasets
GET/v2/reports/datasets
Run a report query
POST/v2/reports/query
Look up report filter values
POST/v2/reports/filter-values
Drill into report rows
POST/v2/reports/drill-in
ModelsExpand Collapse
ReportAttribute object { id, allowedOperators, category, 9 more }
id: string

Attribute ID — use as fieldId in filter rules and as groupBy / segmentBy in query requests.

allowedOperators: array of "is" or "is_not" or "in" or 10 more
One of the following:
"is"
"is_not"
"in"
"not_in"
"contains"
"not_contains"
"gte"
"lte"
"between"
"exists"
"not_exists"
"is_member_of"
"is_not_member_of"
category: string
description: string
name: string
semantics: "current_state" or "historical_action" or "historical_snapshot" or "dynamic_metric_mapped"

Whether the filter uses the latest mutable state, an immutable historical action/snapshot, or a metric-dependent mapping.

One of the following:
"current_state"
"historical_action"
"historical_snapshot"
"dynamic_metric_mapped"
supportsFilter: boolean

Whether the attribute can be used in filters rules.

supportsGroupBy: boolean

Whether the attribute can be used as groupBy / segmentBy.

supportsValueLookup: boolean

Whether POST /v2/reports/filter-values can list this attribute’s values.

valueType: "string" or "number" or "boolean" or 3 more
One of the following:
"string"
"number"
"boolean"
"date"
"enum"
"id"
multiValue: optional boolean
staticOptions: optional array of ReportAttributeOption { label, value }

Fixed value set for enum-like attributes. Attributes without static options resolve values via POST /v2/reports/filter-values.

label: string
value: string
ReportAttributeOption object { label, value }
label: string
value: string
ReportDataset object { id, attributes, description, 2 more }
id: string
attributes: array of ReportAttribute { id, allowedOperators, category, 9 more }
id: string

Attribute ID — use as fieldId in filter rules and as groupBy / segmentBy in query requests.

allowedOperators: array of "is" or "is_not" or "in" or 10 more
One of the following:
"is"
"is_not"
"in"
"not_in"
"contains"
"not_contains"
"gte"
"lte"
"between"
"exists"
"not_exists"
"is_member_of"
"is_not_member_of"
category: string
description: string
name: string
semantics: "current_state" or "historical_action" or "historical_snapshot" or "dynamic_metric_mapped"

Whether the filter uses the latest mutable state, an immutable historical action/snapshot, or a metric-dependent mapping.

One of the following:
"current_state"
"historical_action"
"historical_snapshot"
"dynamic_metric_mapped"
supportsFilter: boolean

Whether the attribute can be used in filters rules.

supportsGroupBy: boolean

Whether the attribute can be used as groupBy / segmentBy.

supportsValueLookup: boolean

Whether POST /v2/reports/filter-values can list this attribute’s values.

valueType: "string" or "number" or "boolean" or 3 more
One of the following:
"string"
"number"
"boolean"
"date"
"enum"
"id"
multiValue: optional boolean
staticOptions: optional array of ReportAttributeOption { label, value }

Fixed value set for enum-like attributes. Attributes without static options resolve values via POST /v2/reports/filter-values.

label: string
value: string
description: string
metrics: array of ReportMetric { id, allowedAggregations, description, 13 more }
id: string

Metric ID — use as metric in query requests.

allowedAggregations: array of "count" or "sum" or "avg" or 6 more
One of the following:
"count"
"sum"
"avg"
"median"
"min"
"max"
"range"
"percentile"
"value"
description: string
name: string
supportedFilterAttributeIds: array of string

Attribute IDs this specific metric accepts in filter expressions.

supportedGroupByDimensions: array of string

Attribute IDs this specific metric accepts as groupBy or segmentBy.

supportedViews: array of "standard" or "hourly_heatmap" or "sankey"

Which view values POST /v2/reports/query accepts for this metric. Most metrics support standard and hourly_heatmap; conversation-flow metrics are sankey-only.

One of the following:
"standard"
"hourly_heatmap"
"sankey"
supportsOfficeHours: boolean
supportsPeriodComparison: boolean
type: "count" or "percentage" or "duration" or "number"
One of the following:
"count"
"percentage"
"duration"
"number"
unit: "count" or "percentage" or "duration_ms" or "number"
One of the following:
"count"
"percentage"
"duration_ms"
"number"
dataAvailableFromIso: optional string

Local calendar date (ISO 8601) from which this specific metric has data, when it differs from the global reporting floor. Windows ending before this date are rejected for this metric.

isDefaultVariant: optional boolean

Whether this variant is the default selection for its variantGroupId.

variantGroupId: optional string

Metrics sharing a variantGroupId are timestamp variants of one logical metric (same display name); each measures the same population at a different timestamp. Query the concrete metric id to pick a variant.

variantId: optional string

Stable identifier for this variant within its group (e.g. created_at, started_at).

variantLabel: optional string

Human-readable variant label for pickers (e.g. Created at, Started at).

name: string
ReportFilterExpression object { children, kind, op }
children: array of ReportFilterRule { fieldId, kind, operator, value } or object { children, kind, op }

Rules and/or nested groups of rules. Groups may nest up to 6 levels at runtime; 100 rules max per expression.

One of the following:
ReportFilterRule object { fieldId, kind, operator, value }
fieldId: string

Attribute ID to filter on (e.g. conversation.channel). Discover attribute IDs via GET /v2/reports/datasets.

minLength1
maxLength512
kind: "rule"
operator: "is" or "is_not" or "in" or 10 more

Comparison operator. Each attribute supports a subset of operators — see the allowedOperators field in the GET /v2/reports/datasets catalog.

One of the following:
"is"
"is_not"
"in"
"not_in"
"contains"
"not_contains"
"gte"
"lte"
"between"
"exists"
"not_exists"
"is_member_of"
"is_not_member_of"
value: optional string or number or boolean or array of string or number or boolean

Value to compare against. Scalar for is, is_not, contains, not_contains, gte, lte (ISO date strings for date attributes); non-empty array for in, not_in, is_member_of, is_not_member_of; 2-element array for between; omit for exists / not_exists.

One of the following:
string
number
boolean
array of string or number or boolean
One of the following:
string
number
boolean
ReportFilterGroup object { children, kind, op }
children: array of ReportFilterRule { fieldId, kind, operator, value }
fieldId: string

Attribute ID to filter on (e.g. conversation.channel). Discover attribute IDs via GET /v2/reports/datasets.

minLength1
maxLength512
kind: "rule"
operator: "is" or "is_not" or "in" or 10 more

Comparison operator. Each attribute supports a subset of operators — see the allowedOperators field in the GET /v2/reports/datasets catalog.

One of the following:
"is"
"is_not"
"in"
"not_in"
"contains"
"not_contains"
"gte"
"lte"
"between"
"exists"
"not_exists"
"is_member_of"
"is_not_member_of"
value: optional string or number or boolean or array of string or number or boolean

Value to compare against. Scalar for is, is_not, contains, not_contains, gte, lte (ISO date strings for date attributes); non-empty array for in, not_in, is_member_of, is_not_member_of; 2-element array for between; omit for exists / not_exists.

One of the following:
string
number
boolean
array of string or number or boolean
One of the following:
string
number
boolean
kind: "group"
op: "and" or "or"

Group operator: and (all match) or or (any match).

One of the following:
"and"
"or"
kind: "group"
op: "and" or "or"

Group operator: and (all match) or or (any match).

One of the following:
"and"
"or"
ReportFilterRule object { fieldId, kind, operator, value }
fieldId: string

Attribute ID to filter on (e.g. conversation.channel). Discover attribute IDs via GET /v2/reports/datasets.

minLength1
maxLength512
kind: "rule"
operator: "is" or "is_not" or "in" or 10 more

Comparison operator. Each attribute supports a subset of operators — see the allowedOperators field in the GET /v2/reports/datasets catalog.

One of the following:
"is"
"is_not"
"in"
"not_in"
"contains"
"not_contains"
"gte"
"lte"
"between"
"exists"
"not_exists"
"is_member_of"
"is_not_member_of"
value: optional string or number or boolean or array of string or number or boolean

Value to compare against. Scalar for is, is_not, contains, not_contains, gte, lte (ISO date strings for date attributes); non-empty array for in, not_in, is_member_of, is_not_member_of; 2-element array for between; omit for exists / not_exists.

One of the following:
string
number
boolean
array of string or number or boolean
One of the following:
string
number
boolean
ReportGroupedDatum object { group, value, groupLabel, 2 more }
group: string

Raw group value (e.g. an ID). Use groupLabel for display.

value: number
groupLabel: optional string
previousValue: optional number
segments: optional array of ReportSegmentDatum { segment, value, previousValue, segmentLabel }
segment: string
value: number
previousValue: optional number
segmentLabel: optional string
ReportMetric object { id, allowedAggregations, description, 13 more }
id: string

Metric ID — use as metric in query requests.

allowedAggregations: array of "count" or "sum" or "avg" or 6 more
One of the following:
"count"
"sum"
"avg"
"median"
"min"
"max"
"range"
"percentile"
"value"
description: string
name: string
supportedFilterAttributeIds: array of string

Attribute IDs this specific metric accepts in filter expressions.

supportedGroupByDimensions: array of string

Attribute IDs this specific metric accepts as groupBy or segmentBy.

supportedViews: array of "standard" or "hourly_heatmap" or "sankey"

Which view values POST /v2/reports/query accepts for this metric. Most metrics support standard and hourly_heatmap; conversation-flow metrics are sankey-only.

One of the following:
"standard"
"hourly_heatmap"
"sankey"
supportsOfficeHours: boolean
supportsPeriodComparison: boolean
type: "count" or "percentage" or "duration" or "number"
One of the following:
"count"
"percentage"
"duration"
"number"
unit: "count" or "percentage" or "duration_ms" or "number"
One of the following:
"count"
"percentage"
"duration_ms"
"number"
dataAvailableFromIso: optional string

Local calendar date (ISO 8601) from which this specific metric has data, when it differs from the global reporting floor. Windows ending before this date are rejected for this metric.

isDefaultVariant: optional boolean

Whether this variant is the default selection for its variantGroupId.

variantGroupId: optional string

Metrics sharing a variantGroupId are timestamp variants of one logical metric (same display name); each measures the same population at a different timestamp. Query the concrete metric id to pick a variant.

variantId: optional string

Stable identifier for this variant within its group (e.g. created_at, started_at).

variantLabel: optional string

Human-readable variant label for pickers (e.g. Created at, Started at).

ReportSegmentDatum object { segment, value, previousValue, segmentLabel }
segment: string
value: number
previousValue: optional number
segmentLabel: optional string
ReportTimeSeriesDatum object { date, value, previousValue, segments }
date: string

Time bucket start (ISO 8601).

value: number
previousValue: optional number

Value for the same bucket in the comparison window, when requested.

segments: optional array of ReportSegmentDatum { segment, value, previousValue, segmentLabel }
segment: string
value: number
previousValue: optional number
segmentLabel: optional string
ReportListDatasetsResponse object { data, object }
data: array of ReportDataset { id, attributes, description, 2 more }
id: string
attributes: array of ReportAttribute { id, allowedOperators, category, 9 more }
id: string

Attribute ID — use as fieldId in filter rules and as groupBy / segmentBy in query requests.

allowedOperators: array of "is" or "is_not" or "in" or 10 more
One of the following:
"is"
"is_not"
"in"
"not_in"
"contains"
"not_contains"
"gte"
"lte"
"between"
"exists"
"not_exists"
"is_member_of"
"is_not_member_of"
category: string
description: string
name: string
semantics: "current_state" or "historical_action" or "historical_snapshot" or "dynamic_metric_mapped"

Whether the filter uses the latest mutable state, an immutable historical action/snapshot, or a metric-dependent mapping.

One of the following:
"current_state"
"historical_action"
"historical_snapshot"
"dynamic_metric_mapped"
supportsFilter: boolean

Whether the attribute can be used in filters rules.

supportsGroupBy: boolean

Whether the attribute can be used as groupBy / segmentBy.

supportsValueLookup: boolean

Whether POST /v2/reports/filter-values can list this attribute’s values.

valueType: "string" or "number" or "boolean" or 3 more
One of the following:
"string"
"number"
"boolean"
"date"
"enum"
"id"
multiValue: optional boolean
staticOptions: optional array of ReportAttributeOption { label, value }

Fixed value set for enum-like attributes. Attributes without static options resolve values via POST /v2/reports/filter-values.

label: string
value: string
description: string
metrics: array of ReportMetric { id, allowedAggregations, description, 13 more }
id: string

Metric ID — use as metric in query requests.

allowedAggregations: array of "count" or "sum" or "avg" or 6 more
One of the following:
"count"
"sum"
"avg"
"median"
"min"
"max"
"range"
"percentile"
"value"
description: string
name: string
supportedFilterAttributeIds: array of string

Attribute IDs this specific metric accepts in filter expressions.

supportedGroupByDimensions: array of string

Attribute IDs this specific metric accepts as groupBy or segmentBy.

supportedViews: array of "standard" or "hourly_heatmap" or "sankey"

Which view values POST /v2/reports/query accepts for this metric. Most metrics support standard and hourly_heatmap; conversation-flow metrics are sankey-only.

One of the following:
"standard"
"hourly_heatmap"
"sankey"
supportsOfficeHours: boolean
supportsPeriodComparison: boolean
type: "count" or "percentage" or "duration" or "number"
One of the following:
"count"
"percentage"
"duration"
"number"
unit: "count" or "percentage" or "duration_ms" or "number"
One of the following:
"count"
"percentage"
"duration_ms"
"number"
dataAvailableFromIso: optional string

Local calendar date (ISO 8601) from which this specific metric has data, when it differs from the global reporting floor. Windows ending before this date are rejected for this metric.

isDefaultVariant: optional boolean

Whether this variant is the default selection for its variantGroupId.

variantGroupId: optional string

Metrics sharing a variantGroupId are timestamp variants of one logical metric (same display name); each measures the same population at a different timestamp. Query the concrete metric id to pick a variant.

variantId: optional string

Stable identifier for this variant within its group (e.g. created_at, started_at).

variantLabel: optional string

Human-readable variant label for pickers (e.g. Created at, Started at).

name: string
object: "list"
ReportQueryResponse object { meta, object, value, 7 more }
meta: object { aggregation, datasetId, granularity, 5 more }
aggregation: "count" or "sum" or "avg" or 6 more

Aggregation function applied to the metric. Each metric supports a subset of aggregations — see the allowedAggregations field in the GET /v2/reports/datasets catalog.

One of the following:
"count"
"sum"
"avg"
"median"
"min"
"max"
"range"
"percentile"
"value"
datasetId: string
granularity: string
metric: string
officeHoursOnly: boolean
unit: "count" or "percentage" or "duration_ms" or "number"
One of the following:
"count"
"percentage"
"duration_ms"
"number"
groupBy: optional string
segmentBy: optional string
object: "report_query_result"
value: number

Aggregated value across the whole reporting window.

deltaPercent: optional number

Percentage change vs the comparison window.

flowData: optional array of object { metricId, pathId, source, 7 more }
metricId: string
pathId: string
source: string
sourceLabel: string
target: string
targetLabel: string
value: number
colorKey: optional string
percentage: optional number
sortOrder: optional number
groupedData: optional array of ReportGroupedDatum { group, value, groupLabel, 2 more }
group: string

Raw group value (e.g. an ID). Use groupLabel for display.

value: number
groupLabel: optional string
previousValue: optional number
segments: optional array of ReportSegmentDatum { segment, value, previousValue, segmentLabel }
segment: string
value: number
previousValue: optional number
segmentLabel: optional string
previousValue: optional number

Aggregated value for the comparison window, when requested.

segmentData: optional array of ReportSegmentDatum { segment, value, previousValue, segmentLabel }
segment: string
value: number
previousValue: optional number
segmentLabel: optional string
table: optional object { columns, key, mode, 6 more }
columns: array of object { id, kind, label, 6 more }
id: string
kind: "dimension" or "metric" or "record_attribute"
One of the following:
"dimension"
"metric"
"record_attribute"
label: string
sortable: boolean
unit: "count" or "percentage" or "duration_ms" or 3 more
One of the following:
"count"
"percentage"
"duration_ms"
"number"
"text"
"datetime"
align: optional "left" or "right"
One of the following:
"left"
"right"
sticky: optional boolean
summary: optional "sum" or "weighted_rate" or "none"
One of the following:
"sum"
"weighted_rate"
"none"
valueType: optional string
key: string
mode: "aggregate" or "records"
One of the following:
"aggregate"
"records"
page: number
pageSize: number
rows: array of object { id, cells }
id: string
cells: map[object { display, denominator, numerator, 3 more } ]
display: string
denominator: optional number
numerator: optional number
raw: optional unknown
sortValue: optional string or number
One of the following:
string
number
value: optional unknown
totalRows: number
sort: optional object { columnId, direction }
columnId: string
direction: "asc" or "desc"
One of the following:
"asc"
"desc"
summaryRows: optional array of object { id, cells }
id: string
cells: map[object { display, denominator, numerator, 3 more } ]
display: string
denominator: optional number
numerator: optional number
raw: optional unknown
sortValue: optional string or number
One of the following:
string
number
value: optional unknown
timeSeries: optional array of ReportTimeSeriesDatum { date, value, previousValue, segments }
date: string

Time bucket start (ISO 8601).

value: number
previousValue: optional number

Value for the same bucket in the comparison window, when requested.

segments: optional array of ReportSegmentDatum { segment, value, previousValue, segmentLabel }
segment: string
value: number
previousValue: optional number
segmentLabel: optional string
ReportLookupFilterValuesResponse object { data, object }
data: array of ReportAttributeOption { label, value }
label: string
value: string
object: "list"
ReportDrillInResponse object { availableColumns, defaultColumnIds, meta, 6 more }
availableColumns: array of object { id, name, supportsSort, 2 more }
id: string

Column ID (an attribute ID or metric.value).

name: string
supportsSort: boolean

Whether this column may be used in the drill-in sort request.

valueType: string
category: optional string
defaultColumnIds: array of string
meta: object { datasetId, metricId, rawMetricId, 6 more }
datasetId: string
metricId: string
rawMetricId: string
reconciliation: object { kind, rowCount, status, 4 more }
kind: "rows" or "actions_across_conversations" or "active_hour_rate" or 2 more
One of the following:
"rows"
"actions_across_conversations"
"active_hour_rate"
"positive_ratings_over_eligible_ratings"
"missed_over_evaluated"
rowCount: number
status: "not_applicable" or "available" or "denominator_unavailable"
One of the following:
"not_applicable"
"available"
"denominator_unavailable"
denominatorHours: optional number
displayedRate: optional number
eligibleDenominatorTotal: optional number
rawNumeratorTotal: optional number
rowGrain: string
rowSemantics: "metric_rows" or "numerator_rows"
One of the following:
"metric_rows"
"numerator_rows"
sourceFact: string
emptyReason: optional "no_matching_rows" or "denominator_unavailable"
One of the following:
"no_matching_rows"
"denominator_unavailable"
metricRowId: optional string
object: "report_drill_in_result"
page: number
pageSize: number
rows: array of map[string or number or boolean or 3 more]

One record per underlying row, keyed by column ID.

One of the following:
string
number
boolean
array of string
ReportDrillInIdentityCell object { id, kind, label, 3 more }
id: string
kind: "identity"
label: string
avatarUrl: optional string
color: optional string
provenance: optional "current" or "historical" or "fallback" or "unassigned"
One of the following:
"current"
"historical"
"fallback"
"unassigned"
ReportDrillInSourceDetailsCell object { items, kind }
items: array of object { label, id, type, url }
label: string
id: optional string
type: optional string
url: optional string
formaturi
kind: "source_details"
timezone: string
total: number