Run a report query
Executes an ad-hoc reporting query: one metric + aggregation over a date range, with optional filters, grouping, segmentation and period-over-period comparison.
Building a query
- Pick a
metricandaggregationfrom the datasets catalog (GET /v2/reports/datasets). Counts usecount; duration metrics supportsum,avg,median,min,max,rangeandpercentile(passpercentile: 95for p95); rate metrics usevalue. - Set the reporting window with
startDate/endDate(ISO 8601) and agranularity(hour,day,week,month) for the returned time series. Reporting data is available from July 12, 2026. Windows ending earlier are rejected; crossing windows are clamped to that boundary in the requested timezone. - Optionally narrow with
filters— a rule ({ "kind": "rule", "fieldId": "...", "operator": "in", "value": [...] }) or anand/orgroup of rules. Attribute IDs and allowed operators come from the catalog. - Optionally break results down with
groupBy(primary dimension) andsegmentBy(secondary dimension). - Optionally pass
compareStartDate/compareEndDateto getpreviousValue/deltaPercentalongside every data point.
Top-N and Show Other
For high-cardinality breakdowns, cap the number of returned series:
topValuesLimitkeeps only the top NgroupByvalues;segmentTopValuesLimitdoes the same forsegmentBy. Allowed values: 5, 7, 10, 15, 20.topValuesLimitrequiresgroupBy;segmentTopValuesLimitrequiressegmentBy.- Members are ranked by the selected metric/aggregation over the full filtered primary range, so the ranked set is stable across every time bucket (a value that spikes in one bucket but is small overall does not enter the set). A comparison period reuses the primary period’s ranked set — it is never re-ranked, so the legend stays identical period-over-period.
showOther/segmentShowOtherappend a single synthetic bucket with id__other__and labelOtherthat sums every value outside the top set. Because the values are summed, Show Other is only supported for additive aggregations (count,sum,value); it is rejected foravg,median,min,max,range,percentile, and for percentage metrics (whose ratios cannot be summed).showOtheralso requirestopValuesLimit(andsegmentShowOtherrequiressegmentTopValuesLimit). PlaintopValuesLimit(without Show Other) works with any aggregation.- The
__other__group/segment aggregates rows outside the selected top groups and cannot be drilled into (POST /v2/reports/drill-inrejectsdataPointFilters.groupValue/segmentValueequal to__other__).
Example
{
"metric": "new_conversations",
"aggregation": "count",
"startDate": "2026-07-12",
"endDate": "2026-07-15",
"granularity": "day",
"groupBy": "conversation.channel",
"filters": {
"kind": "rule",
"fieldId": "conversation.state",
"operator": "is",
"value": "closed"
}
}
Response shape
value— the aggregate across the whole windowtimeSeries— one datum per granularity bucketgroupedData/segmentData— present whengroupBy/segmentBywere requestedflowData— present forview: "sankey"(Overview conversation-flow metrics)meta— echo of the resolved metric, dataset, unit and aggregation
Special views
view: "hourly_heatmap"buckets by day-of-week × hour-of-day (use with volume metrics)view: "sankey"returns conversation flow edges (Overview metrics only)
Version Availability
This endpoint is only available in API version 2026-01-01.nova and newer, and only for workspaces with the Reports product enabled (404 otherwise).
Body ParametersJSON
End of the reporting window (ISO 8601 date or datetime, inclusive). Windows ending before 2026-07-12 are rejected.
Metric ID to query (e.g. new_conversations). Discover metric IDs via GET /v2/reports/datasets.
Start of the reporting window (ISO 8601 date or datetime, inclusive). Reporting data is available from 2026-07-12; crossing windows are clamped to that boundary.
End of the comparison window. Must be paired with compareStartDate.
Start of the comparison window for period-over-period deltas. Must be paired with compareEndDate.
Attribute ID to group results by (e.g. conversation.channel). See supportsGroupBy in the catalog.
Restrict time-based metrics to configured office hours. Only supported by some metrics (see supportsOfficeHours in the catalog).
Percentile (1-100) — required when aggregation is percentile.
Attribute ID for secondary segmentation within each group or time bucket.
When true, fold segmentBy values outside the top set into a synthetic __other__ / Other segment. Only supported for additive aggregations (count, sum, value) and not for percentage metrics. The __other__ segment cannot be drilled into. Requires segmentBy and segmentTopValuesLimit.
When true, append a single synthetic group with id __other__ and label Other that sums the values of every groupBy value outside the top set. Only supported for additive aggregations (count, sum, value) and not for percentage metrics. The __other__ group cannot be drilled into. Requires groupBy and topValuesLimit.
Run a report query
curl https://do.featurebase.app/v2/reports/query \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer $FEATUREBASE_API_KEY" \
-d '{
"aggregation": "count",
"endDate": "2026-07-15",
"granularity": "day",
"metric": "new_conversations",
"startDate": "2026-07-12",
"groupBy": "conversation.channel",
"percentile": 95,
"segmentTopValuesLimit": 5,
"timezone": "Europe/Tallinn",
"topValuesLimit": 10,
"view": "standard"
}'{
"meta": {
"aggregation": "count",
"datasetId": "datasetId",
"granularity": "granularity",
"metric": "metric",
"officeHoursOnly": true,
"unit": "count",
"groupBy": "groupBy",
"segmentBy": "segmentBy"
},
"object": "report_query_result",
"value": 0,
"deltaPercent": 0,
"flowData": [
{
"metricId": "metricId",
"pathId": "pathId",
"source": "source",
"sourceLabel": "sourceLabel",
"target": "target",
"targetLabel": "targetLabel",
"value": 0,
"colorKey": "colorKey",
"percentage": 0,
"sortOrder": 0
}
],
"groupedData": [
{
"group": "group",
"value": 0,
"groupLabel": "groupLabel",
"previousValue": 0,
"segments": [
{
"segment": "segment",
"value": 0,
"previousValue": 0,
"segmentLabel": "segmentLabel"
}
]
}
],
"previousValue": 0,
"segmentData": [
{
"segment": "segment",
"value": 0,
"previousValue": 0,
"segmentLabel": "segmentLabel"
}
],
"table": {
"columns": [
{
"id": "id",
"kind": "dimension",
"label": "label",
"sortable": true,
"unit": "count",
"align": "left",
"sticky": true,
"summary": "sum",
"valueType": "valueType"
}
],
"key": "key",
"mode": "aggregate",
"page": 0,
"pageSize": 0,
"rows": [
{
"id": "id",
"cells": {
"foo": {
"display": "display",
"denominator": 0,
"numerator": 0,
"raw": {},
"sortValue": "string",
"value": {}
}
}
}
],
"totalRows": 0,
"sort": {
"columnId": "columnId",
"direction": "asc"
},
"summaryRows": [
{
"id": "id",
"cells": {
"foo": {
"display": "display",
"denominator": 0,
"numerator": 0,
"raw": {},
"sortValue": "string",
"value": {}
}
}
}
]
},
"timeSeries": [
{
"date": "2026-07-15",
"value": 0,
"previousValue": 0,
"segments": [
{
"segment": "segment",
"value": 0,
"previousValue": 0,
"segmentLabel": "segmentLabel"
}
]
}
]
}Returns Examples
{
"meta": {
"aggregation": "count",
"datasetId": "datasetId",
"granularity": "granularity",
"metric": "metric",
"officeHoursOnly": true,
"unit": "count",
"groupBy": "groupBy",
"segmentBy": "segmentBy"
},
"object": "report_query_result",
"value": 0,
"deltaPercent": 0,
"flowData": [
{
"metricId": "metricId",
"pathId": "pathId",
"source": "source",
"sourceLabel": "sourceLabel",
"target": "target",
"targetLabel": "targetLabel",
"value": 0,
"colorKey": "colorKey",
"percentage": 0,
"sortOrder": 0
}
],
"groupedData": [
{
"group": "group",
"value": 0,
"groupLabel": "groupLabel",
"previousValue": 0,
"segments": [
{
"segment": "segment",
"value": 0,
"previousValue": 0,
"segmentLabel": "segmentLabel"
}
]
}
],
"previousValue": 0,
"segmentData": [
{
"segment": "segment",
"value": 0,
"previousValue": 0,
"segmentLabel": "segmentLabel"
}
],
"table": {
"columns": [
{
"id": "id",
"kind": "dimension",
"label": "label",
"sortable": true,
"unit": "count",
"align": "left",
"sticky": true,
"summary": "sum",
"valueType": "valueType"
}
],
"key": "key",
"mode": "aggregate",
"page": 0,
"pageSize": 0,
"rows": [
{
"id": "id",
"cells": {
"foo": {
"display": "display",
"denominator": 0,
"numerator": 0,
"raw": {},
"sortValue": "string",
"value": {}
}
}
}
],
"totalRows": 0,
"sort": {
"columnId": "columnId",
"direction": "asc"
},
"summaryRows": [
{
"id": "id",
"cells": {
"foo": {
"display": "display",
"denominator": 0,
"numerator": 0,
"raw": {},
"sortValue": "string",
"value": {}
}
}
}
]
},
"timeSeries": [
{
"date": "2026-07-15",
"value": 0,
"previousValue": 0,
"segments": [
{
"segment": "segment",
"value": 0,
"previousValue": 0,
"segmentLabel": "segmentLabel"
}
]
}
]
}