Skip to content

Reporting API V3 — Developer Guide

  • Applies to: Sprinklr Reporting API, version 3 (/api/v3/reports/*), OpenAPI tag Reporting 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

1. Overview

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.

1.1 The four concepts you need

Reporting is a four-level hierarchy. You must resolve each level before you can query.

ConceptWhat it isHow to discover it
Reporting engineThe data domain — Listening, Paid, Inbound Analytics, Voice, and so on. Identified by an id such as PLATFORM or INBOUND_MESSAGE.GET /reports/engine
ReportA 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

1.2 Which query endpoint should I use?

If you…UseWhy
Want data for a widget that already exists on a dashboardPOST /reports/query/widgetThe 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 expressPOST /reports/queryFull control over filters, groupBys, projections, sorts.
Need several queries answered in one round trip, or your widget draws from more than one report typePOST /reports/batchQueryV2: "If the configured metrics and dimensions in a widget are being pulled from multiple report types, batch query API is used."

1.3 The Generate API Payload workflow

The intended path to a working payload is not to hand-write one. Build the widget in the UI, then export its payload:

  1. Create a dashboard and add a widget that shows the data you want.
  2. Grant your user the Generate Widget API Payload role permission — Governance Console → All Settings → Workspace Roles (or Global Roles) → Create/Edit Role.
  3. On the widget, open the three-dot menu → Generate API v2 Payload.
  4. 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.

1.4 Prerequisites

  • 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 Payload permission if you intend to export payloads from the UI.

1.5 Conventions used in this guide

  • 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.

2. Base URLs and environments

{base} = https://{host}/{env}

Full request path:

{base}/api/v3/reports/{operation}
SegmentValue
{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

3. Authentication and common headers

All seven endpoints use the same headers. The V2 pages document four:

HeaderValueRequiredNotes
AuthorizationBearer {{accessToken}}YesOAuth 2.0 access token.
Key{{apiKey}}YesYour Developer Portal API key. The V2 pages show the literal placeholder value api-key; substitute your own key.
Content-Typeapplication/jsonOn POSTRequired for the three query endpoints.
Acceptapplication/jsonRecommendedDeclares the acceptable response type.

Header casing note: HTTP header names are case-insensitive, so Key and key are equivalent.


Discovery endpoints

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.


4. GET /reports/engine — List reporting engines

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.

4.1 Parameters

None. The result is scoped implicitly to the partner and user behind the access token.

4.2 Example request

curl -X GET \
  'https://api3.sprinklr.com/{env}/api/v3/reports/engine' \
  -H 'Authorization: Bearer {{accessToken}}' \
  -H 'Key: {{apiKey}}' \
  -H 'Accept: application/json'

4.3 Example response

{
  "data": [
    { "id": "PLATFORM", "name": "Social Analytics" },
    { "id": "INBOUND_MESSAGE", "name": "Inbound Analytics" },
    { "id": "LISTENING", "name": "Listening" }
  ],
  "errors": []
}

4.4 Reporting engines

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.

idname
ADOPTIONAdoption
ADOPTION_ENGAGEMENTAdoption Engagement
AUDIENCEAudience
AUDIENCE_ACTIVITYAudience Activity
AUDIENCE_INSIGHTSAudience Insights
AUDIENCE_INSIGHTSocial DMP
AUDIENCE_LEADAUDIENCE_LEAD
BENCHMARKINGBenchmarking
SELF_SERVE_BENCHMARKINGBenchmarking
COMMUNITYCommunity
CONSUMPTIONConsumption Analytics
CUSTOM_ENTITYCustom Entity
GALLERY_AUDIENCE_ACTIVITYGallery
INBOUND_MESSAGEInbound Analytics
LISTENINGListening
RDB_FIREHOSEListening Explorer
SELF_SERVE_RDB_FIREHOSEListening Explorer
LIVE_DATASETLive Dataset
LYEARN_REPORTING_ENGINELYEARN_REPORTING_ENGINE
MONITORING_LOGMonitoring Log
OUTBOUND_MESSAGEOutbound Message
PAIDPaid
PLATFORMSocial Analytics
PLATFORM_HEALTHPlatform Health
REAL_TIMEReal Time
SELF_SERVE_MESSAGESelf Serve
SELF_SERVE_LISTENINGSelf Serve
SPR_TASKTask
STORE_FRONT_AUDIENCE_ACTIVITYStore
STORY_MESSAGEStory Analytics
SELF_SERVE_STORY_MESSAGEStory Analytics
UNIFIED_ANALYTICS_REPORTING_ENGINEUnified Analytics
UNIVERSAL_COMMERCE_EVENT_ENGINEUniversal Commerce
UNIVERSAL_PROFILEUniversal Profile
VOICEVoice Analytics
VOICE_SEGMENT_ACTIVATION_CONFIGVOICE_SEGMENT_ACTIVATION_CONFIG
YOUTUBE_REPORTING_ENGINEYouTube Analytics
wfm_reportingwfm_reporting

Three things to note before you build a UI on top of this list:

  • name is not unique. Benchmarking, Listening Explorer, Self Serve and Story Analytics each appear twice under different ids. Key your code on id, and if you present a picker, disambiguate the duplicates yourself.
  • id casing is not uniform. wfm_reporting is 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.

5. GET /reports/report — List report names

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.

5.1 Parameters

ParameterInRequiredTypeDescription
reportingEngineIdquerySee notestringThe reporting engine id, for example PLATFORM. Obtain it from GET /reports/engine.

5.2 Example request

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'

5.3 Example response

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": []
}

5.4 Response parameters

ParameterTypeDescription
dataarrayOne object per report enabled for the engine.
data[].idstringReport identifier. Pass this as report in a query body.
data[].namestringDisplay name. In practice identical to id for most reports.
errorsarrayError 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.


6. GET /reports/metadata — Fetch metrics and dimensions

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.

6.1 Parameters

ParameterInRequired (V3 spec)Required (V2)TypeDescription
reportingEngineIdqueryfalseRequiredstringReporting engine id.
reportNamesqueryfalseRequiredstringOptional comma-separated report names; omit to return all reports.

6.2 Example request

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_INSIGHTS

6.3 Example response

Heavily 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": []
}

6.4 Response parameters

ParameterTypeDescription
dataobjectKeyed by report name — one entry per report you requested.
data.{reportName}objectMetadata for that report.
data.{reportName}.recordTypestringRecord type, for example LIFETIME.
data.{reportName}.measurementsarrayMeasurement (metric) objects. The fieldName of each is what you put in projections[].measurementName.
data.{reportName}.dimensionsarrayDimension objects. The fieldName of each is what you put in groupBys[].dimensionName and filters[].dimensionName.
data.{reportName}.filterDimensionsarrayDimension objects usable specifically for filtering.
data.{reportName}.oldCustomFieldDimensionobjectLegacy custom-field dimension details.
data.{reportName}.oldCustomFieldDimensionNamestringName of the legacy custom-field dimension.
data.{reportName}.skipVisibilityFiltersbooleanWhether visibility filters are bypassed for this report.
data.{reportName}.displayNamestringDisplay name of the report.
data.{reportName}.dateFieldNamestringThe field used as the date field — a good default for timeField in a query body.
errorsarrayError objects, empty on success.

Commonly useful fields on each measurement and dimension object:

FieldTypeMeaning
name / fieldNamestringThe identifier to use in a query. Use fieldName.
displayNamestringHuman-readable label as shown in the UI.
dataTypestringFor example NUMERIC, TIME_DIFFERENCE.
typestringFor example CUMULATIVE, DELTA, SCRIPT, CUSTOM.
measurementGroupsarrayGroups the measurement belongs to, for example COMMON, FACEBOOK, VK.
channelTypesarrayChannels the measurement applies to.
hiddenbooleanHidden measurements are generally not intended for direct use.
filterMeasurement / filterDimensionbooleanWhether the field may be used in projectionFilters / filters.
multiValuebooleanWhether a dimension can hold multiple values per record.
sortablebooleanWhether the field can be used in sorts.
lookupSupportedbooleanWhether the dimension's values can be resolved through a lookup.
translatablebooleanWhether the dimension's values can be translated.
dashboardGroupsarrayThe dashboard groups the dimension is exposed in, for example PARTNER_DASHBOARD, OVERALL_DASHBOARD, QM_DASHBOARDS.

6.5 Resolving a custom property to its UI label

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.


7. GET /reports/custom-metric — Fetch custom metrics

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.

7.1 Parameters

ParameterInRequired (V3 spec)Required (V2)TypeDescription
reportingEngineIdqueryfalseRequiredstringReporting engine id.
reportNamesqueryfalseRequiredstringOptional comma-separated report names; omit for all reports.

7.2 Example request

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'

7.3 Example response

{
  "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.

7.4 Response parameters

ParameterTypeDescription
dataobjectContainer keyed by report name.
data.{reportName}arrayCustom measurement objects for that report.
data.{reportName}[].scriptstringThe formula evaluated to produce the metric, expressed over __formula__elem__* placeholders.
data.{reportName}[].requiredProjectionsarrayThe standard measurements the formula depends on. Each has a key (matching a placeholder in script), a measurement name, and an aggregateFunction.
data.{reportName}[].typestringMeasurement type, for example CALCULATED, DELTA.
data.{reportName}[].measurementGroupsarrayGroups the measurement belongs to.
data.{reportName}[].groupNamesarrayGroup display names, typically Custom Measurement.
data.{reportName}[].isSharedbooleanWhether the measurement is shared.
data.{reportName}[].sharedKeystringKey for shared measurements.
data.{reportName}[].filterMeasurementbooleanWhether the measurement can be used in projectionFilters.
data.{reportName}[].name / fieldNamestringIdentifier to use in projections[].measurementName.
data.{reportName}[].displayNamestringDisplay label.
data.{reportName}[].lcNamestringLower-cased display name.
data.{reportName}[].shortNamestringAbbreviated label.
data.{reportName}[].hiddenbooleanWhether the measurement is hidden in the UI.
data.{reportName}[].enabledForAiConciergebooleanWhether the measurement is exposed to AI Concierge.
data.{reportName}[].dataTypestringFor example NUMERIC, TIME_DIFFERENCE.
data.{reportName}[].filtersarrayFilters baked into the custom measurement definition.
data.{reportName}[].additionalobjectDefinition metadata — definitionId, clientId, measurement_type, IS_PERMISSIBLE.
data.{reportName}[].channelTypesarrayChannels the measurement applies to.
data.{reportName}[].codestringInternal label code.
errorsarrayError 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.


Query endpoints


8. POST /reports/query — Custom query

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.

8.1 Parameters

No path or query parameters. Everything is in the body — see §11.1.

8.2 Example request

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
  }'

8.3 Example response

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.

8.4 Response parameters

ParameterTypeDescription
dataobjectResult container.
data.dataarrayResult rows. Each key corresponds to a heading you supplied in groupBys or projections.
data.hasMorebooleantrue if further rows are available beyond this page. See §12.3.
errorsarrayError objects, empty on success.

9. POST /reports/query/widget — Custom query using widget id

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.

9.1 Parameters

ParameterInRequired (V3 spec)TypeDescription
widgetIdqueryfalsestringWidget id.
replaceHeadingsWithLabelqueryfalsebooleanForwarded to the underlying widget request.

9.2 Finding the widget id

  1. Open the dashboard containing the widget.
  2. Widget three-dot menu → Generate API v2 Payload → Copy Code.
  3. In the copied payload, locate widgetId inside the additional object.

9.3 Request body fields

WidgetReportRequest defines only eight fields.

FieldTypeRequired (V2 page)Description
startTimeinteger (int64)RequiredStart of the time range, epoch milliseconds.
endTimeinteger (int64)RequiredEnd of the time range, epoch milliseconds.
pageinteger (int32)RequiredZero-based page index.
pageSizeinteger (int32)OptionalRows per page. Keep at or below 1000 — see the warning below.
intervalstringOptionalBucket interval. Only required when the widget uses "groupType": "DATE_HISTOGRAM".
skipResolvebooleanRequiredDefault false. When true, suppresses resolution of referenced entities.
jsonResponsebooleanRequiredDefault false. Controls response shape — see §12.2.
timeZonestringRequiredIANA time zone, for example America/New_York.

9.4 Example request

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
  }'

9.5 Example response

With jsonResponse set to false, the widget endpoint returns the columnar form:

{
  "data": {
    "headings": ["Channel", "Followers"],
    "rows": [
      ["FACEBOOK", 128394],
      ["TWITTER", 94021]
    ]
  },
  "errors": []
}

9.6 Response parameters

ParameterTypeDescription
dataobjectResult container.
data.headingsarray of stringsColumn headings, in the order the widget defines them.
data.rowsarray of arraysResult rows. Each inner array is positionally aligned with headings.
errorsarrayError objects, empty on success.

10. POST /reports/batchQuery — Batch query

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.

10.1 Request body fields

FieldTypeRequired (V2 page)Description
requestsobjectRequiredA map of arbitrary caller-chosen keys to ReportRequest objects. The keys you send are echoed back in the response.
collatebooleanOptionalDefault false. Groups multiple queries together in the response.

10.2 Example request

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
  }'

10.3 Example response

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": []
}

10.4 Response parameters

ParameterTypeDescription
dataobjectResult container.
data.reportsobjectMap keyed by your request keys.
data.reports.{key}objectResult for that sub-query, in the same headings/rows form as.
errorsarrayError objects, empty on success.

10.5 The additional object in batch payloads

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-fieldPurpose
translateResponseWhether the response should be translated.
dashboardIdSource dashboard identifier.
engineReporting engine for the sub-request.
widgetIdSource widget identifier.
showTotalWhether to include a total row.
CurrencyCurrency for monetary measurements.
chartTypeChart type the widget renders.
showRolloverTrendsWhether rollover trend data is included.
TABULARTabular rendering flag.

11.1 ReportRequest

FieldTypeRequired (V2)Description
reportingEnginestringRequiredEngine id from §4.
reportstringRequiredReport id from §5.
startTimeinteger (int64)RequiredStart of range, epoch milliseconds.
endTimeinteger (int64)RequiredEnd of range, epoch milliseconds.
timeZonestringRequiredIANA time zone.
pageinteger (int32)RequiredZero-based page index.
pageSizeinteger (int32)RequiredRows per page. Keep at or below 1000.
groupBysarray of GroupRequiredDimensions to slice by.
projectionsarray of ProjectionRequiredMetrics to aggregate.
filtersarray of FilterRequiredFilters applied before aggregation. Send [] if you have none.
jsonResponsebooleanRequiredResponse shape toggle — see §12.2.
sortsarray of SortOptionalResult ordering.
projectionDecorationsarray of stringsOptionalDerived columns — see §11.7.
additionalobjectOptionalFree-form options — see §11.6.
timeFieldstringNot documented in V2The date field the range applies to. Default comes from the report's dateFieldName (§6.4).
projectionFiltersarray of FilterNot documented in V2Filters applied to aggregated measurement values, after grouping.
skipResolvebooleanNot documented in V2Suppresses entity resolution.

11.2 Filter_reporting

FieldTypeDescription
dimensionNamestringDimension to filter on. Use a fieldName
filterTypestringComparison operator.
valuesarrayValues to compare against.
detailsobjectAdditional filter configuration.

11.3 Group_reporting

FieldTypeDescription
headingstringColumn heading for this dimension in the response. This is the key you will read in the result rows.
dimensionNamestringDimension to group by.
groupTypestringGrouping strategy.
detailsobjectAdditional grouping configuration.
namedFiltersobjectMap of name to an array of Filter objects, for named sub-groupings.

11.4 Projection_reporting

FieldTypeDescription
headingstringColumn heading for this metric in the response.
measurementNamestringMeasurement to aggregate. Use a `fieldName
aggregateFunctionstringAggregation to apply.
detailsobjectAdditional projection configuration.

11.5 Sort_reporting

FieldTypeDescription
headingstringThe heading to sort by. Must match a heading you defined in groupBys or projections.
orderstringASC 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.

11.6 The additional object

KeyDocumented effect
SKIP_RESOLVERSet 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.

11.7 Reference enums

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[]:

ValueMeaning
INValue is in the supplied list.
NINValue is not in the supplied list.
EQUALSExact match.
GTGreater than.
GTEGreater than or equal to.
LTLess than.
LTELess than or equal to.
BETWEENWithin a range.
STARTS_WITHString prefix match.
CONTAINSSubstring match.
EXISTSField is present.
FILTERComposite / nested filter.

groupType — used in groupBys[]:

ValueMeaning
FIELDGroup by the raw field value.
DATE_HISTOGRAMBucket by time interval. Requires interval on widget queries.
TIME_OF_DAYBucket by hour of day.
DAY_OF_WEEKBucket by day of week.
MONTH_OF_YEARBucket by month.

aggregateFunction — used in projections[]:

ValueMeaning
SUMTotal.
AVGMean.
MINMinimum.
MAXMaximum.
STATSSummary statistics.

order — used in sorts[]: ASC, DESC.

projectionDecorations — derived columns added alongside a projection:

ValueMeaning
CHANGEAbsolute change versus the comparison period.
PERCENTAGE_CHANGEPercentage change versus the comparison period.
PERCENTAGEShare of total.

12. Response format and status codes

12.1 The envelope

All seven endpoints return the standard APIResponse envelope:

FieldTypeDescription
dataobjectThe payload. Shape varies by endpoint and by jsonResponse — see below.
errorsarray of ErrorError objects. Empty on success.
metadataResponseMetadataResponse metadata.

12.2 The jsonResponse toggle

jsonResponse changes the structure of the result, not merely its formatting. This trips up almost everyone migrating.

jsonResponseShapeBest 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:

EndpointShape
GET /reports/engine, GET /reports/reportdata is an array of {id, name}.
GET /reports/metadata, GET /reports/custom-metricdata is an object keyed by report name.
POST /reports/query, POST /reports/query/widgetdata.data + data.hasMore, or data.headings + data.rows, per jsonResponse.
POST /reports/batchQuerydata.reports, a map keyed by your request keys.

12.4 Status codes

Every one of the seven operations declares exactly these five:

CodeMeaningTypical cause
200Success—
400Bad RequestMalformed body; unknown dimension or measurement; pageSize above your partner limit; invalid time range.
401UnauthorizedMissing, expired or invalid access token.
403ForbiddenToken valid but the user lacks reporting or workspace access.
404Not FoundUnknown widgetId, engine id or report name.

13. V2 → V3 migration

13.1 Endpoint mapping

OperationV2V3Change
Custom queryPOST /api/v2/reports/queryPOST /api/v3/reports/queryVersion only.
Custom query using widget idPOST /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 queryPOST /api/v2/reports/batchQueryPOST /api/v3/reports/batchQueryVersion only.
Fetch reporting enginesGET /api/v2/reports/enginesGET /api/v3/reports/engineBreaking. Plural → singular.
Fetch report namesGET /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 metricsGET /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 dimensionsGET /api/v2/reports/metadata/{reportingEngineId}?reportNames={name}GET /api/v3/reports/metadata?reportingEngineId={id}&reportNames={name}Breaking. Id moves from path to query.