Skip to main content

Ecommerce endpoints

Pro - BusinessAvailable in the Business tier

These endpoints are only available in Burst Pro. Learn more about WooCommerce funnel analytics.

The ecommerce namespace exposes revenue, sales and subscription data collected by Burst Pro's ecommerce tracking module. It mirrors the structure of burst/v1/data/{type} but requires the sales-specific capability and scopes all queries to ecommerce events.

Three route families are available:

  • GET burst/v1/data/ecommerce/{type} — period-scoped ecommerce data (sales, top performers, quick wins, funnel, subscriptions, retention, distribution).
  • GET burst/v1/data/ecommerce/datatable/{id} — per-product datatables (sales_products, subscription_products).
  • GET burst/v1/get_action/ecommerce/{action} — stateful ecommerce actions such as backfill progress lookups.

In addition, ecommerce data is exposed via the WordPress Abilities API when enabled. See Abilities API below.

Prerequisites

  • Burst Pro with ecommerce tracking enabled
  • WordPress user with view_sales_burst_statistics capability
  • See Authentication for setup

:::caution Breaking change Changed in v3.3.0: the permission_callback for these endpoints was updated from user_can_view() to user_can_view_sales(). Any user with only the view_burst_statistics capability will now receive HTTP 403. The view_sales_burst_statistics capability must be granted separately.

For share link viewers, access additionally requires sales in the token's shared_tabs list. :::

Route

GET /wp-json/burst/v1/data/ecommerce/{type}
GET /wp-json/burst/v1/data/ecommerce/datatable/{id}
GET /wp-json/burst/v1/get_action/ecommerce/{action}

Permission: view_sales_burst_statistics

The {type}, {id} and {action} path segments accept characters matching [a-z_-]+.

Added in v3.4.0: the get_action/ecommerce/{action} route and the REST API optimizer now also loads the ecommerce module for any burst/v1/get_action/ecommerce URI, so stateful ecommerce actions are available over a clean, minimal REST stack.

Added in v3.4.2: the data/ecommerce/datatable/{id} route exposes per-product datatables behind a path segment so each datatable can carry its own metric allow-list. Incoming metrics are intersected with the allow-list for the requested {id}; unknown metrics are silently dropped, and unknown datatable IDs return HTTP 404 with code burst_abilities_unknown_datatable.

Request parameters

The ecommerce data endpoint accepts the same parameters as burst/v1/data/{type}:

ParameterTypeDefaultDescription
date_startstring (YYYY-MM-DD)Start of the requested period, normalized to 00:00:00 in the WordPress timezone
date_endstring (YYYY-MM-DD)End of the requested period, normalized to 23:59:59 in the WordPress timezone
filtersarray / JSON string[]Filter payload. Accepts arrays, JSON objects or comma-separated strings
metricsarray / stringvaries by typeMetric names to include
group_byarray / stringvaries by typeGrouping fields

Date clamping: when date_start is earlier than the date ecommerce tracking was activated, Burst automatically advances date_start to the activation date. This prevents misleading zero-padded data for periods before tracking existed.

Changed in v3.4.0: the date-clamping logic no longer applies to subscription-related types (subscriptions, subscriptions-revenue-chart, subscriptions-distribution, subscriptions-retention) or the subscription_products datatable. Subscription data predates ecommerce activation and is scoped separately to the earliest subscription date reported by the active integration.

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 is returned with an appropriate HTTP status code.

Types

sales

Returns top-level ecommerce KPIs for the selected period alongside the equivalent previous period values.

Response — data fields:

FieldTypeDescription
conversion-rateobjectVisitor-to-order conversion rate
abandonment-rateobjectCart abandonment rate
average-orderobjectAverage order value
revenueobjectTotal revenue

Each field contains label, current and previous blocks. The inner structure varies by metric:

conversion-ratecurrent and previous:

FieldTypeDescription
visitorsintTotal unique visitors
total_convertedintVisitors who completed an order
conversion_ratefloatPercentage of visitors who converted

abandonment-ratecurrent and previous:

FieldTypeDescription
total_cartsintSessions where a product was added to cart
total_convertedintSessions that resulted in an order
total_abandonedintSessions that added to cart but did not convert
abandoned_ratefloatAbandonment percentage

average-order and revenuecurrent and previous:

FieldTypeDescription
total_ordersintNumber of completed orders
total_revenuefloatSum of order revenue
average_order_valuefloatAverage revenue per order
currencystringISO 4217 currency code (e.g. USD)
Show code
{
"data": {
"conversion-rate": {
"label": "Conversion rate",
"current": { "visitors": 1200, "total_converted": 48, "conversion_rate": 4.0 },
"previous": { "visitors": 1100, "total_converted": 38, "conversion_rate": 3.45 }
},
"abandonment-rate": {
"label": "Abandonment rate",
"current": { "total_carts": 200, "total_converted": 48, "total_abandoned": 152, "abandoned_rate": 76.0 },
"previous": { "total_carts": 180, "total_converted": 38, "total_abandoned": 142, "abandoned_rate": 78.9 }
},
"average-order": {
"label": "Average order value",
"current": { "total_orders": 48, "total_revenue": 2880.00, "average_order_value": 60.00, "currency": "USD" },
"previous": { "total_orders": 38, "total_revenue": 2090.00, "average_order_value": 55.00, "currency": "USD" }
},
"revenue": {
"label": "Revenue",
"current": { "total_orders": 48, "total_revenue": 2880.00, "average_order_value": 60.00, "currency": "USD" },
"previous": { "total_orders": 38, "total_revenue": 2090.00, "average_order_value": 55.00, "currency": "USD" }
}
},
"request_success": true,
"success": true
}

top-performers

Returns the top-performing product, campaign, country and device for the selected period, each compared against the previous period.

Response — data fields:

FieldTypeDescription
top-productobjectBest-performing product by revenue
top-campaignobjectBest-performing UTM campaign by revenue
top-countryobjectCountry generating the most revenue
top-deviceobjectDevice category generating the most revenue

Each field contains label, current, previous and revenue_change (percentage change, nullable).

top-productcurrent and previous:

FieldTypeDescription
product_namestringWooCommerce product name
product_idintWooCommerce product ID
total_quantity_soldintUnits sold in the period
total_revenuefloatRevenue generated
currencystringISO 4217 currency code

top-campaigncurrent and previous:

FieldTypeDescription
campaign_idintInternal campaign ID
campaign_namestringUTM campaign value
total_revenuefloatRevenue attributed to the campaign
currencystringISO 4217 currency code

top-countrycurrent and previous:

FieldTypeDescription
country_codestringISO 3166-1 alpha-2 country code
total_revenuefloatRevenue from this country
currencystringISO 4217 currency code

top-devicecurrent and previous:

FieldTypeDescription
device_namestringDevice category name
total_revenuefloatRevenue from this device category
currencystringISO 4217 currency code
Show code
{
"data": {
"top-product": {
"label": "Top product",
"current": { "product_name": "Pro Plan", "product_id": 42, "total_quantity_sold": 18, "total_revenue": 1620.00, "currency": "USD" },
"previous": { "product_name": "Pro Plan", "product_id": 42, "total_quantity_sold": 14, "total_revenue": 1260.00, "currency": "USD" },
"revenue_change": 28.57
},
"top-campaign": {
"label": "Top campaign",
"current": { "campaign_id": 7, "campaign_name": "spring-sale", "total_revenue": 940.00, "currency": "USD" },
"previous": { "campaign_id": 7, "campaign_name": "spring-sale", "total_revenue": 0, "currency": "USD" },
"revenue_change": null
}
},
"request_success": true,
"success": true
}

revenue_change is null when the previous value is zero (division not possible).

quick-wins

Returns a list of data-driven recommendations based on ecommerce performance in the selected period.

Response — data fields:

FieldTypeDescription
quickWinsarrayList of recommendation objects
dateRangeobject / null{ date_start, date_end } of the analysis window, or null if insufficient data

Each item in quickWins:

FieldTypeDescription
typestringRecommendation category (e.g. abandoned_cart, top_product)
keystringUnique identifier for this recommendation
titlestringShort headline
messagestringExplanation of the finding
recommendationstringSuggested action
urlstringLink to the relevant admin page or product
Show code
{
"data": {
"quickWins": [
{
"type": "abandoned_cart",
"key": "high_abandonment_mobile",
"title": "High cart abandonment on mobile",
"message": "76% of mobile sessions that add to cart do not complete the order.",
"recommendation": "Review the mobile checkout flow for friction points.",
"url": "https://example.com/wp-admin/admin.php?page=burst#/statistics"
}
],
"dateRange": { "date_start": "2026-04-01", "date_end": "2026-04-15" }
},
"request_success": true,
"success": true
}

sales-funnel

Returns a five-stage conversion funnel showing drop-off from site visits through to completed orders.

Extra parameters:

ParameterTypeDescription
selected_pagesarray of stringsPage URLs to scope the "Product page views" stage. When omitted, all product pages are counted

Response — data is an indexed array of five stage objects:

FieldTypeDescription
idstringStage identifier
stagestringHuman-readable stage label
valueintCount for the stage

Stages are always returned in this order:

idStage
visitsTotal site visits
product_page_viewsProduct page views
add_to_cartAdd-to-cart events
checkout_visitsCheckout page visits
conversionsCompleted orders
Show code
{
"data": [
{ "id": "visits", "stage": "Visits", "value": 1200 },
{ "id": "product_page_views", "stage": "Product page views", "value": 640 },
{ "id": "add_to_cart", "stage": "Add to cart", "value": 200 },
{ "id": "checkout_visits", "stage": "Checkout", "value": 80 },
{ "id": "conversions", "stage": "Orders", "value": 48 }
],
"request_success": true,
"success": true
}

subscriptions

Added in v3.4.0. Returns the top-level subscription KPIs for the selected period alongside the equivalent previous period values. Subscription data is available when an active subscription integration is detected (WooCommerce Subscriptions, Easy Digital Downloads Recurring or Subscriben).

Prerequisites

  • A subscription integration active on the site
  • view_sales_burst_statistics capability

Response — data fields:

FieldTypeDescription
monthly_recurring_revenueobjectMRR for active subscriptions
active_subscriptionsobjectCount of active subscriptions at period end
canceled_subscriptionsobjectCount of subscriptions canceled within the period
revenue_churnobjectMRR lost to cancellations and the implied churn rate
average_lifetime_valueobjectAverage lifetime revenue per active subscriber

Each field contains label, current, previous and rate_change (percentage change, nullable).

monthly_recurring_revenuecurrent and previous:

FieldTypeDescription
mrrfloatMonthly recurring revenue, normalized to a per-month value
countintActive subscription count contributing to MRR

active_subscriptionscurrent and previous:

FieldTypeDescription
currentintActive subscription count at the end of the period
previousint / nullActive subscription count at the end of the previous period

canceled_subscriptionscurrent and previous:

FieldTypeDescription
currentintSubscriptions canceled within the period
previousint / nullSubscriptions canceled within the previous period

revenue_churncurrent and previous:

FieldTypeDescription
churned_percentagefloatMRR churn rate, relative to the MRR at the start of the period
churned_mrrfloatAbsolute MRR lost in the period
countintNumber of subscriptions that churned
previously_active_countintActive subscriptions at the start of the period (current only)

average_lifetime_valuecurrent and previous:

FieldTypeDescription
valuefloatAverage lifetime revenue per active subscription
active_subscription_countintActive subscription count used as denominator
total_revenuefloatTotal lifetime revenue aggregated across active subscriptions

The top-level monthly_recurring_revenue and average_lifetime_value objects also include the base currency as currency (ISO 4217).

Show code
{
"data": {
"monthly_recurring_revenue": {
"label": "Monthly Recurring Revenue",
"currency": "USD",
"current": { "mrr": 4820.00, "count": 192 },
"previous": { "mrr": 4610.00, "count": 184 },
"rate_change": 4.56
},
"active_subscriptions": {
"label": "Active Subscriptions",
"current": 192,
"previous": 184,
"rate_change": 4.35
},
"canceled_subscriptions": {
"label": "Canceled Subscriptions",
"current": 6,
"previous": 9,
"rate_change": -33.33
},
"revenue_churn": {
"label": "Revenue Churn",
"current": { "churned_percentage": 1.42, "churned_mrr": 65.00, "count": 6, "previously_active_count": 184 },
"previous": { "churned_percentage": 2.01, "churned_mrr": 92.00, "count": 9 },
"rate_change": -29.35
},
"average_lifetime_value": {
"label": "Average Lifetime Value",
"currency": "USD",
"current": { "value": 312.40, "active_subscription_count": 192, "total_revenue": 59980.80 },
"previous": { "value": 298.10, "active_subscription_count": 184, "total_revenue": 54850.40 },
"rate_change": 4.80
}
},
"request_success": true,
"success": true
}

subscriptions-revenue-chart

Added in v3.4.0. Returns bucketed new vs renewal chart data for subscriptions, grouped by day, week or month.

Extra parameters:

ParameterTypeDefaultDescription
group_bystringautoOne of auto, day, week or month
chart_modestringrevenueOne of revenue or sales

Response — data fields:

FieldTypeDescription
intervalstringResolved grouping interval (day, week or month)
spans_multiple_yearsboolWhether the selected range spans more than one calendar year
modestringEchoes the requested chart_mode
currencystringISO 4217 currency code for monetary values
rowsarrayOrdered bucket rows with timestamp, label, newValue and renewalValue

Each item in rows contains:

FieldTypeDescription
timestampintUnix timestamp (UTC) marking the start of the bucket
labelstringDisplay label formatted for the resolved interval
newValuefloat / intNew subscription revenue (or sales count when chart_mode=sales)
renewalValuefloat / intRenewal revenue (or renewal sales count when chart_mode=sales)
Show code
{
"data": {
"interval": "day",
"spans_multiple_years": false,
"mode": "revenue",
"currency": "USD",
"rows": [
{ "timestamp": 1711929600, "label": "Apr 1", "newValue": 180.00, "renewalValue": 420.00 },
{ "timestamp": 1712016000, "label": "Apr 2", "newValue": 90.00, "renewalValue": 510.00 }
]
},
"request_success": true,
"success": true
}

subscriptions-distribution

Added in v3.4.0. Returns a distribution of subscription activity for the selected period across payment gateways, currencies or countries.

Extra parameters:

ParameterTypeDefaultDescription
distribution_viewstringgatewaysOne of gateways, currencies or countries

Response — data is an indexed array of distribution rows:

FieldTypeDescription
idstringStable key for the row (sanitized key)
labelstringHuman-readable label
countintNumber of subscription events attributed to this row
valuefloatShare of total events, as a percentage (two decimals)

Rows are ordered by descending count.

Show code
{
"data": [
{ "id": "stripe", "label": "Stripe", "count": 124, "value": 64.58 },
{ "id": "paypal", "label": "PayPal", "count": 56, "value": 29.17 },
{ "id": "bacs", "label": "Bank transfer", "count": 12, "value": 6.25 }
],
"request_success": true,
"success": true
}

subscriptions-retention

Added in v3.4.0. Returns a monthly cohort retention matrix for subscriptions.

Extra parameters:

ParameterTypeDefaultDescription
product_idint0Optional product filter. 0 means all products

Response — data fields:

FieldTypeDescription
intervalstringRetention interval unit (month, quarter or year)
max_offsetintHighest interval offset present in rows
rowsarrayCohort rows with retention data points
productsarrayProduct filter options detected for the current request

Each cohort row in rows:

FieldTypeDescription
idstringCohort label in the form {label} ({signup_count})
signup_countintSubscriptions acquired in the cohort
dataarrayPoints keyed by offset; each has x, y (nullable float, 0–100), count (nullable int)

Each product filter option in products:

FieldTypeDescription
idintProduct ID
labelstringProduct name
is_yearlyboolWhether all active subscriptions for this product bill yearly
Show code
{
"data": {
"interval": "month",
"max_offset": 3,
"rows": [
{
"id": "Jan 2026 (120)",
"signup_count": 120,
"data": [
{ "x": "M+0", "y": 100.0, "count": 120 },
{ "x": "M+1", "y": 82.5, "count": 99 },
{ "x": "M+2", "y": 74.17, "count": 89 },
{ "x": "M+3", "y": 68.33, "count": 82 }
]
}
],
"products": [
{ "id": 42, "label": "Pro Plan", "is_yearly": false },
{ "id": 58, "label": "Annual Plan", "is_yearly": true }
]
},
"request_success": true,
"success": true
}

datatable/{id}

Changed in v3.4.2: per-product datatables are now exposed as path-based resources. Use data/ecommerce/datatable/{id} instead of passing id on the generic data/ecommerce/datatable endpoint, which returns HTTP 403.

Each {id} carries its own metric allow-list. Incoming metrics are intersected with that allow-list, so unknown metrics are silently dropped and never reach the underlying query. Unknown {id} values return HTTP 404 with the message "Unknown datatable endpoint." Rows always include the dimensional identifiers (e.g. product_id, plan) regardless of which metrics were requested. All monetary values are wrapped in { currency, value } for direct use with the frontend currency renderer.

Supported {id} values:

idDescription
sales_productsPer-product sales breakdown
subscription_productsPer-product subscription breakdown

sales_products

Added in v3.4.2.

Supported metrics:

Metric keyColumnType
productProduct namestring
adds_to_cartAdd-to-cart eventsint
salesUnits soldint
revenueRevenue{ currency, value }
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

Added in v3.4.0. Path-based route added in v3.4.2 — call data/ecommerce/datatable/subscription_products instead of passing id=subscription_products on the generic endpoint. The column set is driven by the requested metrics; all monetary values are wrapped in { currency, value } for direct use with the frontend currency renderer.

Supported metrics:

Metric keyColumnType
planProduct namestring
active_subscribersActive subscriptionsint
canceled_subscribersCanceled subscriptionsint
trialling_subscribersTrialling subscriptionsint
monthly_recurring_revenueMRR{ currency, value }
product_churn_valueProduct churn percentagefloat (percentage)

Rows always include product_id and plan as identifiers.

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"
Show code
{
"data": [
{
"product_id": 42,
"plan": "Pro Plan",
"active_subscribers": 98,
"monthly_recurring_revenue": { "currency": "USD", "value": 2940.00 }
},
{
"product_id": 58,
"plan": "Annual Plan",
"active_subscribers": 41,
"monthly_recurring_revenue": { "currency": "USD", "value": 1230.00 }
}
],
"request_success": true,
"success": true
}

Get actions

Added in v3.4.0. The get_action/ecommerce/{action} route exposes stateful ecommerce lookups that do not fit the period-scoped data/ecommerce/{type} shape.

get_subscriptions_backfill_progress

Reports progress of the subscription data backfill cron that populates historical daily aggregation tables after an integration is first activated.

GET /wp-json/burst/v1/get_action/ecommerce/get_subscriptions_backfill_progress

Response fields:

FieldTypeDescription
is_processingboolWhether a backfill run is currently in progress
progressintCompletion percentage (0100)
processedintNumber of days already processed
totalintTotal number of days scheduled for backfill
Show code
{
"is_processing": true,
"progress": 42,
"processed": 126,
"total": 300
}

When no backfill is running, all numeric fields are 0 and is_processing is false.

Abilities API

Added in v3.4.1. When the Abilities API is enabled (Settings → Advanced → "Enable Abilities API"), Burst Pro registers two ecommerce abilities under the burst-statistics category. These are intended for trusted AI agents and automation tools that consume the WordPress Abilities API rather than the REST routes documented above.

Pro - BusinessAvailable in the Business tier

The ecommerce abilities require Burst Pro with ecommerce tracking active. Learn more about revenue and sales tracking.

:::caution Breaking change Changed in v3.4.2: the abilities permission_callback now requires manage_burst_statistics instead of view_burst_statistics. Callers that previously authenticated as a viewer-only user will receive HTTP 403 with code burst_abilities_forbidden. :::

Prerequisites

  • WordPress build that registers the Abilities API (wp_register_ability) is available
  • The enable_abilities_api option is enabled on the site
  • The calling user has manage_burst_statistics capability
  • BURST_PRO is defined — both abilities return HTTP 503 (burst_abilities_pro_required) on the free plugin

burst/sales-data

Returns ecommerce sales metrics, scoped to events with type=purchase, formatted as a datatable response with explicit dimensions and metric metadata.

Changed in v3.4.2: the ability is routed through the sales_products datatable internally. Requested metrics are intersected with the sales_products allow-list (product, adds_to_cart, sales, revenue); unknown metrics are silently dropped. When the intersection is empty, the default metrics are used as a fallback; when even those are not in the allow-list the ability returns burst_abilities_invalid_metrics (HTTP 400).

Input schema:

FieldTypeDefaultDescription
date_startint0Unix timestamp for start date
date_endint0Unix timestamp for end date
metricsarray of strings["product", "sales", "revenue"]Metric column ids to retrieve. Intersected with the sales_products allow-list
filtersarray of objects[]Additional filter objects; each item must include a key and may include a value. The type=purchase filter is always appended server-side
group_byarray of strings["product"]Grouping columns. utm_source is normalized to source
limitint100Maximum number of rows to return. Clamped to the inclusive range 1–500

Changed in v3.4.2: default metrics is now ["product", "sales", "revenue"] and default group_by is now ["product"] (previously ["revenue"] and ["source"]). filters and limit are accepted as new input fields.

Response fields:

FieldTypeDescription
typestringAlways datatable
dimensionsarrayResolved dimension definitions (id, label)
metricsarrayResolved metric definitions (id, label)
rowsarrayDatatable rows
row_countintNumber of rows returned

burst/subscriptions-data

Returns ecommerce subscription metrics, scoped to events with type=subscription. Input shape, normalization and response shape match burst/sales-data.

Changed in v3.4.2: the ability is routed through the subscription_products datatable internally. Requested metrics are intersected with the subscription_products allow-list (plan, active_subscribers, canceled_subscribers, trialling_subscribers, monthly_recurring_revenue, product_churn_value); unknown metrics are silently dropped.

Input schema:

FieldTypeDefaultDescription
date_startint0Unix timestamp for start date
date_endint0Unix timestamp for end date
metricsarray of strings["plan", "active_subscribers", "canceled_subscribers", "trialling_subscribers", "monthly_recurring_revenue", "product_churn_value"]Metric column ids to retrieve. Intersected with the subscription_products allow-list
filtersarray of objects[]Additional filter objects; each item must include a key and may include a value. The type=subscription filter is always appended server-side
group_byarray of strings["plan"]Grouping columns. utm_source is normalized to source
limitint100Maximum number of rows to return. Clamped to the inclusive range 1–500

Changed in v3.4.2: default metrics is now the full subscription_products column set and default group_by is now ["plan"] (previously ["revenue"] and ["source"]). filters and limit are accepted as new input fields.

Rate limiting

Each ability is rate-limited per user. Defaults are 30 requests per 60-second window; both can be overridden:

Show code
add_filter(
'burst_abilities_rate_limit_max',
static function ( int $max, string $ability ): int {
return $ability === 'sales-data' ? 60 : $max;
},
10,
2
);

add_filter(
'burst_abilities_rate_limit_window',
static function ( int $window, string $ability ): int {
return $window;
},
10,
2
);

When the limit is exceeded, the ability returns a WP_Error with code burst_abilities_rate_limited and HTTP status 429.

Error codes

CodeHTTPCause
burst_abilities_pro_required503BURST_PRO is not defined
burst_abilities_forbidden403Caller lacks manage_burst_statistics or is anonymous
burst_abilities_rate_limited429Per-user rate limit exceeded
burst_abilities_unavailable503Burst admin services could not be bootstrapped
burst_abilities_execution_failed500Underlying statistics query threw an exception
burst_abilities_unknown_datatable404Datatable {id} is not in the per-tier allow-list
burst_abilities_invalid_metrics400No requested or fallback metric is valid for the resolved datatable

Added in v3.4.2: burst_abilities_unknown_datatable and burst_abilities_invalid_metrics are returned by the datatable-routed abilities when the requested datatable or metrics cannot be resolved against the per-datatable allow-list.

Code examples

Sales summary for a date range

Show code
curl -u "wp_user:xxxx xxxx xxxx xxxx xxxx xxxx" \
--get "https://example.com/wp-json/burst/v1/data/ecommerce/sales" \
--data-urlencode "date_start=2026-04-01" \
--data-urlencode "date_end=2026-04-15"

Sales funnel scoped to specific product pages

Show code
curl -u "wp_user:xxxx xxxx xxxx xxxx xxxx xxxx" \
--get "https://example.com/wp-json/burst/v1/data/ecommerce/sales-funnel" \
--data-urlencode "date_start=2026-04-01" \
--data-urlencode "date_end=2026-04-15" \
--data-urlencode "selected_pages[]=/shop/pro-plan/" \
--data-urlencode "selected_pages[]=/shop/enterprise-plan/"

PHP request

Show code
$response = wp_remote_get(
add_query_arg(
[
'date_start' => '2026-04-01',
'date_end' => '2026-04-15',
],
rest_url( 'burst/v1/data/ecommerce/top-performers' )
),
[
'headers' => [
'Authorization' => 'Basic ' . base64_encode( 'wp_user:xxxx xxxx xxxx xxxx xxxx xxxx' ),
],
'timeout' => 15,
]
);

if ( is_wp_error( $response ) ) {
return;
}

$body = json_decode( wp_remote_retrieve_body( $response ), true );

if ( empty( $body['success'] ) ) {
return;
}

$top_product = $body['data']['top-product']['current'] ?? null;

Poll subscription backfill progress

Show code
$response = wp_remote_get(
rest_url( 'burst/v1/get_action/ecommerce/get_subscriptions_backfill_progress' ),
[
'headers' => [
'Authorization' => 'Basic ' . base64_encode( 'wp_user:xxxx xxxx xxxx xxxx xxxx xxxx' ),
],
'timeout' => 15,
]
);

if ( is_wp_error( $response ) ) {
return;
}

$progress = json_decode( wp_remote_retrieve_body( $response ), true );

if ( ! empty( $progress['is_processing'] ) ) {
// Show progress bar: $progress['progress'] %
}

Invoke the burst/sales-data ability

Show code
if ( ! function_exists( 'wp_execute_ability' ) ) {
return;
}

$result = wp_execute_ability(
'burst/sales-data',
[
'date_start' => strtotime( '2026-04-01 00:00:00' ),
'date_end' => strtotime( '2026-04-15 23:59:59' ),
'metrics' => [ 'product', 'sales', 'revenue' ],
'filters' => [
[ 'key' => 'country_code', 'value' => 'NL' ],
],
'group_by' => [ 'product' ],
'limit' => 50,
]
);

if ( is_wp_error( $result ) ) {
return;
}

foreach ( $result['rows'] as $row ) {
// Each row is keyed by dimension and metric ids.
}

Troubleshooting

HTTP 403 on a request that previously worked From v3.3.0 onward, view_burst_statistics is no longer sufficient for these endpoints. Ensure the user has view_sales_burst_statistics. Grant it directly or by assigning the appropriate role in Burst Pro's user management.

HTTP 403 from data/ecommerce/datatable without an {id} From v3.4.2 onward, the generic datatable endpoints are blocked. Switch to the path-based form, for example data/ecommerce/datatable/subscription_products, and remove the id query parameter.

date_start in the response differs from the value sent Burst clamps date_start to the ecommerce activation date when the requested range predates ecommerce tracking. The response reflects the actual queried window. Subscription-related types (including the subscription_products datatable) skip this clamp and use the earliest subscription date instead.

Empty subscription responses Subscription endpoints return empty payloads when no supported subscription integration is active or when the integration reports no subscription data yet. Verify that WooCommerce Subscriptions, Easy Digital Downloads Recurring or Subscriben is active and that at least one subscription exists.

Abilities return HTTP 503 burst_abilities_pro_required The burst/sales-data and burst/subscriptions-data abilities only execute when BURST_PRO is defined. Confirm Burst Pro is active on the site issuing the call.

Abilities return HTTP 403 burst_abilities_forbidden From v3.4.2 onward, the abilities require manage_burst_statistics. Viewer-only users that previously worked must be granted the manage capability or call the REST routes directly with the appropriate sales capability.

Abilities return HTTP 400 burst_abilities_invalid_metrics None of the requested metrics — and none of the defaults — are present in the resolved datatable's allow-list. Re-check the metric list against the table in the relevant datatable/{id} section above.

Abilities are not registered The category and abilities only register when wp_register_ability() exists and the enable_abilities_api option is true. Enable the setting at Settings → Advanced and confirm the host WordPress build ships the Abilities API.