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.
:::caution Breaking change
Changed in v3.4.2: 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.
:::
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 |
group_by | array / string | varies by type | Grouping fields. A single string value is normalized to a single-element array |
goal_id | int | 0 | Goal identifier. Required for goals and live-goals types |
isOnboarding | bool | false | Used by the live-visitors onboarding flow; has no effect on other types |
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 |
Changed in v3.4.0: 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.
Changed in v3.4.2: 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.
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 |
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) |
Burst Pro (additional keys, all roles):
| Key | Type | Description |
|---|---|---|
country_code | string / array | ISO 3166-1 alpha-2 country code |
city | string / array | City name |
state | string / array | State or province name |
continent | string / array | Continent name |
continent_code | string / array | Two-letter continent code |
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, tooltip } | Current live visitor count |
today | { value, tooltip } | Unique visitors for the period |
mostViewed | { title, value, tooltip } | Most viewed page title and view count |
referrer | { title, value, tooltip } | Top referrer hostname and session count |
pageviews | { title, value, tooltip } | Total pageview count |
timeOnPage | { title, value, tooltip } | Average time on page (formatted string) |
Show code
{
"data": {
"live": { "value": "12", "tooltip": "Live visitors" },
"today": { "value": "348", "tooltip": "Unique visitors" },
"mostViewed": { "title": "Most viewed", "value": "/blog/", "tooltip": "124 views" },
"referrer": { "title": "Top referrer", "value": "google.com", "tooltip": "87 sessions" },
"pageviews": { "title": "Pageviews", "value": "512", "tooltip": "" },
"timeOnPage": { "title": "Avg. time on page", "value": "1:24", "tooltip": "" }
},
"request_success": true,
"success": true
}
goals
Returns goal statistics for the selected period. Requires goal_id.
Extra parameters: goal_id (int, required)
Response — data fields:
| Field | Type | Description |
|---|---|---|
goalId | int | The requested goal ID |
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, tooltip } | Top converting page |
conversionMetric | { value, title, tooltip } | Primary conversion metric |
conversionPercentage | { value, title, tooltip } | Conversion rate for the period |
bestDevice | { value, title, tooltip, 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, required)
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 or auto. auto selects an interval based on the date range |
Changed in v3.4.0: 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 or month |
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 |
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
},
{
"label": "Visitors",
"data": [348, 312, 401],
"backgroundColor": "#FFF8DC",
"borderColor": "#FFDA4A",
"fill": 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 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
}
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 |
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 |
Changed in v3.4.0: 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 and dummy_data datatables are served.
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
Added in v3.4.2.
Each granular endpoint maps to a single datatable and enforces a per-datatable metric allow-list. 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.
Free-tier datatable IDs (registered by core):
| ID | Route | Description |
|---|---|---|
statistics_pages | data/datatable/statistics_pages | Top pages and posts with visitor/session metrics |
statistics_parameters | data/datatable/statistics_parameters | URL parameter breakdown |
statistics_referrers | data/datatable/statistics_referrers | Referrer breakdown |
dummy_data | data/datatable/dummy_data | Randomised preview rows used for demo/screenshot UIs (see dummy_data below) |
Pro datatable IDs (registered when Burst Pro is active):
| ID | Route | Description | Required tier |
|---|---|---|---|
sources_referrers | data/datatable/sources_referrers | Detailed referrer breakdown for the Sources tab | Pro |
sources_countries | data/datatable/sources_countries | Country / state / city breakdown | Pro |
sources_campaigns | data/datatable/sources_campaigns | UTM campaign breakdown | Pro |
sales_products | data/ecommerce/datatable/sales_products | Per-product sales metrics | Business |
subscription_products | data/ecommerce/datatable/subscription_products | Per-product subscription metrics | Business |
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, visitors, sessions, bounce_rate, conversions, sales, revenue, page_value.
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_countries
Pro - CreatorAvailable in the Creator tier
Requires Burst Pro for Geo-IP resolution. See Geographic insights.
Allowed metrics: country_code, state, city, continent, visitors, sessions, bounce_rate, conversions, sales, revenue, sales_conversion_rate, avg_order_value.
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.
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 is exposed through the burst_datatable_metric_allow_list filter. Use it to register a custom datatable or to expose an additional metric for an existing one.
Show code
add_filter(
'burst_datatable_metric_allow_list',
static function ( array $allow_list ): array {
$allow_list['statistics_pages'][] = 'my_custom_metric';
$allow_list['team_dashboard'] = [
'page_url',
'pageviews',
'visitors',
'my_custom_metric',
];
return $allow_list;
}
);
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.
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
Added in v3.4.1.
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 or sources_referrers |
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 |
Changed in v3.4.2: 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 |
Changed in v3.4.2: 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 were removed in v3.4.2. Switch to data/datatable/{id} or data/ecommerce/datatable/{id} and pass the specific datatable ID in the path.
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_metric_allow_list filter to expose additional metrics.
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.
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.