Synchronous Reports Quick Start
Some reports can be retrieved synchronously — instead of creating a report, waiting for it to finish, and downloading a file, you request the results directly and receive the rows in the API response, a page at a time. This guide walks through that synchronous workflow.
Synchronous reporting is only available to accounts that have access to the synchronous reports functionality, and only report definitions that support the synchronous (SYNC) flow are returned. For file-based (asynchronous) reports, see the Reports Quick Start.
Authentication
All requests are made against the base URL https://insights.bandwidth.com/api. Authenticate each request with a Bearer token:
Authorization: Bearer <token>
HTTP Basic authentication (username:password) is also supported.
The synchronous workflow
The synchronous flow uses the v2 Reporting endpoints (/v2/report-definitions) — these are separate from the /v1/reports endpoints used for the asynchronous, file-based flow in the Reports Quick Start.
- List report definitions to discover which synchronous reports you can run and get each report's
reportDefinitionId. - Get a report definition to inspect its filters, operators, value types, required parameters, and output fields.
- Generate results by posting your query criteria, and page through the response.
Step 1: List report definitions
Use Get Report Definitions to list the synchronous report definitions available to your accounts. Narrow the list with the category, domain, and reportName query parameters, and page through it with the offset and limit query parameters. The page object in the response reports the pagination metadata (pageSize, totalElements, totalPages, pageNumber) for the returned page.
GET /v2/report-definitions?category=USAGE&domain=VOICE
Each item is a full report definition: its id (the reportDefinitionId), category, domain, name, description, the regions it covers, maxMonthsBack, the filters it accepts, the outputFields returned in each result row, and the supportedModes (execution flows) it supports.
{
"links": [],
"data": {
"reportDefinitions": [
{
"id": "6d4f848a-9543-4e18-b580-2621c9525892",
"category": "USAGE",
"domain": "VOICE",
"reportName": "Call Detail Records (CDRs)",
"description": "Call Detail Records (CDRs) provides details for all the Voice calls associated with your account. Data may be delayed by a few hours.",
"regions": ["US", "EU"],
"maxMonthsBack": 12,
"filters": [
{
"filterName": "accountIds",
"validationType": "INTEGER",
"operator": "IN",
"required": true
},
{
"filterName": "callInviteTime",
"validationType": "ISO8601",
"operator": "GREATER_OR_EQUAL",
"required": true
},
{
"filterName": "callInviteTime",
"validationType": "ISO8601",
"operator": "LESSER_OR_EQUAL",
"required": true
},
{
"filterName": "callDirection",
"operator": "EQUAL",
"required": false,
"allowedValues": ["inbound", "outbound"]
}
],
"outputFields": [
{ "fieldName": "customerId", "fieldType": "STRING" },
{ "fieldName": "callDate", "fieldType": "STRING" },
{ "fieldName": "callId", "fieldType": "STRING" },
{ "fieldName": "callStartTime", "fieldType": "STRING" },
{ "fieldName": "duration", "fieldType": "INTEGER" },
{ "fieldName": "result", "fieldType": "STRING" },
{
"fieldName": "destinationPhoneNumber",
"fieldType": "STRING"
},
{ "fieldName": "sourcePhoneNumber", "fieldType": "STRING" }
],
"supportedModes": ["SYNC"]
}
]
},
"page": {
"pageSize": 50,
"totalElements": 1,
"totalPages": 1,
"pageNumber": 0
},
"errors": []
}
Step 2: Get a report definition
Use Get Report Definition with the reportDefinitionId to retrieve the full definition. The response contains everything needed to build a results request: the regions the report covers, its maxMonthsBack, the complete list of filter parameters — each with its supported operators, value type, and whether it is required — and the output fields returned in each result row.
GET /v2/report-definitions/6d4f848a-9543-4e18-b580-2621c9525892
{
"links": [
{
"rel": "self",
"href": "https://insights.bandwidth.com/api/v2/report-definitions/6d4f848a-9543-4e18-b580-2621c9525892"
}
],
"data": {
"id": "6d4f848a-9543-4e18-b580-2621c9525892",
"category": "USAGE",
"domain": "VOICE",
"reportName": "Call Detail Records (CDRs)",
"description": "Call Detail Records (CDRs) provides details for all the Voice calls associated with your account. Data may be delayed by a few hours.",
"regions": ["US", "EU"],
"maxMonthsBack": 12,
"filters": [
{
"filterName": "accountIds",
"validationType": "INTEGER",
"operator": "IN",
"required": true
},
{
"filterName": "callInviteTime",
"validationType": "ISO8601",
"operator": "GREATER_OR_EQUAL",
"required": true
},
{
"filterName": "callInviteTime",
"validationType": "ISO8601",
"operator": "LESSER_OR_EQUAL",
"required": true
},
{
"filterName": "callDirection",
"operator": "EQUAL",
"required": false,
"allowedValues": ["inbound", "outbound"]
}
],
"outputFields": [
{ "fieldName": "customerId", "fieldType": "STRING" },
{ "fieldName": "callDate", "fieldType": "STRING" },
{ "fieldName": "callId", "fieldType": "STRING" },
{ "fieldName": "callStartTime", "fieldType": "STRING" },
{ "fieldName": "duration", "fieldType": "INTEGER" },
{ "fieldName": "result", "fieldType": "STRING" },
{ "fieldName": "destinationPhoneNumber", "fieldType": "STRING" },
{ "fieldName": "sourcePhoneNumber", "fieldType": "STRING" }
],
"supportedModes": ["SYNC"]
},
"errors": []
}
Understanding filters
Each entry in filters tells you how to build a criterion for Step 3:
filterName— theparametername to use in thequeryCriteriarequest body.operator— the operator to use for that criterion (for exampleIN,EQUAL,GREATER_OR_EQUAL,LESSER_OR_EQUAL). A filter can appear more than once with different operators — for examplecallInviteTimeis listed with bothGREATER_OR_EQUALandLESSER_OR_EQUAL, which together let you request a time range (see Step 3).required— whentrue, the criterion must be supplied. In the example above,accountIdsandcallInviteTimeare required.- How the value is validated — a filter is one of two shapes:
- Enumerated — includes an
allowedValueslist; the value you supply must be one of those values (e.g.callDirectionacceptsinboundoroutbound). - Validation-type — includes a
validationType(e.g.INTEGER,ISO8601,STRING) and optionally avalidationRegex; the value you supply must match that type/pattern.
- Enumerated — includes an
Understanding output fields
outputFields describes every field returned in each result row from Step 3. Each entry has a fieldName (the key in the result row) and a fieldType (for example STRING, INTEGER). Use this to know which columns to expect and how to parse them.
If the report covers more than one region (see regions), you must also supply a region criterion when requesting results.
Step 3: Generate report results
Use Generate Report Results to run the report and get its rows synchronously. Supply your filters in the queryCriteria array — each criterion has a parameter, an operator, and a values array. At least one criterion is required. Control paging with pageSize and pageNumber.
POST /v2/report-definitions/6d4f848a-9543-4e18-b580-2621c9525892/results
{
"queryCriteria": [
{
"parameter": "region",
"operator": "EQUAL",
"values": ["US"]
},
{
"parameter": "accountIds",
"operator": "IN",
"values": ["9900000", "9900001"]
},
{
"parameter": "callInviteTime",
"operator": "GREATER_OR_EQUAL",
"values": ["2026-01-01T00:00:00.000Z"]
},
{
"parameter": "callInviteTime",
"operator": "LESSER_OR_EQUAL",
"values": ["2026-01-31T23:59:59.999Z"]
},
{
"parameter": "callDirection",
"operator": "EQUAL",
"values": ["inbound"]
}
],
"pageSize": 50,
"pageNumber": 0
}
The response returns the result rows in data.results, pagination metadata in page, and HATEOAS links you can follow to page through the full result set.
{
"links": [
{
"rel": "self",
"href": "https://insights.bandwidth.com/api/v2/report-definitions/6d4f848a-9543-4e18-b580-2621c9525892/results",
"method": "POST"
},
{
"rel": "first",
"href": "https://insights.bandwidth.com/api/v2/report-definitions/6d4f848a-9543-4e18-b580-2621c9525892/results",
"method": "POST"
},
{
"rel": "last",
"href": "https://insights.bandwidth.com/api/v2/report-definitions/6d4f848a-9543-4e18-b580-2621c9525892/results",
"method": "POST"
}
],
"data": {
"results": [
{
"customerId": "1234567",
"callDate": "2024-01-15",
"callId": "1234567890abcdefghijklmnopqrstuvwxyz",
"callStartTime": "2024-01-15T17:05:48.960Z",
"duration": 120,
"result": "COMPLETED",
"destinationPhoneNumber": "+15554443333",
"sourcePhoneNumber": "+15554442222"
}
]
},
"page": {
"pageSize": 50,
"totalElements": 1,
"totalPages": 1,
"pageNumber": 0
},
"errors": []
}
The fields in each result row vary by report — the exact set is described by the outputFields in the report definition from Step 2.
Paging through results
To retrieve the next page, either follow the pagination links in the response, or repeat the request with an incremented pageNumber. Use page.totalPages and page.totalElements to know how many pages are available.
Next steps
- See the Reports Overview for the report categories and domains, and use Get Report Definitions to discover the reports available to your accounts.
- Need a downloadable file instead of inline results? See the Reports Quick Start.
- Explore the full Insights API Reference.