Data endpoints
GET burst/v1/data/{type} is the primary read API for pulling analytics data out of Burst Statistics. Use it to build external dashboards, feed data pipelines or power AI workflows.
Prerequisites
- Burst Statistics (Free or Pro)
- WordPress user with
view_burst_statisticscapability, or an Application Password for that user - See Authentication for setup
Route
GET /wp-json/burst/v1/data/{type}
GET /wp-json/burst/v1/data/datatable/{id}
GET /wp-json/burst/v1/data/ecommerce/datatable/{id}
Permission: view_burst_statistics (datatable and standard types). Ecommerce datatables additionally require the view_sales_burst_statistics capability.
The {type} path segment selects the data shape returned. Accepted characters: [a-z_-]+.
The {id} path segment selects a specific datatable. Accepted characters: [a-z_-]+. See Granular datatable endpoints below.
The generic data/datatable and data/ecommerce/datatable endpoints now return HTTP 403 for all callers. Switch every datatable request to the granular data/datatable/{id} or data/ecommerce/datatable/{id} routes. The granular routes enforce a per-datatable metric allow-list — metrics not in the allow-list are silently dropped from the response.
Each granular datatable also declares a required capability. Requests from a user who lacks that capability return HTTP 403 with a message of Access denied.. The ecommerce datatables (sales_products, subscription_products) require view_sales_burst_statistics; the remaining datatables require view_burst_statistics.
Request parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
date_start | string (YYYY-MM-DD) | — | Start of the requested period. Normalized to 00:00:00 in the WordPress timezone |
date_end | string (YYYY-MM-DD) | — | End of the requested period. Normalized to 23:59:59 in the WordPress timezone |
date_range | string | — | Optional named range. Accepted values include today, yesterday, last-7-days, last-30-days, last-90-days, week-to-date, month-to-date, year-to-date and all-time |
filters | array / JSON string | [] | Filter payload. Accepts arrays, JSON-encoded arrays/objects or comma-separated strings. Empty strings are removed; 0 is preserved |
metrics | array / string | varies by type | Metric names to include. A single string value is normalized to a single-element array. For datatable endpoints, values are intersected with the per-datatable allow-list; when omitted, the full allow-list for the datatable is returned |
group_by | array / string | varies by type | Grouping fields. A single string value is normalized to a single-element array |
goal_id | int / string | 0 | Goal identifier. Required for goals and live-goals types. Accepts an integer goal ID or the literal all to aggregate every active goal |
compare_mode | string | '' | Comparison mode for the insights type. Accepts previous_period or year_over_year. Any other value is ignored |
compare_date_start | string (YYYY-MM-DD) | — | Custom comparison window start. Normalized to 00:00:00 in the WordPress timezone |
compare_date_end | string (YYYY-MM-DD) | — | Custom comparison window end. Normalized to 23:59:59 in the WordPress timezone |
page_url | string | — | Page URL to break down. Required for the page-parameters type |
isOnboarding | bool | false | Used by the live-visitors onboarding flow; has no effect on other types |
least_engagement | bool | false | Reverses the sort for the reading_engagement type and the reading-engagement datatable so the least-engaged pages are returned first |
chart_mode | string | revenue | Value mode for subscriptions-revenue-chart. Accepts revenue or sales |
distribution_view | string | gateways | Breakdown dimension for subscriptions-distribution. Accepts gateways, currencies or countries |
product_id | int | 0 | Optional product filter for subscriptions-retention |
id | string | — | Datatable identifier. Equivalent to using the data/datatable/{id} path segment and useful when calling the AJAX fallback. Must be one of the granular datatable IDs |
is_ecommerce | bool | false | Routes the request through the ecommerce permission gate. Set automatically when the data/ecommerce/datatable/{id} route is used |
The all-time value is now accepted by date_range. New arguments chart_mode, distribution_view and product_id were added for the subscriptions data types, and id is now a recognised datatable argument.
id is now mandatory whenever a datatable response is requested. The new is_ecommerce flag is forwarded to the permission layer when the ecommerce datatable route is invoked through the AJAX fallback.
The compare_mode argument (previous_period or year_over_year) drives the comparison line for the insights type, while compare_date_start and compare_date_end define a custom comparison window. These three arguments are recognised request parameters and can also be injected through the burst_get_data_request_args filter.
Filter keys
The filters parameter accepts an object where each key maps to a value or array of values. Accepted keys depend on the user's role and whether Burst Pro is active.
All authenticated users (strict mode — viewer role):
| Key | Type | Description |
|---|---|---|
page_type | string / array | Post type (e.g. post, page) |
page_id | int / array | WordPress post ID |
page_url | string / array | Full or partial page URL |
referrer | string / array | Referrer hostname |
device | string / array | Device category: desktop, tablet, mobile, other |
browser | string / array | Browser name |
platform | string / array | Operating system name |
status | string | HTTP response status. 404 returns not-found (404) hits only, 200 returns found pages only and all returns both. Standard data requests exclude 404 hits by default; set this key to include or isolate them |
Admin users (non-strict mode — additional keys):
| Key | Type | Description |
|---|---|---|
goal_id | int | Filter sessions that converted a specific goal |
bounces | bool / int | 1 for bounced sessions only, 0 for non-bounced |
new_visitor | bool / int | 1 for first-time visitors only |
device_id | int / array | Internal device lookup ID |
browser_id | int / array | Internal browser lookup ID |
platform_id | int / array | Internal platform lookup ID |
time_per_session | string | Time-on-site range (e.g. 0-30) |
Country location filters (free):
| Key | Type | Description |
|---|---|---|
country_code | string / array | ISO 3166-1 alpha-2 country code |
continent | string / array | Continent name |
continent_code | string / array | Two-letter continent code |
Burst Pro (additional keys, all roles):
| Key | Type | Description |
|---|---|---|
city | string / array | City name |
state | string / array | State or province name |
source | string / array | UTM source |
medium | string / array | UTM medium |
campaign | string / array | UTM campaign |
term | string / array | UTM term |
content | string / array | UTM content |
Prefix a filter value with ! to exclude it (e.g. "device": "!mobile" excludes mobile sessions).
Keys outside the allowed list for the current role are silently ignored.
Response envelope
All successful responses follow this structure:
Show code
{
"data": {},
"request_success": true,
"success": true
}
On failure, success is false and a message field or empty data is returned with an appropriate HTTP status code.
Types
live-visitors
Returns the current count of active visitors on the site. The live window is approximately 10 minutes with configurable offsets.
Extra parameters: isOnboarding (bool) — enables a simplified count path used during the plugin's onboarding flow.
Response:
Show code
{
"data": {
"visitors": 12
},
"request_success": true,
"success": true
}
live-traffic
Returns the most recent traffic rows within the live window (max 100 rows). Use this to build a real-time activity feed.
Response — data is an indexed array of row objects:
| Field | Type | Description |
|---|---|---|
uid | string | Anonymous visitor identifier |
page_url | string | URL of the page visited |
time | int | Unix timestamp of the hit |
time_on_page | int | Seconds spent on the page |
active_time | int | Active (non-idle) seconds |
utm_source | string | Session referrer or UTM source |
entry | bool | Whether this is the session's entry page |
checkout | bool | Whether a checkout event was recorded |
exit | bool | Whether this is the session's exit page |
Show code
{
"data": [
{
"uid": "a1b2c3d4",
"page_url": "/shop/product-name/",
"time": 1714000000,
"time_on_page": 45,
"active_time": 30,
"utm_source": "google",
"entry": true,
"checkout": false,
"exit": false
}
],
"request_success": true,
"success": true
}
today
Returns the summary metrics shown in the Burst "Today" card. Accepts date_start and date_end to query any period, not just today.
Response — data fields:
| Field | Type | Description |
|---|---|---|
live | { value } | Current live visitor count |
today | { value } | Unique visitors for the period |
mostViewed | { title, value } | Most viewed page title and view count |
referrer | { title, value } | Top referrer hostname and session count |
pageviews | { title, value } | Total pageview count |
timeOnPage | { title, value } | Average time on page (formatted string) |
Show code
{
"data": {
"live": { "value": "12" },
"today": { "value": "348" },
"mostViewed": { "title": "Most viewed", "value": "/blog/" },
"referrer": { "title": "Top referrer", "value": "google.com" },
"pageviews": { "title": "Pageviews", "value": "512" },
"timeOnPage": { "title": "Avg. time on page", "value": "1:24" }
},
"request_success": true,
"success": true
}
goals
Returns goal statistics for the selected period. Requires goal_id.
Extra parameters: goal_id (int or all, required) — pass all to aggregate every active goal into a single combined result.
Response — data fields:
| Field | Type | Description |
|---|---|---|
goalId | int / string | The requested goal ID, or all for the combined result |
status | string | Goal status |
dateCreated | string | ISO date the goal was created |
dateStart | string | Period start date |
dateEnd | string | Period end date |
today | { value, title, tooltip } | Conversions today |
total | { value, title, tooltip } | Total conversions in the period |
topPerformer | { value, title } | Top converting page |
conversionMetric | { value, title, tooltip } | Primary conversion metric |
conversionPercentage | { value, title, tooltip } | Conversion rate for the period |
bestDevice | { value, title, icon } | Device with the highest conversion rate |
live-goals
Returns the live conversion count for a single goal. Requires goal_id.
Extra parameters: goal_id (int or all, required) — pass all to count live conversions across every active goal.
Response:
Show code
{
"data": {
"goals_count": 3
},
"request_success": true,
"success": true
}
insights
Returns time-series chart data for the selected period. This is the data behind the main insights graph.
Extra parameters:
| Parameter | Notes |
|---|---|
metrics | Default: ["pageviews", "visitors"]. Pass additional metric names to include extra datasets |
group_by | Controls the time interval. Accepts hour, day, week, month, year or auto. auto selects an interval based on the date range |
compare_mode | Optional. previous_period or year_over_year. When set and exactly one metric is selected, the response appends a comparison dataset for the matching window |
The response no longer returns a pre-formatted labels array. Instead it returns raw timestamps, the resolved interval and a spans_multiple_years flag so the client can format dates with Intl.DateTimeFormat (or any server-side formatter) and decide whether to include the year.
Response — data fields:
| Field | Type | Description |
|---|---|---|
timestamps | int[] | UTC Unix timestamps, one per period bucket |
interval | string | Resolved interval: hour, day, week, month or year |
spans_multiple_years | bool | Whether the range crosses a year boundary |
datasets | array | One object per metric (see below) |
Each dataset object:
| Field | Type | Description |
|---|---|---|
label | string | Human-readable metric name |
data | number[] | One value per timestamp bucket |
backgroundColor | string | Hex colour for the chart fill |
borderColor | string | Hex colour for the chart line |
fill | bool | Whether to fill the area under the line |
metric_key | string | Raw metric key for the dataset |
is_comparison | bool | Whether this dataset holds comparison-period values |
comparison_timestamps | int[] | Present on comparison datasets — the actual timestamps of the comparison period, aligned to the current-period x-axis |
compare_mode | string | Present on comparison datasets — the comparison mode used |
When compare_mode is set and exactly one metric is selected, an extra dataset is appended with is_comparison set to true. It carries the comparison-period values aligned to the current period's x-axis plus a comparison_timestamps array so the client can show the real comparison date in tooltips. The comparison dataset is only emitted for single-metric requests.
Show code
{
"data": {
"timestamps": [1714521600, 1714608000, 1714694400],
"interval": "day",
"spans_multiple_years": false,
"datasets": [
{
"label": "Pageviews",
"data": [512, 489, 601],
"backgroundColor": "#ECF4ED",
"borderColor": "#2B8133",
"fill": true,
"metric_key": "pageviews",
"is_comparison": false
},
{
"label": "Visitors",
"data": [348, 312, 401],
"backgroundColor": "#FFF8DC",
"borderColor": "#FFDA4A",
"fill": false,
"metric_key": "visitors",
"is_comparison": false
}
]
},
"request_success": true,
"success": true
}
compare
Returns aggregated metrics for the current period alongside the same metrics for the previous period of equal length. Useful for period-over-period comparisons.
When goal_id is set in filters, the response switches to goal-specific metrics.
Response — standard (no goal):
Show code
{
"data": {
"current": {
"pageviews": 512,
"sessions": 280,
"visitors": 348,
"first_time_visitors": 210,
"avg_time_on_page": 84,
"bounced_sessions": 112,
"bounce_rate": 40.0
},
"previous": {
"pageviews": 489,
"sessions": 265,
"visitors": 312,
"bounced_sessions": 104,
"bounce_rate": 39.2
}
},
"request_success": true,
"success": true
}
Response — goal variant (goal_id present in filters):
Show code
{
"data": {
"current": {
"pageviews": 512,
"visitors": 348,
"sessions": 280,
"first_time_visitors": 210,
"conversions": 42,
"conversion_rate": 15.0
},
"previous": {
"pageviews": 489,
"visitors": 312,
"sessions": 265,
"conversions": 38,
"conversion_rate": 14.3
}
},
"request_success": true,
"success": true
}
The previous period is calculated automatically as the same-length window immediately before date_start. To supply a custom comparison window, pass compare_date_start and compare_date_end as request parameters, or inject them via the burst_get_data_request_args filter — see Filters reference.
devicestitleandvalue
Returns visitor counts broken down by device category.
Response:
Show code
{
"data": {
"all": { "count": 348 },
"desktop": { "count": 210 },
"mobile": { "count": 98 },
"tablet": { "count": 30 },
"other": { "count": 10 }
},
"request_success": true,
"success": true
}
all is the sum of the named categories. Additional device names from the internal lookup table may appear as extra keys.
devicessubtitle
Returns secondary detail (OS, browser, internal ID) for each device category. Intended to power the sub-row display under the devices panel.
Response — data keys are device names (desktop, tablet, mobile, other):
Show code
{
"data": {
"desktop": {
"os": "Windows",
"browser": "Chrome",
"device_id": 1
},
"mobile": {
"os": "iOS",
"browser": "Safari",
"device_id": 2
},
"tablet": {
"os": "Android",
"browser": "Chrome",
"device_id": 3
},
"other": {
"os": "",
"browser": "",
"device_id": 0
}
},
"request_success": true,
"success": true
}
reading_engagement
Returns the average time on page for each tracked page URL within the period, ordered by engagement. Powers the reading engagement panel.
Extra parameters: least_engagement (bool) — when true, rows are ordered ascending so the least-engaged pages are returned first. date_start and date_end define the window.
Response — data is an indexed array of row objects:
| Field | Type | Description |
|---|---|---|
page_url | string | The page URL |
avg_time_on_page | int | Average time on page in seconds |
Show code
{
"data": [
{ "page_url": "/blog/long-read/", "avg_time_on_page": 214 },
{ "page_url": "/about/", "avg_time_on_page": 96 }
],
"request_success": true,
"success": true
}
search_terms
Returns the top on-site search terms recorded within the period, with their occurrence volume and the largest result count seen for each term. Powers the search terms panel.
Extra parameters: date_start and date_end define the window.
Response — data is an indexed array of row objects:
| Field | Type | Description |
|---|---|---|
term | string | The search term |
volume | int | Number of times the term was searched in the period |
results | int | Largest result count returned for the term in the period |
Show code
{
"data": [
{ "term": "pricing", "volume": 48, "results": 6 },
{ "term": "contact", "volume": 21, "results": 3 }
],
"request_success": true,
"success": true
}
not_found_pages
Returns the top page URLs that produced a 404 (not found) response within the period, with a hit count per URL. Powers the not-found pages panel on the engagement tab. 404 hits are stored with an internal page_type of 404 and are excluded from every other data type, so this type is the way to surface them.
Extra parameters: date_start and date_end define the window. filters accepts the standard filter object; the status filter is forced to 404 for this type.
Response — data is an indexed array of row objects:
| Field | Type | Description |
|---|---|---|
page_url | string | The requested URL that returned a 404 |
hits | int | Number of 404 hits recorded for the URL in the period |
Show code
{
"data": [
{ "page_url": "/old-landing-page/", "hits": 87 },
{ "page_url": "/blog/removed-post/", "hits": 24 }
],
"request_success": true,
"success": true
}
page-parameters
Pro - CreatorAvailable in the Creator tier
Requires Burst Pro. See Analyze incoming URL parameters.
Returns the URL parameter variations recorded for a single page within the period, with pageview and visitor counts. Powers the progressively loaded parameter variations accordion shown under each pages row.
Extra parameters: page_url (string, required) — the page URL to break down. date_start and date_end are also required; an empty page_url or missing date range returns the column definitions with an empty data array.
Response — datatable-shaped data:
| Field | Type | Description |
|---|---|---|
columns | array | Column definitions (parameter, pageviews, visitors) |
data | array | Row objects with parameter, pageviews and visitors |
Show code
{
"data": {
"columns": [
{ "name": "Parameter", "id": "parameter", "sortable": "true", "right": "false" },
{ "name": "Pageviews", "id": "pageviews", "sortable": "true", "right": "true" },
{ "name": "Visitors", "id": "visitors", "sortable": "true", "right": "true" }
],
"data": [
{ "parameter": "utm_source=google", "pageviews": 124, "visitors": 98 },
{ "parameter": "ref=newsletter", "pageviews": 42, "visitors": 30 }
]
},
"request_success": true,
"success": true
}
page-parameter-counts
Pro - CreatorAvailable in the Creator tier
Requires Burst Pro. See Analyze incoming URL parameters.
Returns a flat map of page URL to the number of distinct parameter variations recorded in the period. Used to render the "n variations" badge and the expandable-row indicator on the pages datatable without inflating that query.
Extra parameters: date_start and date_end (both required). A missing date range returns an empty object.
Response — data is an object keyed by page URL:
Show code
{
"data": {
"/blog/": 4,
"/shop/": 2
},
"request_success": true,
"success": true
}
sources-over-time
Pro - CreatorAvailable in the Creator tier
Requires Burst Pro. See Referral source analysis.
Returns visitor counts per source category bucketed over the selected period. Powers the source category chart on the Sources tab. Each hit's referrer, UTM campaign and click IDs are classified into one of seven categories: search, social, referral, aiReferral, paid, email and direct.
Extra parameters:
| Parameter | Notes |
|---|---|
group_by | Bucket size. Accepts hour, day, week, month or auto. auto resolves the interval from the date range |
date_start | Period start |
date_end | Period end |
filters | Standard filter object |
Response — data fields:
| Field | Type | Description |
|---|---|---|
timestamps | int[] | One UTC Unix timestamp per bucket |
search | number[] | Visitors classified as search traffic, aligned to timestamps |
social | number[] | Visitors classified as social traffic |
referral | number[] | Visitors classified as referral traffic |
aiReferral | number[] | Visitors classified as AI referral traffic |
paid | number[] | Visitors classified as paid traffic |
email | number[] | Visitors classified as email traffic |
direct | number[] | Visitors classified as direct or unknown traffic |
Show code
{
"data": {
"timestamps": [1714521600, 1714608000, 1714694400],
"search": [120, 98, 140],
"social": [40, 52, 38],
"referral": [22, 18, 27],
"aiReferral": [8, 12, 15],
"paid": [30, 24, 41],
"email": [10, 9, 14],
"direct": [80, 72, 91]
},
"request_success": true,
"success": true
}
sources-list
Pro - CreatorAvailable in the Creator tier
Requires Burst Pro. See Referral source analysis.
Returns visitor counts grouped by source category and source name for the selected period. Powers the sources list on the Sources tab.
Extra parameters: date_start and date_end define the window. filters accepts the standard filter object.
Response — data is an indexed array of row objects:
| Field | Type | Description |
|---|---|---|
category | string | Source category: search, social, referral, aiReferral, paid, email or direct |
source | string | Source name (referrer host or campaign name) |
visitors | int | Unique visitor count for the category/source pair |
Show code
{
"data": [
{ "category": "search", "source": "google.com", "visitors": 312 },
{ "category": "social", "source": "facebook.com", "visitors": 98 },
{ "category": "direct", "source": "Direct / unknown", "visitors": 240 }
],
"request_success": true,
"success": true
}
datatable
Tabular data is returned by the granular data/datatable/{id} and data/ecommerce/datatable/{id} routes. The {id} segment selects the datatable; metrics, group_by and filters then refine the rows.
Common parameters:
| Parameter | Notes |
|---|---|
metrics | Array of metric column names. Values are intersected with the datatable's allow-list; unknown metrics are dropped. Omit metrics entirely to return every metric in the allow-list |
group_by | Field to group rows by (e.g. page_url, referrer, device) |
filters | Standard filter object; all filter keys from the filter keys section apply |
id | Datatable identifier when calling through the AJAX fallback. Ignored when the {id} path segment is used |
is_ecommerce | Set internally when the data/ecommerce/datatable/{id} route is used. Pass true when calling the ecommerce datatables via the AJAX fallback |
The burst_datatable_pre_data filter runs before the default SQL query and can short-circuit the result set. Providers that return an array from this filter fully replace the rows that Burst would have calculated from the statistics table, which is how the subscription_products, dummy_data, outgoing-links, reading-engagement, search-terms, search_console, not-found-pages and forms datatables are served. The assembled { columns, data, metrics } response then passes through the burst_datatable_response filter, which lets providers add extra top-level keys (for example, the scraping_progress value on outgoing-links).
Response:
| Field | Type | Description |
|---|---|---|
columns | array | Column definitions (see below) |
data | array | Row objects, keyed by metric/column name |
metrics | array | Resolved list of metric names included in the response after allow-list filtering |
Each column object:
| Field | Type | Description |
|---|---|---|
name | string | Display label |
id | string | Column key used in row objects |
sortable | bool | Whether the column can be sorted client-side |
right | bool | Whether to right-align the column |
Show code
{
"data": {
"columns": [
{ "name": "Page", "id": "page_url", "sortable": true, "right": false },
{ "name": "Pageviews", "id": "pageviews", "sortable": true, "right": true },
{ "name": "Visitors", "id": "visitors", "sortable": true, "right": true }
],
"data": [
{ "page_url": "/blog/", "pageviews": 124, "visitors": 98 },
{ "page_url": "/shop/", "pageviews": 87, "visitors": 72 }
],
"metrics": ["pageviews", "visitors"]
},
"request_success": true,
"success": true
}
Granular datatable endpoints
Each granular endpoint maps to a single datatable and enforces a per-datatable metric allow-list and capability requirement. Metrics not listed for the requested datatable are silently dropped before the SQL is built, so attempting to request an unrelated metric never leaks data from another datatable. A caller who lacks the datatable's required capability receives HTTP 403 with a message of Access denied..
Free-tier datatable IDs (registered by core):
| ID | Route | Description | Required capability |
|---|---|---|---|
statistics_pages | data/datatable/statistics_pages | Top pages and posts with visitor/session metrics | view_burst_statistics |
statistics_parameters | data/datatable/statistics_parameters | URL parameter breakdown | view_burst_statistics |
statistics_referrers | data/datatable/statistics_referrers | Referrer breakdown | view_burst_statistics |
sources_countries | data/datatable/sources_countries | Country-level location breakdown | view_burst_statistics |
reading-engagement | data/datatable/reading-engagement | Average time on page per page (reading engagement) | view_burst_statistics |
search-terms | data/datatable/search-terms | On-site search terms with volume and result counts | view_burst_statistics |
not-found-pages | data/datatable/not-found-pages | Page URLs that returned a 404, with hit counts | view_burst_statistics |
search_console | data/datatable/search_console | Google Search Console search queries with clicks, impressions, CTR and position | view_burst_statistics |
outgoing-links | data/datatable/outgoing-links | Outgoing external link clicks (requires external link tracking) | view_burst_statistics |
dummy_data | data/datatable/dummy_data | Randomised preview rows used for demo/screenshot UIs (see dummy_data below) | view_burst_statistics |
Pro datatable IDs (registered when Burst Pro is active):
| ID | Route | Description | Required tier | Required capability |
|---|---|---|---|---|
sources_referrers | data/datatable/sources_referrers | Detailed referrer breakdown for the Sources tab | Pro | view_burst_statistics |
sources_campaigns | data/datatable/sources_campaigns | UTM campaign breakdown | Pro | view_burst_statistics |
forms | data/datatable/forms | Per-form submission metrics and conversion rates | Pro | view_burst_statistics |
sales_products | data/ecommerce/datatable/sales_products | Per-product sales metrics | Business | view_sales_burst_statistics |
subscription_products | data/ecommerce/datatable/subscription_products | Per-product subscription metrics | Business | view_sales_burst_statistics |
Burst Pro extends the free sources_countries datatable with region/city detail and ecommerce metrics — see sources_countries below.
Unknown IDs respond with HTTP 404 and a message of Unknown datatable endpoint..
statistics_pages
Allowed metrics: page_url, pageviews, visitors, sessions, bounce_rate, avg_time_on_page, entrances, exit_rate, conversions, conversion_rate, sales, revenue, sales_conversion_rate, page_value.
Show code
curl -u "wp_user:xxxx xxxx xxxx xxxx xxxx xxxx" \
--get "https://example.com/wp-json/burst/v1/data/datatable/statistics_pages" \
--data-urlencode "date_start=2026-04-01" \
--data-urlencode "date_end=2026-04-15" \
--data-urlencode "metrics[]=pageviews" \
--data-urlencode "metrics[]=visitors" \
--data-urlencode "metrics[]=bounce_rate"
statistics_parameters
Allowed metrics: parameter, parameters, visitors, sessions, bounce_rate, avg_time_on_page, conversions, sales, revenue, page_value.
statistics_referrers
Allowed metrics: referrer, source_category, visitors, sessions, bounce_rate, conversions, sales, revenue, page_value.
sources_countries
Returns a country-level location breakdown. Country tracking is available in the free plugin, so this datatable resolves with country metrics without Pro.
Allowed metrics (free): country_code, visitors, bounce_rate.
Pro - CreatorAvailable in the Creator tier
Burst Pro adds region/city detail and ecommerce metrics on top of the free country breakdown. See Geographic insights.
Allowed metrics with Burst Pro: country_code, state, city, continent, visitors, sessions, bounce_rate, conversions, sales, revenue, sales_conversion_rate, avg_order_value.
Show code
curl -u "wp_user:xxxx xxxx xxxx xxxx xxxx xxxx" \
--get "https://example.com/wp-json/burst/v1/data/datatable/sources_countries" \
--data-urlencode "date_start=2026-04-01" \
--data-urlencode "date_end=2026-04-15" \
--data-urlencode "metrics[]=country_code" \
--data-urlencode "metrics[]=visitors"
reading-engagement
Returns the average time on page per page URL, sourced through burst_datatable_pre_data. This is the datatable-shaped equivalent of the reading_engagement type.
Allowed metrics: page_url, avg_time_on_page.
Extra parameters: least_engagement (bool) — when true, rows are ordered ascending so the least-engaged pages are returned first.
Show code
curl -u "wp_user:xxxx xxxx xxxx xxxx xxxx xxxx" \
--get "https://example.com/wp-json/burst/v1/data/datatable/reading-engagement" \
--data-urlencode "date_start=2026-04-01" \
--data-urlencode "date_end=2026-04-15"
search-terms
Returns the top on-site search terms with their occurrence volume and largest result count, sourced through burst_datatable_pre_data. This is the datatable-shaped equivalent of the search_terms type.
Allowed metrics: term, volume, results.
Show code
curl -u "wp_user:xxxx xxxx xxxx xxxx xxxx xxxx" \
--get "https://example.com/wp-json/burst/v1/data/datatable/search-terms" \
--data-urlencode "date_start=2026-04-01" \
--data-urlencode "date_end=2026-04-15"
not-found-pages
Returns the page URLs that returned a 404 within the period, with a hit count per URL, sourced through burst_datatable_pre_data. This is the datatable-shaped equivalent of the not_found_pages type and maps to the engagement tab. Rows are ordered by hit count descending. 404 hits are excluded from every other datatable, so this endpoint is the way to surface them.
Allowed metrics: page_url, hits.
Show code
curl -u "wp_user:xxxx xxxx xxxx xxxx xxxx xxxx" \
--get "https://example.com/wp-json/burst/v1/data/datatable/not-found-pages" \
--data-urlencode "date_start=2026-04-01" \
--data-urlencode "date_end=2026-04-15"
Show code
{
"data": {
"columns": [
{ "name": "Page", "id": "page_url", "sortable": true, "right": false },
{ "name": "Hits", "id": "hits", "sortable": true, "right": true }
],
"data": [
{ "page_url": "/old-landing-page/", "hits": 87 },
{ "page_url": "/blog/removed-post/", "hits": 24 }
],
"metrics": ["page_url", "hits"]
},
"request_success": true,
"success": true
}
search_console
Returns the top Google Search Console search queries for the selected period, aggregated across days from the locally stored burst_search_terms table. Rows are served through burst_datatable_pre_data, so the Search Console API is never called on dashboard load — Burst syncs the data on an hourly cron and the dashboard only reads the stored rows.
Connect Google Search Console under Settings → Integrations and enable the feature before this datatable returns rows. Until a property matching the site is resolved, the endpoint returns an empty data array. Clicks and impressions are summed across the range, click_through_rate is recomputed from the summed totals as a percentage (0–100) and position is the impression-weighted average.
Allowed metrics: query, clicks, impressions, click_through_rate, position.
Extra parameters: date_start and date_end define the window. When omitted, the endpoint defaults to the most recent 28 days of available data.
Show code
curl -u "wp_user:xxxx xxxx xxxx xxxx xxxx xxxx" \
--get "https://example.com/wp-json/burst/v1/data/datatable/search_console" \
--data-urlencode "date_start=2026-04-01" \
--data-urlencode "date_end=2026-04-15"
Show code
{
"data": {
"columns": [
{ "name": "Query", "id": "query", "sortable": true, "right": false },
{ "name": "Clicks", "id": "clicks", "sortable": true, "right": true },
{ "name": "Impressions", "id": "impressions", "sortable": true, "right": true },
{ "name": "CTR", "id": "click_through_rate", "sortable": true, "right": true },
{ "name": "Position", "id": "position", "sortable": true, "right": true }
],
"data": [
{ "query": "burst statistics", "clicks": 142, "impressions": 3200, "click_through_rate": 4.44, "position": 3.1 },
{ "query": "wordpress analytics", "clicks": 88, "impressions": 5400, "click_through_rate": 1.63, "position": 8.7 }
],
"metrics": ["query", "clicks", "impressions", "click_through_rate", "position"]
},
"request_success": true,
"success": true
}
outgoing-links
Pro - CreatorAvailable in the Creator tier
Requires Burst Pro with external link tracking enabled under Settings → General. See Burst pricing.
Returns click counts for every tracked outgoing external link across three time windows: the current period, the previous period of equal length and the same window one year earlier. Rows are sourced through burst_datatable_pre_data; when external link tracking is disabled the endpoint returns an empty row set.
Allowed metrics: url, clicks, previous_clicks, previous_clicks_yoy.
The assembled response also carries a top-level scraping_progress integer (0–100) describing how far the first external-link scraping cycle has progressed. A value of 100 indicates the first cycle has completed.
Show code
{
"data": {
"columns": [
{ "name": "URL", "id": "url", "sortable": true, "right": false },
{ "name": "Clicks", "id": "clicks", "sortable": true, "right": true }
],
"data": [
{ "url": "https://example.org/", "clicks": 42, "previous_clicks": 30, "previous_clicks_yoy": 18 }
],
"metrics": ["url", "clicks", "previous_clicks", "previous_clicks_yoy"],
"scraping_progress": 100
},
"request_success": true,
"success": true
}
sources_referrers
Pro - CreatorAvailable in the Creator tier
Requires Burst Pro. See Referral source analysis.
Mirrors statistics_referrers but is the route the Sources tab calls into. Same allowed metrics as statistics_referrers.
sources_campaigns
Pro - CreatorAvailable in the Creator tier
Requires Burst Pro for UTM tracking. See UTM campaign tracking.
Allowed metrics: campaign, source, medium, term, content, visitors, bounce_rate, conversions, conversion_rate, sales, revenue, sales_conversion_rate, page_value.
forms
Pro - CreatorAvailable in the Creator tier
Requires Burst Pro with a supported form plugin (Contact Form 7, WPForms, Fluent Forms, HappyForms, WS Form, Gravity Forms, Ninja Forms or Elementor Forms). See Burst pricing.
Returns submission metrics per tracked form, comparing the current period against the previous period of equal length. Rows are sourced through burst_datatable_pre_data; when no form table exists the endpoint returns an empty row set.
Allowed metrics: form_id, form_title, form_provider, form_provider_label, submissions, pageviews, conversion_rate, previous_submissions, previous_pageviews, previous_conversion_rate.
The pageviews and previous_pageviews columns carry the site-wide unique visitor count used as the conversion-rate denominator, and conversion_rate is the submissions-per-visitor percentage.
Show code
curl -u "wp_user:xxxx xxxx xxxx xxxx xxxx xxxx" \
--get "https://example.com/wp-json/burst/v1/data/datatable/forms" \
--data-urlencode "date_start=2026-04-01" \
--data-urlencode "date_end=2026-04-15"
sales_products
Pro - BusinessAvailable in the Business tier
Requires the Business tier with an active WooCommerce or EDD integration. See Revenue and sales tracking.
Allowed metrics: product, adds_to_cart, sales, revenue.
Show code
curl -u "wp_user:xxxx xxxx xxxx xxxx xxxx xxxx" \
--get "https://example.com/wp-json/burst/v1/data/ecommerce/datatable/sales_products" \
--data-urlencode "date_start=2026-04-01" \
--data-urlencode "date_end=2026-04-15" \
--data-urlencode "metrics[]=product" \
--data-urlencode "metrics[]=sales" \
--data-urlencode "metrics[]=revenue"
subscription_products
Pro - BusinessAvailable in the Business tier
Subscription datatables and metrics require the Business tier with an active subscriptions integration. See Revenue and sales tracking.
Allowed metrics: plan, active_subscribers, canceled_subscribers, trialling_subscribers, monthly_recurring_revenue, product_churn_value.
Rows are keyed by a product identifier and expose subscription-specific metrics rather than pageview metrics.
Show code
{
"data": {
"columns": [
{ "name": "Plan", "id": "plan", "sortable": true, "right": false },
{ "name": "Active subs", "id": "active_subscribers", "sortable": true, "right": true },
{ "name": "MRR", "id": "monthly_recurring_revenue", "sortable": true, "right": true }
],
"data": [
{
"product_id": 42,
"plan": "Pro monthly",
"active_subscribers": 128,
"monthly_recurring_revenue": { "currency": "USD", "value": 2560.00 }
}
],
"metrics": ["plan", "active_subscribers", "monthly_recurring_revenue"]
},
"request_success": true,
"success": true
}
dummy_data
Returns a fixed-size set of randomised rows that match the statistics_pages schema. Use this in demo screens, onboarding flows or screenshots where production data is not available. Rows are generated in PHP and never touch the statistics table.
Allowed metrics: identical to statistics_pages.
Show code
curl -u "wp_user:xxxx xxxx xxxx xxxx xxxx xxxx" \
--get "https://example.com/wp-json/burst/v1/data/datatable/dummy_data" \
--data-urlencode "metrics[]=page_url" \
--data-urlencode "metrics[]=pageviews" \
--data-urlencode "metrics[]=visitors"
Extending the allow-list
The per-datatable allow-list and capability requirement are exposed through the burst_datatable_config filter. Each entry maps a datatable ID to a metrics array and a capability string. Use it to register a custom datatable or to expose an additional metric for an existing one.
Show code
add_filter(
'burst_datatable_config',
static function ( array $config ): array {
$config['statistics_pages']['metrics'][] = 'my_custom_metric';
$config['team_dashboard'] = [
'metrics' => [
'page_url',
'pageviews',
'visitors',
'my_custom_metric',
],
'capability' => 'view_burst_statistics',
];
return $config;
}
);
A new datatable ID also needs a row provider — register one via burst_datatable_pre_data to short-circuit the default SQL query and return rows directly.
@deprecated The burst_datatable_metric_allow_list filter is replaced by burst_datatable_config. Migrate any callbacks to the new filter, which also carries the per-datatable capability requirement.
subscriptions
Pro - BusinessAvailable in the Business tier
Requires the Business tier with an active subscriptions integration (WooCommerce Subscriptions, EDD Recurring or Subscriben). See the Business plan.
Returns the subscription summary cards (MRR, active/canceled subscriptions, revenue churn, average lifetime value) with current/previous period values and rate-of-change.
Response — data fields:
| Field | Type | Description |
|---|---|---|
monthly_recurring_revenue | { label, currency, current, previous, rate_change } | Current and previous MRR plus active subscription counts |
active_subscriptions | { label, current, previous, rate_change } | Active subscription totals |
canceled_subscriptions | { label, current, previous, rate_change } | Canceled subscription totals |
revenue_churn | { label, current, previous, rate_change } | Churn percentage, churned MRR and counts |
average_lifetime_value | { label, currency, current, previous, rate_change } | Average lifetime value with lifetime revenue totals |
Show code
{
"data": {
"monthly_recurring_revenue": {
"label": "Monthly Recurring Revenue",
"currency": "USD",
"current": { "mrr": 2560.00, "count": 128 },
"previous": { "mrr": 2310.00, "count": 118 },
"rate_change": 10.82
},
"active_subscriptions": {
"label": "Active Subscriptions",
"current": 128,
"previous": 118,
"rate_change": 8.47
},
"revenue_churn": {
"label": "Revenue Churn",
"current": {
"churned_percentage": 2.15,
"churned_mrr": 49.99,
"count": 3,
"previously_active_count": 118
},
"previous": {
"churned_percentage": 1.84,
"churned_mrr": 42.50,
"count": 2
},
"rate_change": 16.85
}
},
"request_success": true,
"success": true
}
subscriptions-revenue-chart
Pro - BusinessAvailable in the Business tier
Requires the Business tier with an active subscriptions integration. See the Business plan.
Returns bucketed data for the new vs renewal subscriptions chart.
Extra parameters:
| Parameter | Notes |
|---|---|
group_by | Bucket size. Accepts day, week, month or auto |
chart_mode | revenue (default) or sales to switch between revenue amounts and subscription counts |
Response — data fields:
| Field | Type | Description |
|---|---|---|
interval | string | Resolved bucket interval (day, week or month) |
spans_multiple_years | bool | Whether the range crosses a year boundary |
mode | string | revenue or sales, matching the request |
currency | string | Base store currency (only meaningful when mode is revenue) |
rows | array | Bucketed rows with timestamp, label, newValue and renewalValue |
Show code
{
"data": {
"interval": "day",
"spans_multiple_years": false,
"mode": "revenue",
"currency": "USD",
"rows": [
{ "timestamp": 1714521600, "label": "Apr 1", "newValue": 199.00, "renewalValue": 399.00 },
{ "timestamp": 1714608000, "label": "Apr 2", "newValue": 0.00, "renewalValue": 99.00 }
]
},
"request_success": true,
"success": true
}
subscriptions-distribution
Pro - BusinessAvailable in the Business tier
Requires the Business tier with an active subscriptions integration. See the Business plan.
Returns a distribution breakdown of subscription signups and renewals in the selected period.
Extra parameters:
| Parameter | Notes |
|---|---|
distribution_view | One of gateways (default), currencies or countries |
Response — data is an indexed array of row objects:
| Field | Type | Description |
|---|---|---|
id | string | Sanitized row identifier |
label | string | Human-readable label |
count | int | Number of events (signups + renewals) attributed to this row |
value | float | Share of the total, expressed as a percentage |
Show code
{
"data": [
{ "id": "stripe", "label": "Stripe", "count": 140, "value": 68.29 },
{ "id": "paypal", "label": "PayPal", "count": 48, "value": 23.41 },
{ "id": "manual", "label": "Manual", "count": 17, "value": 8.30 }
],
"request_success": true,
"success": true
}
subscriptions-retention
Pro - BusinessAvailable in the Business tier
Requires the Business tier with an active subscriptions integration. See the Business plan.
Returns cohort retention data for subscription signups in the selected period.
Extra parameters:
| Parameter | Notes |
|---|---|
product_id | Optional product filter. Use 0 for all products |
Response — data fields:
| Field | Type | Description |
|---|---|---|
rows | array | One row per cohort with id, signup_count and a data array of retention points |
products | array | Available product filter options (id, label, is_yearly) |
interval | string | Cohort bucket unit (month, quarter or year) |
max_offset | int | Maximum offset index used across the cohorts |
Show code
{
"data": {
"rows": [
{
"id": "Mar 2026 (42)",
"signup_count": 42,
"data": [
{ "x": "M+0", "y": 100, "count": 42 },
{ "x": "M+1", "y": 83.33, "count": 35 },
{ "x": "M+2", "y": 71.43, "count": 30 }
]
}
],
"products": [
{ "id": 42, "label": "Pro monthly", "is_yearly": false }
],
"interval": "month",
"max_offset": 2
},
"request_success": true,
"success": true
}
Abilities API
The Abilities API exposes the most common read paths as WordPress abilities under the burst-statistics category. Use it from AI agents, automation tools or any client that consumes the WordPress abilities registry instead of calling REST routes directly. Abilities are read-only, rate-limited and resolve to the same data the REST endpoints return.
Prerequisites
- WordPress build that ships the Abilities API (the
wp_register_abilityfunction must exist) enable_abilities_apioption turned on under Settings → Advanced (off by default)- Authenticated user with the
manage_burst_statisticscapability
When the Abilities API is unavailable or the option is off, no abilities are registered and existing REST endpoints are unaffected.
Rate limits
Each ability enforces a per-user rate limit of 30 calls per 60-second window. Adjust both via filters:
| Filter | Default | Description |
|---|---|---|
burst_abilities_rate_limit_window | 60 | Window length in seconds |
burst_abilities_rate_limit_max | 30 | Maximum calls allowed per window |
Show code
add_filter(
'burst_abilities_rate_limit_max',
static function ( int $max, string $ability ): int {
return $ability === 'data' ? 60 : $max;
},
10,
2
);
Exceeding the limit returns burst_abilities_rate_limited with HTTP 429.
Available abilities
| Ability | Description |
|---|---|
burst/live-visitors | Current live visitor count |
burst/live-traffic | Recent live traffic rows |
burst/today-summary | Summary metrics for a date range |
burst/data | Insights time-series or datatable rows |
burst/sales-data | Ecommerce sales metrics (Burst Pro only) |
burst/subscriptions-data | Subscription metrics (Burst Pro only) |
burst/tasks | Current Burst task list |
burst/tracking-status | Tracking transport status and last test time |
burst/license-notices | License state and notices |
All abilities are registered with show_in_rest = true and the read-only / non-destructive / idempotent annotations.
burst/live-visitors
Input: none
Output:
| Field | Type | Description |
|---|---|---|
visitors | int | Current live visitor count (clamped to 0 minimum) |
burst/live-traffic
Input:
| Field | Type | Default | Description |
|---|---|---|---|
limit | int | 100 | Number of rows to return, clamped to the range 1–100 |
Output:
| Field | Type | Description |
|---|---|---|
items | array | Rows from the live traffic feed |
total | int | Total number of rows available before the limit is applied |
Each row in items:
| Field | Type | Description |
|---|---|---|
uid | string | Anonymous visitor identifier |
page_url | string | URL of the page visited |
time | int | Unix timestamp of the hit |
time_on_page | int | Seconds spent on the page |
active_time | float | Active (non-idle) seconds |
entry | bool | Whether this is the session's entry page |
checkout | bool | Whether a checkout event was recorded |
exit | bool | Whether this is the session's exit page |
burst/today-summary
Input:
| Field | Type | Default | Description |
|---|---|---|---|
date_start | int | — | Unix timestamp marking the start of the period |
date_end | int | — | Unix timestamp marking the end of the period |
Output:
| Field | Type | Description |
|---|---|---|
live | int | Current live visitors |
today | int | Unique visitors for the period |
most_viewed | { title, value } | Top page title and view count |
top_referrer | { title, value } | Top referrer hostname and session count |
pageviews | int | Total pageviews |
avg_time_on_page | int | Average seconds on page |
This is the agent-shaped equivalent of the REST today type. Field names use snake_case and numeric values are returned as integers, not formatted strings.
burst/data
Returns either an insights time-series or a datatable, depending on the type input.
Input:
| Field | Type | Default | Description |
|---|---|---|---|
type | string | — | Required. Either insights or datatable |
datatable_id | string | — | Required when type is datatable. One of statistics_pages, statistics_parameters, statistics_referrers, sources_countries, sources_campaigns, sales_products, subscription_products, sources_referrers, outgoing-links, search-terms, search_console or forms |
date_start | int | 0 | Unix timestamp for the start of the period |
date_end | int | 0 | Unix timestamp for the end of the period |
interval | string | auto | Insights-only bucket override. One of auto, hour, day, week or month |
metrics | string[] | ["pageviews"] | Metrics to retrieve. For datatable requests, values are intersected with the allow-list for datatable_id |
filters | object[] | [] | Filter objects (only honoured for datatable) |
group_by | string[] | ["page_url"] | Grouping columns (only honoured for datatable) |
limit | int | 0 (no limit) | Maximum number of rows returned |
datatable_id is now required for type=datatable and is validated against the registered datatable allow-list. Unknown values respond with burst_abilities_unknown_datatable (HTTP 404). The new interval field replaces group_by for insights — if interval is omitted, the first value of group_by is read as a backward-compatible interval hint. If no requested metric is valid for the chosen datatable, the ability falls back to the datatable's default metrics; if none of those resolve either, it responds with burst_abilities_invalid_metrics (HTTP 400).
utm_source is normalized to source in group_by.
Output — type=insights:
| Field | Type | Description |
|---|---|---|
type | string | Always "insights" |
interval | string | Resolved bucket interval (hour, day, week, month or auto) |
spans_multiple_years | bool | Whether the range crosses a year boundary |
series | array | One entry per requested metric with id, label and points |
point_count | int | Number of points per series |
Each points entry has timestamp (int) and value (float).
Output — type=datatable:
| Field | Type | Description |
|---|---|---|
type | string | Always "datatable" |
dimensions | array | One entry per group_by column with id and label |
metrics | array | One entry per metric column with id and label |
rows | array | Row objects keyed by metric/dimension name |
row_count | int | Number of rows in rows |
burst/sales-data and burst/subscriptions-data
Pro - BusinessAvailable in the Business tier
Both abilities require Burst Pro with an active ecommerce or subscriptions integration. They return burst_abilities_pro_required with HTTP 503 on Free installs. See Revenue and sales tracking.
Input:
| Field | Type | Default | Description |
|---|---|---|---|
date_start | int | 0 | Unix timestamp for the start of the period |
date_end | int | 0 | Unix timestamp for the end of the period |
metrics | string[] | varies | Metrics to retrieve. For burst/sales-data the default is ["product", "sales", "revenue"]; for burst/subscriptions-data it is ["plan", "active_subscribers", "canceled_subscribers", "trialling_subscribers", "monthly_recurring_revenue", "product_churn_value"] |
filters | object[] | [] | Additional filter objects appended to the implicit purchase/subscription filter |
group_by | string[] | varies | Grouping columns. Default for burst/sales-data is ["product"]; for burst/subscriptions-data it is ["plan"] |
limit | int | 100 | Maximum number of rows returned, clamped to the range 1–500 |
Both abilities now accept filters and limit, target the sales_products and subscription_products granular datatables and enforce their metric allow-lists. Metrics outside the allow-list fall back to the defaults above.
Output: identical shape to burst/data with type=datatable.
burst/sales-data filters the result set to purchase events; burst/subscriptions-data filters to subscription events.
Error responses
Abilities return WP_Error objects which the WordPress REST layer translates to JSON with the matching HTTP status:
| Code | HTTP | When |
|---|---|---|
burst_abilities_forbidden | 403 | User is not logged in or lacks manage_burst_statistics |
burst_abilities_invalid_input | 400 | Required input is missing or has the wrong type |
burst_abilities_invalid_metrics | 400 | No requested metric is valid for the chosen datatable, and no default metric resolves either |
burst_abilities_unknown_datatable | 404 | datatable_id is not registered in the allow-list |
burst_abilities_rate_limited | 429 | Per-user rate limit exceeded |
burst_abilities_pro_required | 503 | Pro-only ability called on a Free install |
burst_abilities_unavailable | 503 | Burst admin services failed to bootstrap |
burst_abilities_execution_failed | 500 | Underlying data fetch threw an exception |
Calling an ability
Show code
if ( ! function_exists( 'wp_get_ability' ) ) {
return;
}
$ability = wp_get_ability( 'burst/data' );
if ( ! $ability ) {
return;
}
$result = $ability->execute(
[
'type' => 'datatable',
'datatable_id' => 'statistics_pages',
'date_start' => strtotime( '2026-04-01 00:00:00' ),
'date_end' => strtotime( '2026-04-15 23:59:59' ),
'metrics' => [ 'pageviews', 'visitors' ],
'group_by' => [ 'page_url' ],
'limit' => 25,
]
);
if ( is_wp_error( $result ) ) {
// Inspect $result->get_error_code() / get_error_message().
return;
}
$rows = $result['rows'];
Code examples
Basic request with a date range
curl -u "wp_user:xxxx xxxx xxxx xxxx xxxx xxxx" \
"https://example.com/wp-json/burst/v1/data/today?date_start=2026-04-01&date_end=2026-04-15"
Granular datatable with filters
Show code
curl -u "wp_user:xxxx xxxx xxxx xxxx xxxx xxxx" \
--get "https://example.com/wp-json/burst/v1/data/datatable/statistics_pages" \
--data-urlencode "date_start=2026-04-01" \
--data-urlencode "date_end=2026-04-15" \
--data-urlencode "group_by=page_url" \
--data-urlencode "metrics[]=pageviews" \
--data-urlencode "metrics[]=visitors" \
--data-urlencode 'filters={"device":["desktop","mobile"],"country_code":"US"}'
Subscription products datatable
Show code
curl -u "wp_user:xxxx xxxx xxxx xxxx xxxx xxxx" \
--get "https://example.com/wp-json/burst/v1/data/ecommerce/datatable/subscription_products" \
--data-urlencode "date_start=2026-04-01" \
--data-urlencode "date_end=2026-04-15" \
--data-urlencode "metrics[]=plan" \
--data-urlencode "metrics[]=active_subscribers" \
--data-urlencode "metrics[]=monthly_recurring_revenue"
PHP request via wp_remote_get
Show code
$response = wp_remote_get(
add_query_arg(
[
'date_start' => '2026-04-01',
'date_end' => '2026-04-15',
'group_by' => 'page_url',
'metrics' => [ 'pageviews', 'visitors' ],
],
rest_url( 'burst/v1/data/datatable/statistics_pages' )
),
[
'headers' => [
'Authorization' => 'Basic ' . base64_encode( 'wp_user:xxxx xxxx xxxx xxxx xxxx xxxx' ),
],
'timeout' => 15,
]
);
if ( is_wp_error( $response ) ) {
// Handle connection error.
return;
}
$body = json_decode( wp_remote_retrieve_body( $response ), true );
if ( empty( $body['success'] ) ) {
// Handle API-level error.
return;
}
$rows = $body['data']['data'];
Troubleshooting
HTTP 401 — missing authentication
Application Passwords require the WordPress REST API to be publicly accessible. If a security plugin blocks REST API access for unauthenticated users, allowlist the burst/v1 namespace or use nonce authentication from within WordPress.
HTTP 403 — Generic datatable endpoints are not allowed
The generic data/datatable and data/ecommerce/datatable endpoints are not callable. Use data/datatable/{id} or data/ecommerce/datatable/{id} and pass the specific datatable ID in the path.
HTTP 403 — Access denied
The requested datatable declares a capability your user does not have. The ecommerce datatables (sales_products, subscription_products) require view_sales_burst_statistics; the remaining datatables require view_burst_statistics. Authenticate as a user with the required capability.
Requested metric is missing from the response
Each granular datatable enforces an allow-list. Metrics that are not registered for the datatable are silently dropped before the SQL query runs. Inspect the metrics array returned in data.metrics to see which metrics were actually resolved, and use the burst_datatable_config filter to expose additional metrics.
404 pages are missing from the pages datatable
404 hits are stored with an internal page_type of 404 and are excluded from every standard data type and datatable. Use the not_found_pages type or the not-found-pages datatable to list them, or pass the status filter (404, 200 or all) on a data request to include or isolate them.
Empty data array despite a valid date range
Burst stores hits in a staging table and flushes them to the main statistics table on a cron schedule. Hits from the last few minutes may not yet appear. Live types (live-visitors, live-traffic) always reflect real-time data.
search_console returns an empty data array
The search_console datatable reads from the locally synced burst_search_terms table. Connect Google Search Console under Settings → Integrations, enable the feature and wait for a property matching the site to resolve. Search Console data lags roughly two days and the historical backfill runs in the background, so recent days or a freshly connected site may return no rows until the sync catches up.
Subscription types return empty data
Subscription endpoints require an active subscriptions integration and an up-to-date aggregation table. New installs backfill historical data in the background; until that completes, some periods may return zeroed counts. The insights response also changed shape in v3.4.0 — clients that still read labels should switch to timestamps + interval before upgrading.
Abilities API returns 404 or the abilities are not registered
The Abilities API only registers when wp_register_ability is available and the enable_abilities_api option is on. Check Settings → Advanced and confirm WordPress core (or the Abilities API plugin) provides the registry function. If the option is hidden in the UI, the running WordPress build does not yet ship the Abilities API.
Abilities API returns 403 for a viewer user
v3.4.2 raised the abilities permission requirement from view_burst_statistics to manage_burst_statistics. Use a user with the manage capability for ability calls, or fall back to the REST endpoints for read-only viewers.