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_statisticscapability - 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}:
| 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 |
filters | array / JSON string | [] | Filter payload. Accepts arrays, JSON objects or comma-separated strings |
metrics | array / string | varies by type | Metric names to include |
group_by | array / string | varies by type | Grouping 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:
| Field | Type | Description |
|---|---|---|
conversion-rate | object | Visitor-to-order conversion rate |
abandonment-rate | object | Cart abandonment rate |
average-order | object | Average order value |
revenue | object | Total revenue |
Each field contains label, current and previous blocks. The inner structure varies by metric:
conversion-rate — current and previous:
| Field | Type | Description |
|---|---|---|
visitors | int | Total unique visitors |
total_converted | int | Visitors who completed an order |
conversion_rate | float | Percentage of visitors who converted |
abandonment-rate — current and previous:
| Field | Type | Description |
|---|---|---|
total_carts | int | Sessions where a product was added to cart |
total_converted | int | Sessions that resulted in an order |
total_abandoned | int | Sessions that added to cart but did not convert |
abandoned_rate | float | Abandonment percentage |
average-order and revenue — current and previous:
| Field | Type | Description |
|---|---|---|
total_orders | int | Number of completed orders |
total_revenue | float | Sum of order revenue |
average_order_value | float | Average revenue per order |
currency | string | ISO 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:
| Field | Type | Description |
|---|---|---|
top-product | object | Best-performing product by revenue |
top-campaign | object | Best-performing UTM campaign by revenue |
top-country | object | Country generating the most revenue |
top-device | object | Device category generating the most revenue |
Each field contains label, current, previous and revenue_change (percentage change, nullable).
top-product — current and previous:
| Field | Type | Description |
|---|---|---|
product_name | string | WooCommerce product name |
product_id | int | WooCommerce product ID |
total_quantity_sold | int | Units sold in the period |
total_revenue | float | Revenue generated |
currency | string | ISO 4217 currency code |
top-campaign — current and previous:
| Field | Type | Description |
|---|---|---|
campaign_id | int | Internal campaign ID |
campaign_name | string | UTM campaign value |
total_revenue | float | Revenue attributed to the campaign |
currency | string | ISO 4217 currency code |
top-country — current and previous:
| Field | Type | Description |
|---|---|---|
country_code | string | ISO 3166-1 alpha-2 country code |
total_revenue | float | Revenue from this country |
currency | string | ISO 4217 currency code |
top-device — current and previous:
| Field | Type | Description |
|---|---|---|
device_name | string | Device category name |
total_revenue | float | Revenue from this device category |
currency | string | ISO 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:
| Field | Type | Description |
|---|---|---|
quickWins | array | List of recommendation objects |
dateRange | object / null | { date_start, date_end } of the analysis window, or null if insufficient data |
Each item in quickWins:
| Field | Type | Description |
|---|---|---|
type | string | Recommendation category (e.g. abandoned_cart, top_product) |
key | string | Unique identifier for this recommendation |
title | string | Short headline |
message | string | Explanation of the finding |
recommendation | string | Suggested action |
url | string | Link 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:
| Parameter | Type | Description |
|---|---|---|
selected_pages | array of strings | Page 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:
| Field | Type | Description |
|---|---|---|
id | string | Stage identifier |
stage | string | Human-readable stage label |
value | int | Count for the stage |
Stages are always returned in this order:
id | Stage |
|---|---|
visits | Total site visits |
product_page_views | Product page views |
add_to_cart | Add-to-cart events |
checkout_visits | Checkout page visits |
conversions | Completed 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_statisticscapability
Response — data fields:
| Field | Type | Description |
|---|---|---|
monthly_recurring_revenue | object | MRR for active subscriptions |
active_subscriptions | object | Count of active subscriptions at period end |
canceled_subscriptions | object | Count of subscriptions canceled within the period |
revenue_churn | object | MRR lost to cancellations and the implied churn rate |
average_lifetime_value | object | Average lifetime revenue per active subscriber |
Each field contains label, current, previous and rate_change (percentage change, nullable).
monthly_recurring_revenue — current and previous:
| Field | Type | Description |
|---|---|---|
mrr | float | Monthly recurring revenue, normalized to a per-month value |
count | int | Active subscription count contributing to MRR |
active_subscriptions — current and previous:
| Field | Type | Description |
|---|---|---|
current | int | Active subscription count at the end of the period |
previous | int / null | Active subscription count at the end of the previous period |
canceled_subscriptions — current and previous:
| Field | Type | Description |
|---|---|---|
current | int | Subscriptions canceled within the period |
previous | int / null | Subscriptions canceled within the previous period |
revenue_churn — current and previous:
| Field | Type | Description |
|---|---|---|
churned_percentage | float | MRR churn rate, relative to the MRR at the start of the period |
churned_mrr | float | Absolute MRR lost in the period |
count | int | Number of subscriptions that churned |
previously_active_count | int | Active subscriptions at the start of the period (current only) |
average_lifetime_value — current and previous:
| Field | Type | Description |
|---|---|---|
value | float | Average lifetime revenue per active subscription |
active_subscription_count | int | Active subscription count used as denominator |
total_revenue | float | Total 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:
| Parameter | Type | Default | Description |
|---|---|---|---|
group_by | string | auto | One of auto, day, week or month |
chart_mode | string | revenue | One of revenue or sales |
Response — data fields:
| Field | Type | Description |
|---|---|---|
interval | string | Resolved grouping interval (day, week or month) |
spans_multiple_years | bool | Whether the selected range spans more than one calendar year |
mode | string | Echoes the requested chart_mode |
currency | string | ISO 4217 currency code for monetary values |
rows | array | Ordered bucket rows with timestamp, label, newValue and renewalValue |
Each item in rows contains:
| Field | Type | Description |
|---|---|---|
timestamp | int | Unix timestamp (UTC) marking the start of the bucket |
label | string | Display label formatted for the resolved interval |
newValue | float / int | New subscription revenue (or sales count when chart_mode=sales) |
renewalValue | float / int | Renewal 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:
| Parameter | Type | Default | Description |
|---|---|---|---|
distribution_view | string | gateways | One of gateways, currencies or countries |
Response — data is an indexed array of distribution rows:
| Field | Type | Description |
|---|---|---|
id | string | Stable key for the row (sanitized key) |
label | string | Human-readable label |
count | int | Number of subscription events attributed to this row |
value | float | Share 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:
| Parameter | Type | Default | Description |
|---|---|---|---|
product_id | int | 0 | Optional product filter. 0 means all products |
Response — data fields:
| Field | Type | Description |
|---|---|---|
interval | string | Retention interval unit (month, quarter or year) |
max_offset | int | Highest interval offset present in rows |
rows | array | Cohort rows with retention data points |
products | array | Product filter options detected for the current request |
Each cohort row in rows:
| Field | Type | Description |
|---|---|---|
id | string | Cohort label in the form {label} ({signup_count}) |
signup_count | int | Subscriptions acquired in the cohort |
data | array | Points keyed by offset; each has x, y (nullable float, 0–100), count (nullable int) |
Each product filter option in products:
| Field | Type | Description |
|---|---|---|
id | int | Product ID |
label | string | Product name |
is_yearly | bool | Whether 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:
id | Description |
|---|---|
sales_products | Per-product sales breakdown |
subscription_products | Per-product subscription breakdown |
sales_products
Added in v3.4.2.
Supported metrics:
| Metric key | Column | Type |
|---|---|---|
product | Product name | string |
adds_to_cart | Add-to-cart events | int |
sales | Units sold | int |
revenue | Revenue | { 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 key | Column | Type |
|---|---|---|
plan | Product name | string |
active_subscribers | Active subscriptions | int |
canceled_subscribers | Canceled subscriptions | int |
trialling_subscribers | Trialling subscriptions | int |
monthly_recurring_revenue | MRR | { currency, value } |
product_churn_value | Product churn percentage | float (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:
| Field | Type | Description |
|---|---|---|
is_processing | bool | Whether a backfill run is currently in progress |
progress | int | Completion percentage (0–100) |
processed | int | Number of days already processed |
total | int | Total 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_apioption is enabled on the site - The calling user has
manage_burst_statisticscapability BURST_PROis 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:
| Field | Type | Default | Description |
|---|---|---|---|
date_start | int | 0 | Unix timestamp for start date |
date_end | int | 0 | Unix timestamp for end date |
metrics | array of strings | ["product", "sales", "revenue"] | Metric column ids to retrieve. Intersected with the sales_products allow-list |
filters | array 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_by | array of strings | ["product"] | Grouping columns. utm_source is normalized to source |
limit | int | 100 | Maximum 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:
| Field | Type | Description |
|---|---|---|
type | string | Always datatable |
dimensions | array | Resolved dimension definitions (id, label) |
metrics | array | Resolved metric definitions (id, label) |
rows | array | Datatable rows |
row_count | int | Number 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:
| Field | Type | Default | Description |
|---|---|---|---|
date_start | int | 0 | Unix timestamp for start date |
date_end | int | 0 | Unix timestamp for end date |
metrics | array 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 |
filters | array 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_by | array of strings | ["plan"] | Grouping columns. utm_source is normalized to source |
limit | int | 100 | Maximum 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
| Code | HTTP | Cause |
|---|---|---|
burst_abilities_pro_required | 503 | BURST_PRO is not defined |
burst_abilities_forbidden | 403 | Caller lacks manage_burst_statistics or is anonymous |
burst_abilities_rate_limited | 429 | Per-user rate limit exceeded |
burst_abilities_unavailable | 503 | Burst admin services could not be bootstrapped |
burst_abilities_execution_failed | 500 | Underlying statistics query threw an exception |
burst_abilities_unknown_datatable | 404 | Datatable {id} is not in the per-tier allow-list |
burst_abilities_invalid_metrics | 400 | No 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.