- Applies to: Sprinklr Reporting API, version 3 (
/api/v3/reports/*), OpenAPI tagReporting V3 - V2 API reference: Reporting (index) — Custom Query, Custom Query Using Widget Id, Batch Query, Fetch Reporting Engines, Fetch Report Names, Fetch Custom Metrics, Fetch Metrics and Dimensions
The Reporting API returns the same analytics data that Sprinklr's reporting dashboards display. The OpenAPI document describes the Reporting V3 tag as:
Run analytics queries and retrieve reporting metadata. Supports single, widget, and batch queries, listing reporting engines and enabled report names, fetching report metadata and custom measurements, retrieving viral trend insights, returning compiled backend query strings, and Research Assistant queries.
Reporting is a four-level hierarchy. You must resolve each level before you can query.
| Concept | What it is | How to discover it |
|---|---|---|
| Reporting engine | The data domain — Listening, Paid, Inbound Analytics, Voice, and so on. Identified by an id such as PLATFORM or INBOUND_MESSAGE. | GET /reports/engine |
| Report | A dataset within an engine, such as ACCOUNT_INSIGHTS or POST_INSIGHTS. | GET /reports/report |
Dimensions (groupBys) | The attributes you slice by — channel, account, date. | GET /reports/metadata |
Measurements (projections) | The numbers you aggregate — impressions, followers, handling time. | GET /reports/metadata and GET /reports/custom-metric |
| If you… | Use | Why |
|---|---|---|
| Want data for a widget that already exists on a dashboard | POST /reports/query/widget | The widget already encodes the report, filters, dimensions and metrics. You supply only a time range and paging. |
| Want to build a query from scratch, or need filters the UI cannot express | POST /reports/query | Full control over filters, groupBys, projections, sorts. |
| Need several queries answered in one round trip, or your widget draws from more than one report type | POST /reports/batchQuery | V2: "If the configured metrics and dimensions in a widget are being pulled from multiple report types, batch query API is used." |
The intended path to a working payload is not to hand-write one. Build the widget in the UI, then export its payload:
- Create a dashboard and add a widget that shows the data you want.
- Grant your user the
Generate Widget API Payloadrole permission — Governance Console → All Settings → Workspace Roles (or Global Roles) → Create/Edit Role. - On the widget, open the three-dot menu → Generate API v2 Payload.
- Choose Copy Code and paste the result into your request body.
Two constraints from the Blueprints article that surprise people:
- "a separate API payload needs to be generated for every widget within the dashboard."
- "dashboard level filters will not be reflected in the payload that is generated." — fold any dashboard-level filter into the widget, or add it manually to
filters.
To use the exported payload with POST /reports/query/widget, find widgetId inside the additional object of the generated payload.
- A registered Developer Portal application with an API key and secret. Best practice from the Blueprints article: register the app against a service account, not a personal user account, so the integration survives staff changes.
- An OAuth 2.0 access token. Validate it against the "ME" endpoint before debugging anything reporting-specific.
- Reporting view permission for the dashboards and workspaces you intend to query. A token whose user lacks workspace (client) access is the most common cause of a successful-but-empty response.
- The
Generate Widget API Payloadpermission if you intend to export payloads from the UI.
- Base URL is written
{base}and stands for `https://{host}/{env}. - Credentials always appear as
{{accessToken}}and{{apiKey}}. Never paste a real token into a shared document or ticket. - All epoch timestamps are milliseconds.
{base} = https://{host}/{env}Full request path:
{base}/api/v3/reports/{operation}| Segment | Value |
|---|---|
{host} | Region-specific API host, for example api2.sprinklr.com or api3.sprinklr.com |
{env} | Environment/partner path segment issued with your Developer Portal application |
All seven endpoints use the same headers. The V2 pages document four:
| Header | Value | Required | Notes |
|---|---|---|---|
Authorization | Bearer {{accessToken}} | Yes | OAuth 2.0 access token. |
Key | {{apiKey}} | Yes | Your Developer Portal API key. The V2 pages show the literal placeholder value api-key; substitute your own key. |
Content-Type | application/json | On POST | Required for the three query endpoints. |
Accept | application/json | Recommended | Declares the acceptable response type. |
Header casing note: HTTP header names are case-insensitive, so Key and key are equivalent.
The four GET endpoints resolve the hierarchy described in §1.1. Call them in the order below the first time you integrate; cache the results afterwards, since engine and report catalogues change rarely.
Summary. List reporting engines visible to the current partner. operationId. ReportingApiV3_listReportingEngines Response. 200 with the standard APIResponse envelope.
This is the entry point. The id values it returns are what you pass as reportingEngine in a query body and as reportingEngineId to the other three discovery endpoints.
None. The result is scoped implicitly to the partner and user behind the access token.
curl -X GET \
'https://api3.sprinklr.com/{env}/api/v3/reports/engine' \
-H 'Authorization: Bearer {{accessToken}}' \
-H 'Key: {{apiKey}}' \
-H 'Accept: application/json'{
"data": [
{ "id": "PLATFORM", "name": "Social Analytics" },
{ "id": "INBOUND_MESSAGE", "name": "Inbound Analytics" },
{ "id": "LISTENING", "name": "Listening" }
],
"errors": []
}The following 38 engines were returned by the V2 endpoint. The set visible to your token depends on your partner's licensed products, so always call the endpoint rather than hard-coding this list.
id | name |
|---|---|
ADOPTION | Adoption |
ADOPTION_ENGAGEMENT | Adoption Engagement |
AUDIENCE | Audience |
AUDIENCE_ACTIVITY | Audience Activity |
AUDIENCE_INSIGHTS | Audience Insights |
AUDIENCE_INSIGHT | Social DMP |
AUDIENCE_LEAD | AUDIENCE_LEAD |
BENCHMARKING | Benchmarking |
SELF_SERVE_BENCHMARKING | Benchmarking |
COMMUNITY | Community |
CONSUMPTION | Consumption Analytics |
CUSTOM_ENTITY | Custom Entity |
GALLERY_AUDIENCE_ACTIVITY | Gallery |
INBOUND_MESSAGE | Inbound Analytics |
LISTENING | Listening |
RDB_FIREHOSE | Listening Explorer |
SELF_SERVE_RDB_FIREHOSE | Listening Explorer |
LIVE_DATASET | Live Dataset |
LYEARN_REPORTING_ENGINE | LYEARN_REPORTING_ENGINE |
MONITORING_LOG | Monitoring Log |
OUTBOUND_MESSAGE | Outbound Message |
PAID | Paid |
PLATFORM | Social Analytics |
PLATFORM_HEALTH | Platform Health |
REAL_TIME | Real Time |
SELF_SERVE_MESSAGE | Self Serve |
SELF_SERVE_LISTENING | Self Serve |
SPR_TASK | Task |
STORE_FRONT_AUDIENCE_ACTIVITY | Store |
STORY_MESSAGE | Story Analytics |
SELF_SERVE_STORY_MESSAGE | Story Analytics |
UNIFIED_ANALYTICS_REPORTING_ENGINE | Unified Analytics |
UNIVERSAL_COMMERCE_EVENT_ENGINE | Universal Commerce |
UNIVERSAL_PROFILE | Universal Profile |
VOICE | Voice Analytics |
VOICE_SEGMENT_ACTIVATION_CONFIG | VOICE_SEGMENT_ACTIVATION_CONFIG |
YOUTUBE_REPORTING_ENGINE | YouTube Analytics |
wfm_reporting | wfm_reporting |
Three things to note before you build a UI on top of this list:
nameis not unique. Benchmarking, Listening Explorer, Self Serve and Story Analytics each appear twice under different ids. Key your code onid, and if you present a picker, disambiguate the duplicates yourself.idcasing is not uniform.wfm_reportingis lower-case while every other id is upper snake case. Do not normalise case when echoing an id back to the API.- Some entries expose an internal identifier as the display name —
AUDIENCE_LEAD,LYEARN_REPORTING_ENGINE,VOICE_SEGMENT_ACTIVATION_CONFIG. These are unlikely to be presentable to end users as-is.
Summary. List the reports enabled for a reporting engine. Response. 200 with the standard APIResponse envelope.
Given an engine id from, this returns the reports available within it. The values feed the report field of a query body and the reportNames parameter.
| Parameter | In | Required | Type | Description |
|---|---|---|---|---|
reportingEngineId | query | See note | string | The reporting engine id, for example PLATFORM. Obtain it from GET /reports/engine. |
curl -X GET \
'https://api3.sprinklr.com/{env}/api/v3/reports/report?reportingEngineId=PLATFORM' \
-H 'Authorization: Bearer {{accessToken}}' \
-H 'Key: {{apiKey}}' \
-H 'Accept: application/json'The response is an array of {id, name} objects, one per report. The PLATFORM engine returns several hundred; this is an abridged extract.
{
"data": [
{ "id": "ACCOUNT_INBOUND_VOLUME", "name": "ACCOUNT_INBOUND_VOLUME" },
{ "id": "ACCOUNT_INSIGHTS", "name": "ACCOUNT_INSIGHTS" },
{ "id": "AGENT_PERFORMANCE_AGGREGATED_REPORT", "name": "AGENT_PERFORMANCE_AGGREGATED_REPORT" },
{ "id": "ANALYTICS", "name": "ANALYTICS" },
{ "id": "FACEBOOK_HOURLY_INSIGHTS", "name": "FACEBOOK_HOURLY_INSIGHTS" },
{ "id": "POST_INSIGHTS", "name": "POST_INSIGHTS" },
{ "id": "CaseSLAReport", "name": "CaseSLAReport" }
],
"errors": []
}| Parameter | Type | Description |
|---|---|---|
data | array | One object per report enabled for the engine. |
data[].id | string | Report identifier. Pass this as report in a query body. |
data[].name | string | Display name. In practice identical to id for most reports. |
errors | array | Error objects, empty on success. |
Note that report ids are not uniformly upper snake case — the V2 response mixes ACCOUNT_INSIGHTS with CaseSLAReport, CaseProcessingSLAReport and ComprehensiveCaseSLAReport. Treat report ids as opaque, case-sensitive strings.
Summary. Get report metadata for a reporting engine. operationId. ReportingApiV3_getMetadata Response. 200 with the standard APIResponse envelope.
This is the endpoint that tells you what you are allowed to put in projections and groupBys. For each requested report it returns the full catalogue of measurements (metrics), dimensions, and filter dimensions, with their field names, data types and display names.
| Parameter | In | Required (V3 spec) | Required (V2) | Type | Description |
|---|---|---|---|---|---|
reportingEngineId | query | false | Required | string | Reporting engine id. |
reportNames | query | false | Required | string | Optional comma-separated report names; omit to return all reports. |
curl -X GET \
'https://api3.sprinklr.com/{env}/api/v3/reports/metadata?reportingEngineId=PLATFORM&reportNames=POST_INSIGHTS' \
-H 'Authorization: Bearer {{accessToken}}' \
-H 'Key: {{apiKey}}' \
-H 'Accept: application/json'To request several reports, comma-separate them:
?reportingEngineId=PLATFORM&reportNames=POST_INSIGHTS,ACCOUNT_INSIGHTSHeavily abridged — a real response for one report is several hundred lines.
{
"data": {
"POST_INSIGHTS": {
"recordType": "LIFETIME",
"displayName": "POST_INSIGHTS",
"dateFieldName": "date",
"skipVisibilityFilters": false,
"measurements": [
{
"type": "CUMULATIVE",
"measurementGroups": ["FACEBOOK"],
"name": "POST_FB_NEGATIVE_FEEDBACK_BY_TYPE_UNIQUE_HIDE_ALL_CLICKS",
"fieldName": "POST_FB_NEGATIVE_FEEDBACK_BY_TYPE_UNIQUE_HIDE_ALL_CLICKS",
"displayName": "Facebook Post Negative Feedback Unique All Hide",
"isShared": false,
"filterMeasurement": true,
"hidden": false,
"enabledForAiConcierge": false,
"channelTypes": ["FACEBOOK"]
}
],
"dimensions": [
{
"type": "SCRIPT",
"name": "postFeatures.ocr_gcv",
"fieldName": "postFeatures.ocr_gcv",
"displayName": "Creative Insight: All Text in Asset",
"filterDimension": true,
"multiValue": true,
"sortable": false,
"lookupSupported": true,
"hidden": false
}
],
"oldCustomFieldDimensionName": "OUTBOUND_CUSTOM_PROPERTY_NAME"
}
},
"errors": []
}| Parameter | Type | Description |
|---|---|---|
data | object | Keyed by report name — one entry per report you requested. |
data.{reportName} | object | Metadata for that report. |
data.{reportName}.recordType | string | Record type, for example LIFETIME. |
data.{reportName}.measurements | array | Measurement (metric) objects. The fieldName of each is what you put in projections[].measurementName. |
data.{reportName}.dimensions | array | Dimension objects. The fieldName of each is what you put in groupBys[].dimensionName and filters[].dimensionName. |
data.{reportName}.filterDimensions | array | Dimension objects usable specifically for filtering. |
data.{reportName}.oldCustomFieldDimension | object | Legacy custom-field dimension details. |
data.{reportName}.oldCustomFieldDimensionName | string | Name of the legacy custom-field dimension. |
data.{reportName}.skipVisibilityFilters | boolean | Whether visibility filters are bypassed for this report. |
data.{reportName}.displayName | string | Display name of the report. |
data.{reportName}.dateFieldName | string | The field used as the date field — a good default for timeField in a query body. |
errors | array | Error objects, empty on success. |
Commonly useful fields on each measurement and dimension object:
| Field | Type | Meaning |
|---|---|---|
name / fieldName | string | The identifier to use in a query. Use fieldName. |
displayName | string | Human-readable label as shown in the UI. |
dataType | string | For example NUMERIC, TIME_DIFFERENCE. |
type | string | For example CUMULATIVE, DELTA, SCRIPT, CUSTOM. |
measurementGroups | array | Groups the measurement belongs to, for example COMMON, FACEBOOK, VK. |
channelTypes | array | Channels the measurement applies to. |
hidden | boolean | Hidden measurements are generally not intended for direct use. |
filterMeasurement / filterDimension | boolean | Whether the field may be used in projectionFilters / filters. |
multiValue | boolean | Whether a dimension can hold multiple values per record. |
sortable | boolean | Whether the field can be used in sorts. |
lookupSupported | boolean | Whether the dimension's values can be resolved through a lookup. |
translatable | boolean | Whether the dimension's values can be translated. |
dashboardGroups | array | The dashboard groups the dimension is exposed in, for example PARTNER_DASHBOARD, OVERALL_DASHBOARD, QM_DASHBOARDS. |
When a response contains a custom property field name you do not recognise, copy that field name from the request and pass it to the fetch custom field using field name API to retrieve the label shown in the UI.
Summary. Get custom measurements for a reporting engine. operationId. ReportingApiV3_getCustomMetrics Response. 200 with the standard APIResponse envelope.
Custom measurements are metrics your organisation has defined itself in Sprinklr — typically a formula over one or more standard measurements. §6 returns the standard catalogue; this endpoint returns the customer-defined additions, together with the formula behind each.
| Parameter | In | Required (V3 spec) | Required (V2) | Type | Description |
|---|---|---|---|---|---|
reportingEngineId | query | false | Required | string | Reporting engine id. |
reportNames | query | false | Required | string | Optional comma-separated report names; omit for all reports. |
curl -X GET \
'https://api3.sprinklr.com/{env}/api/v3/reports/custom-metric?reportingEngineId=PLATFORM&reportNames=ACCOUNT_INSIGHTS' \
-H 'Authorization: Bearer {{accessToken}}' \
-H 'Key: {{apiKey}}' \
-H 'Accept: application/json'{
"data": {
"ACCOUNT_INSIGHTS": [
{
"script": " (__formula__elem__453*1000)",
"requiredProjections": [
{
"key": "__formula__elem__453",
"measurement": "FOLLOWERS_COUNT",
"aggregateFunction": "SUM"
}
],
"measurementGroups": ["COMMON"],
"groupNames": ["Custom Measurement"],
"isShared": false,
"sharedKey": "EXAMPLE_METRIC_1",
"filterMeasurement": true,
"name": "EXAMPLE_METRIC_1",
"fieldName": "EXAMPLE_METRIC_1",
"displayName": "Followers per thousand",
"lcName": "followers per thousand",
"hidden": false,
"enabledForAiConcierge": false,
"dataType": "NUMERIC",
"additional": {
"measurement_type": "Custom Measurement",
"clientId": 0000,
"IS_PERMISSIBLE": "false",
"definitionId": "000000000000000000000000"
}
},
{
"script": " (__formula__elem__1001+__formula__elem__1002)",
"requiredProjections": [
{
"key": "__formula__elem__1001",
"measurement": "FOLLOWERS_COUNT",
"aggregateFunction": "SUM"
},
{
"key": "__formula__elem__1002",
"measurement": "FACEBOOK_PAGE_FANS",
"aggregateFunction": "SUM"
}
],
"type": "CALCULATED",
"measurementGroups": ["COMMON"],
"groupNames": ["Custom Measurement"],
"isShared": false,
"sharedKey": "EXAMPLE_METRIC_2",
"filterMeasurement": true,
"name": "EXAMPLE_METRIC_2",
"fieldName": "EXAMPLE_METRIC_2",
"displayName": "Total audience",
"lcName": "total audience",
"filters": [],
"hidden": false,
"enabledForAiConcierge": false,
"dataType": "NUMERIC",
"additional": {
"definitionId": "000000000000000000000001",
"measurement_type": "Custom Measurement",
"IS_PERMISSIBLE": "false",
"clientId": 0000
}
}
]
},
"errors": []
}The metric names, display names, sharedKey, definitionId and clientId values above are illustrative placeholders and do not identify a real customer configuration.
| Parameter | Type | Description |
|---|---|---|
data | object | Container keyed by report name. |
data.{reportName} | array | Custom measurement objects for that report. |
data.{reportName}[].script | string | The formula evaluated to produce the metric, expressed over __formula__elem__* placeholders. |
data.{reportName}[].requiredProjections | array | The standard measurements the formula depends on. Each has a key (matching a placeholder in script), a measurement name, and an aggregateFunction. |
data.{reportName}[].type | string | Measurement type, for example CALCULATED, DELTA. |
data.{reportName}[].measurementGroups | array | Groups the measurement belongs to. |
data.{reportName}[].groupNames | array | Group display names, typically Custom Measurement. |
data.{reportName}[].isShared | boolean | Whether the measurement is shared. |
data.{reportName}[].sharedKey | string | Key for shared measurements. |
data.{reportName}[].filterMeasurement | boolean | Whether the measurement can be used in projectionFilters. |
data.{reportName}[].name / fieldName | string | Identifier to use in projections[].measurementName. |
data.{reportName}[].displayName | string | Display label. |
data.{reportName}[].lcName | string | Lower-cased display name. |
data.{reportName}[].shortName | string | Abbreviated label. |
data.{reportName}[].hidden | boolean | Whether the measurement is hidden in the UI. |
data.{reportName}[].enabledForAiConcierge | boolean | Whether the measurement is exposed to AI Concierge. |
data.{reportName}[].dataType | string | For example NUMERIC, TIME_DIFFERENCE. |
data.{reportName}[].filters | array | Filters baked into the custom measurement definition. |
data.{reportName}[].additional | object | Definition metadata — definitionId, clientId, measurement_type, IS_PERMISSIBLE. |
data.{reportName}[].channelTypes | array | Channels the measurement applies to. |
data.{reportName}[].code | string | Internal label code. |
errors | array | Error objects, empty on success. |
To use a custom metric in a query, put its fieldName in projections[].measurementName exactly as returned — Sprinklr resolves the formula server-side. You do not need to reproduce script or requiredProjections yourself.
Summary. Execute a reporting query (plain ReportRequest). operationId. ReportingApiV3_query Request body. ReportRequest, required. Response. 200 with the standard APIResponse envelope.
The general-purpose endpoint. You specify the engine, the report, the time range, and the dimensions, metrics, filters and sorts explicitly.
No path or query parameters. Everything is in the body — see §11.1.
curl -X POST \
'https://api3.sprinklr.com/{env}/api/v3/reports/query' \
-H 'Authorization: Bearer {{accessToken}}' \
-H 'Key: {{apiKey}}' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{
"reportingEngine": "PLATFORM",
"report": "ACCOUNT_INSIGHTS",
"startTime": 1735689600000,
"endTime": 1738368000000,
"timeZone": "America/New_York",
"page": 0,
"pageSize": 100,
"groupBys": [
{
"heading": "Channel",
"dimensionName": "SOCIAL_NETWORK",
"groupType": "FIELD"
}
],
"projections": [
{
"heading": "Followers",
"measurementName": "FOLLOWERS_COUNT",
"aggregateFunction": "SUM"
}
],
"filters": [
{
"dimensionName": "ACCOUNT_ID",
"filterType": "IN",
"values": ["000000000000000000000000"]
}
],
"sorts": [
{
"heading": "Followers",
"order": "DESC"
}
],
"jsonResponse": true
}'With jsonResponse set to true, rows are returned as objects keyed by heading:
{
"data": {
"data": [
{
"Channel": "FACEBOOK",
"Followers": 128394
},
{
"Channel": "TWITTER",
"Followers": 94021
}
],
"hasMore": false
},
"errors": []
}With jsonResponse set to false, the same result arrives in the compact columnar form — see §12.2.
| Parameter | Type | Description |
|---|---|---|
data | object | Result container. |
data.data | array | Result rows. Each key corresponds to a heading you supplied in groupBys or projections. |
data.hasMore | boolean | true if further rows are available beyond this page. See §12.3. |
errors | array | Error objects, empty on success. |
Summary. Execute a reporting query for a dashboard widget. operationId. ReportingApiV3_queryWidget Request body. WidgetReportRequest, required. Response. 200 with the standard APIResponse envelope.
The widget already defines the report, engine, dimensions, metrics and filters, so the body carries only the time range, paging and formatting options. This is the lowest-effort way to pull dashboard data programmatically.
| Parameter | In | Required (V3 spec) | Type | Description |
|---|---|---|---|---|
widgetId | query | false | string | Widget id. |
replaceHeadingsWithLabel | query | false | boolean | Forwarded to the underlying widget request. |
- Open the dashboard containing the widget.
- Widget three-dot menu → Generate API v2 Payload → Copy Code.
- In the copied payload, locate
widgetIdinside theadditionalobject.
WidgetReportRequest defines only eight fields.
| Field | Type | Required (V2 page) | Description |
|---|---|---|---|
startTime | integer (int64) | Required | Start of the time range, epoch milliseconds. |
endTime | integer (int64) | Required | End of the time range, epoch milliseconds. |
page | integer (int32) | Required | Zero-based page index. |
pageSize | integer (int32) | Optional | Rows per page. Keep at or below 1000 — see the warning below. |
interval | string | Optional | Bucket interval. Only required when the widget uses "groupType": "DATE_HISTOGRAM". |
skipResolve | boolean | Required | Default false. When true, suppresses resolution of referenced entities. |
jsonResponse | boolean | Required | Default false. Controls response shape — see §12.2. |
timeZone | string | Required | IANA time zone, for example America/New_York. |
curl -X POST \
'https://api3.sprinklr.com/{env}/api/v3/reports/query/widget?widgetId=000000000000000000000000' \
-H 'Authorization: Bearer {{accessToken}}' \
-H 'Key: {{apiKey}}' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{
"startTime": 1735689600000,
"endTime": 1738368000000,
"timeZone": "America/New_York",
"page": 0,
"pageSize": 1000,
"skipResolve": false,
"jsonResponse": false
}'With jsonResponse set to false, the widget endpoint returns the columnar form:
{
"data": {
"headings": ["Channel", "Followers"],
"rows": [
["FACEBOOK", 128394],
["TWITTER", 94021]
]
},
"errors": []
}| Parameter | Type | Description |
|---|---|---|
data | object | Result container. |
data.headings | array of strings | Column headings, in the order the widget defines them. |
data.rows | array of arrays | Result rows. Each inner array is positionally aligned with headings. |
errors | array | Error objects, empty on success. |
Summary. Execute multiple reporting queries in one request. operationId. ReportingApiV3_batchQuery Request body. BatchReportRequest, required. Response. 200 with the standard APIResponse envelope.
Use this when you need several results in one round trip, or when a single widget draws its metrics and dimensions from more than one report type. From the V2 page:
If the configured metrics and dimensions in a widget are being pulled from multiple report types, batch query API is used.
| Field | Type | Required (V2 page) | Description |
|---|---|---|---|
requests | object | Required | A map of arbitrary caller-chosen keys to ReportRequest objects. The keys you send are echoed back in the response. |
collate | boolean | Optional | Default false. Groups multiple queries together in the response. |
curl -X POST \
'https://api3.sprinklr.com/{env}/api/v3/reports/batchQuery' \
-H 'Authorization: Bearer {{accessToken}}' \
-H 'Key: {{apiKey}}' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{
"requests": {
"req1": {
"reportingEngine": "PLATFORM",
"report": "ACCOUNT_INSIGHTS",
"startTime": 1735689600000,
"endTime": 1738368000000,
"timeZone": "America/New_York",
"page": 0,
"pageSize": 100,
"groupBys": [
{ "heading": "Channel", "dimensionName": "SOCIAL_NETWORK", "groupType": "FIELD" }
],
"projections": [
{ "heading": "Followers", "measurementName": "FOLLOWERS_COUNT", "aggregateFunction": "SUM" }
],
"filters": []
},
"req2": {
"reportingEngine": "INBOUND_MESSAGE",
"report": "INBOUND_CASE",
"startTime": 1735689600000,
"endTime": 1738368000000,
"timeZone": "America/New_York",
"page": 0,
"pageSize": 100,
"groupBys": [
{ "heading": "Channel", "dimensionName": "SOCIAL_NETWORK", "groupType": "FIELD" }
],
"projections": [
{ "heading": "Volume", "measurementName": "INBOUND_COUNT", "aggregateFunction": "SUM" }
],
"filters": []
}
},
"collate": false
}'Results are returned in a reports map keyed by the same keys you sent.
{
"data": {
"reports": {
"req1": {
"headings": ["Channel", "Followers"],
"rows": [
["FACEBOOK", 128394],
["TWITTER", 94021]
]
},
"req2": {
"headings": ["Channel", "Volume"],
"rows": [
["FACEBOOK", 4821],
["TWITTER", 3107]
]
}
}
},
"errors": []
}| Parameter | Type | Description |
|---|---|---|
data | object | Result container. |
data.reports | object | Map keyed by your request keys. |
data.reports.{key} | object | Result for that sub-query, in the same headings/rows form as. |
errors | array | Error objects, empty on success. |
The V2 page documents these sub-fields of additional on a batch sub-request. They are typically populated automatically by the UI payload generator.
| Sub-field | Purpose |
|---|---|
translateResponse | Whether the response should be translated. |
dashboardId | Source dashboard identifier. |
engine | Reporting engine for the sub-request. |
widgetId | Source widget identifier. |
showTotal | Whether to include a total row. |
Currency | Currency for monetary measurements. |
chartType | Chart type the widget renders. |
showRolloverTrends | Whether rollover trend data is included. |
TABULAR | Tabular rendering flag. |
| Field | Type | Required (V2) | Description |
|---|---|---|---|
reportingEngine | string | Required | Engine id from §4. |
report | string | Required | Report id from §5. |
startTime | integer (int64) | Required | Start of range, epoch milliseconds. |
endTime | integer (int64) | Required | End of range, epoch milliseconds. |
timeZone | string | Required | IANA time zone. |
page | integer (int32) | Required | Zero-based page index. |
pageSize | integer (int32) | Required | Rows per page. Keep at or below 1000. |
groupBys | array of Group | Required | Dimensions to slice by. |
projections | array of Projection | Required | Metrics to aggregate. |
filters | array of Filter | Required | Filters applied before aggregation. Send [] if you have none. |
jsonResponse | boolean | Required | Response shape toggle — see §12.2. |
sorts | array of Sort | Optional | Result ordering. |
projectionDecorations | array of strings | Optional | Derived columns — see §11.7. |
additional | object | Optional | Free-form options — see §11.6. |
timeField | string | Not documented in V2 | The date field the range applies to. Default comes from the report's dateFieldName (§6.4). |
projectionFilters | array of Filter | Not documented in V2 | Filters applied to aggregated measurement values, after grouping. |
skipResolve | boolean | Not documented in V2 | Suppresses entity resolution. |
| Field | Type | Description |
|---|---|---|
dimensionName | string | Dimension to filter on. Use a fieldName |
filterType | string | Comparison operator. |
values | array | Values to compare against. |
details | object | Additional filter configuration. |
| Field | Type | Description |
|---|---|---|
heading | string | Column heading for this dimension in the response. This is the key you will read in the result rows. |
dimensionName | string | Dimension to group by. |
groupType | string | Grouping strategy. |
details | object | Additional grouping configuration. |
namedFilters | object | Map of name to an array of Filter objects, for named sub-groupings. |
| Field | Type | Description |
|---|---|---|
heading | string | Column heading for this metric in the response. |
measurementName | string | Measurement to aggregate. Use a `fieldName |
aggregateFunction | string | Aggregation to apply. |
details | object | Additional projection configuration. |
| Field | Type | Description |
|---|---|---|
heading | string | The heading to sort by. Must match a heading you defined in groupBys or projections. |
order | string | ASC or DESC. |
Note that sorting is keyed on heading, not on dimensionName or measurementName — so headings must be unique within a request if you intend to sort.
| Key | Documented effect |
|---|---|
SKIP_RESOLVER | Set to true to suppress automatic resolution of CASE / ASSOCIATED_CASE descriptions. Useful when you want raw ids and faster responses. |
Batch sub-requests carry additional key.
All five fields are plain type: string in V3. The values below are taken from the V2 documentation and are the only published list.
filterType — used in filters[] and projectionFilters[]:
| Value | Meaning |
|---|---|
IN | Value is in the supplied list. |
NIN | Value is not in the supplied list. |
EQUALS | Exact match. |
GT | Greater than. |
GTE | Greater than or equal to. |
LT | Less than. |
LTE | Less than or equal to. |
BETWEEN | Within a range. |
STARTS_WITH | String prefix match. |
CONTAINS | Substring match. |
EXISTS | Field is present. |
FILTER | Composite / nested filter. |
groupType — used in groupBys[]:
| Value | Meaning |
|---|---|
FIELD | Group by the raw field value. |
DATE_HISTOGRAM | Bucket by time interval. Requires interval on widget queries. |
TIME_OF_DAY | Bucket by hour of day. |
DAY_OF_WEEK | Bucket by day of week. |
MONTH_OF_YEAR | Bucket by month. |
aggregateFunction — used in projections[]:
| Value | Meaning |
|---|---|
SUM | Total. |
AVG | Mean. |
MIN | Minimum. |
MAX | Maximum. |
STATS | Summary statistics. |
order — used in sorts[]: ASC, DESC.
projectionDecorations — derived columns added alongside a projection:
| Value | Meaning |
|---|---|
CHANGE | Absolute change versus the comparison period. |
PERCENTAGE_CHANGE | Percentage change versus the comparison period. |
PERCENTAGE | Share of total. |
All seven endpoints return the standard APIResponse envelope:
| Field | Type | Description |
|---|---|---|
data | object | The payload. Shape varies by endpoint and by jsonResponse — see below. |
errors | array of Error | Error objects. Empty on success. |
metadata | ResponseMetadata | Response metadata. |
jsonResponse changes the structure of the result, not merely its formatting. This trips up almost everyone migrating.
jsonResponse | Shape | Best for |
|---|---|---|
true | {"data": {"data": [ {heading: value, …} ], "hasMore": false}} — an array of objects, each keyed by heading. | Readability; direct mapping to typed models. |
false | {"data": {"headings": [...], "rows": [[...]]}} — a heading array plus positionally aligned row arrays. | Compactness; large result sets; direct load into a dataframe or CSV. |
Four distinct response shapes appear across the seven endpoints:
| Endpoint | Shape |
|---|---|
GET /reports/engine, GET /reports/report | data is an array of {id, name}. |
GET /reports/metadata, GET /reports/custom-metric | data is an object keyed by report name. |
POST /reports/query, POST /reports/query/widget | data.data + data.hasMore, or data.headings + data.rows, per jsonResponse. |
POST /reports/batchQuery | data.reports, a map keyed by your request keys. |
Every one of the seven operations declares exactly these five:
| Code | Meaning | Typical cause |
|---|---|---|
200 | Success | — |
400 | Bad Request | Malformed body; unknown dimension or measurement; pageSize above your partner limit; invalid time range. |
401 | Unauthorized | Missing, expired or invalid access token. |
403 | Forbidden | Token valid but the user lacks reporting or workspace access. |
404 | Not Found | Unknown widgetId, engine id or report name. |
| Operation | V2 | V3 | Change |
|---|---|---|---|
| Custom query | POST /api/v2/reports/query | POST /api/v3/reports/query | Version only. |
| Custom query using widget id | POST /api/v2/reports/query/{widgetId} | POST /api/v3/reports/query/widget?widgetId={id} | Breaking. Id moves from path to query and the path gains a /widget segment. |
| Batch query | POST /api/v2/reports/batchQuery | POST /api/v3/reports/batchQuery | Version only. |
| Fetch reporting engines | GET /api/v2/reports/engines | GET /api/v3/reports/engine | Breaking. Plural → singular. |
| Fetch report names | GET /api/v2/reports/reports/{reportingEngineId} | GET /api/v3/reports/report?reportingEngineId={id} | Breaking. Doubled reports/reports collapses to singular report; id moves from path to query. |
| Fetch custom metrics | GET /api/v2/reports/customMetric/{reportingEngineId}?reportNames={name} | GET /api/v3/reports/custom-metric?reportingEngineId={id}&reportNames={name} | Breaking. camelCase → kebab-case; id moves from path to query. |
| Fetch metrics and dimensions | GET /api/v2/reports/metadata/{reportingEngineId}?reportNames={name} | GET /api/v3/reports/metadata?reportingEngineId={id}&reportNames={name} | Breaking. Id moves from path to query. |