Authentication
Burst data endpoints support three authentication methods: WordPress nonces for browser-based requests, Application Passwords for server-to-server integrations and signed MainWP proxy payloads for MainWP dashboard requests.
Application Passwords (recommended for external tools)
Application Passwords allow server-to-server requests without a browser session or CSRF nonce. When a request is authenticated this way, Burst skips nonce verification entirely — the verify_nonce helper short-circuits to true once WordPress has authenticated the request through application_password_did_authenticate and an HTTP Basic Authorization header is present.
Setup:
- In WordPress, go to Users > Profile for the user that will own the integration
- Scroll to Application Passwords
- Enter a name (e.g.
Burst API) and click Add new application password - Copy the generated password immediately — it is not shown again
Use HTTP Basic Auth with the WordPress username and the application password:
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"
The application password contains spaces as displayed; pass it exactly as copied.
Capability requirements:
The user account must hold the capability matching the endpoint's permission level:
| Endpoint group | Required capability |
|---|---|
burst/v1/data/{type} | view_burst_statistics |
burst/v1/data/ecommerce/{type} | view_sales_burst_statistics |
burst/v1/menu, fields/*, options/*, goals/* (write) | manage_burst_statistics |
Administrators have all three capabilities by default. For a read-only integration user, assign the burst_viewer role or grant view_burst_statistics directly.
Nonce authentication (browser / dashboard requests)
The Burst admin dashboard authenticates via the standard WordPress REST nonce mechanism. Include the nonce in the X-WP-Nonce header:
Show code
fetch( '/wp-json/burst/v1/data/today', {
headers: {
'X-WP-Nonce': burstSettings.nonce,
},
} );
The nonce action is burst_nonce. Nonces expire after the standard WordPress nonce lifetime (24 hours by default).
All write endpoints (POST) require a valid nonce regardless of authentication method for browser-originated requests. The burst_verify_nonce filter can be used to extend or override verification logic — see Filters reference.
AJAX fallback endpoints
When the WordPress REST API is blocked by a security plugin or server configuration, the admin dashboard falls back to admin-ajax.php. As of v3.4.1 the single fallback handler is split into two capability-scoped actions so that read and write traffic cannot be confused at the transport layer.
| AJAX action | Capability | Allowed routes |
|---|---|---|
burst_rest_api_fallback_get_action | view_burst_statistics | Read endpoints (/get_action/*, data fetches) |
burst_rest_api_fallback_do_action | manage_burst_statistics | Write endpoints (/options/set, /fields/set, /goals/add, /goals/delete, /goals/set, /goals/add_predefined, /do_action/*) |
Each handler verifies the caller's capability before dispatching, and the dispatcher additionally rejects requests whose action path does not match the handler's scope (for example, a write action submitted to the read handler returns a forbidden response). A valid burst_nonce is still required on every fallback request.
Share link tokens (Pro)
Pro - CreatorAvailable in the Creator tier
Share link authentication is only available in Burst Pro.
Share link viewers send the token in the X-Burst-Share-Token HTTP header on every REST request. The nonce verification layer treats a valid token as equivalent to a valid nonce for users with the burst_viewer role.
Token format: 32-character lowercase hexadecimal (bin2hex( random_bytes( 16 ) )). Values not matching /^[a-f0-9]{32}$/ are rejected without further processing — the strict validation runs at the token-read boundary, so a malformed token cannot reach any downstream lookup or comparison.
Changed in v3.4.2: the dashboard is now served from path-based routes (/burst-dashboard/{tab}/) instead of a single hash-routed page. Each share token is bound to a specific tab at creation time, and the routing layer resolves the requested tab from the URL path (for page loads) or from the REST endpoint path (for API calls). Legacy hash URLs like /burst-dashboard/?burst_share_token=...#/statistics are served a small upgrade page that rewrites the URL into the path-based format before loading the app.
Token transport:
| Channel | Header / param | Notes |
|---|---|---|
| REST and AJAX | X-Burst-Share-Token | Preferred; resolved first |
| Page load and fallback | burst_share_token query parameter | Used for the initial dashboard load; consumed by the path router |
Endpoint-to-tab access control:
Changed in v3.4.2: share-token access is now enforced through a deny-by-default endpoint-to-tab map rather than capability checks alone. Every REST endpoint is mapped to a tab slug via the burst_endpoint_tab_map filter; generic datatable endpoints are resolved through the burst_datatable_id_tab_map filter using the datatable id. A request is allowed only when:
- The resolved tab exists in the map (unmapped endpoints are denied)
- The resolved tab is present in the token's
shared_tabsfield - For ecommerce endpoints,
salesis inshared_tabs - For story-mode tokens (
report_id > 0), the endpoint resource matches one of the blocks declared in the report
Filter-dependent endpoints such as get_action/get_filter_options, goals/get, and posts additionally require the can_filter permission flag on the token.
Path routing:
Direct page loads resolve the tab from the URL segment after /burst-dashboard/:
https://example.com/burst-dashboard/statistics/?burst_share_token=<32-hex>
https://example.com/burst-dashboard/sales/?burst_share_token=<32-hex>
https://example.com/burst-dashboard/story/?burst_share_token=<32-hex>
A request whose path tab is not in the token's shared_tabs returns a 403-style wp_die() response. Report share links always route to /burst-dashboard/story/.
Viewer user hardening:
The shared dashboard authenticates the visitor as the burst_statistics_viewer user, which holds only the burst_viewer role and the view_burst_statistics capability. Application Passwords are disabled for this role (see admonition above), so a share-link recipient cannot mint a credential that outlives the token.
Share link access is scoped at token creation time. A viewer can only reach the data types and dashboard tabs listed in the token's shared_tabs field. Access to ecommerce endpoints additionally requires sales in shared_tabs.
For full share link setup and management, see Share links.
MainWP proxy authentication
MainWP integration is only available when the MainWP add on is installed.
Added in v3.4.0: the MainWP dashboard authenticates to child sites through a dedicated proxy endpoint at burst/v1/mainwp-auth. Rather than exposing long-lived credentials, the dashboard sends a signed payload and the child issues a short-lived Application Password for the duration of the session.
Changed in v3.4.1: the endpoint is now gated by a check_auth_permission callback that runs before the route handler. The permission gate enforces one of two acceptance paths and rejects everything else (subscribers, anonymous unsigned callers, forged signatures) before the Application Password mint path can be reached.
Permission gate (v3.4.1):
| Path | Requirements |
|---|---|
| Server-to-server bootstrap | Body contains a valid MainWP signature, user resolves to an existing WordPress account, and that account holds manage_burst_statistics. The current user is switched to the resolved account and the verified dashboard_origin is persisted to the burst_mainwp_dashboard_url option for later CORS reflection |
| Same-session reuse | Caller is already logged in and holds manage_burst_statistics |
The dashboard origin option is only written from inside the permission gate after a successful signature verification. There is no longer a code path that updates burst_mainwp_dashboard_url from an unverified header or body field at the route handler level.
Request flow:
- The dashboard signs
function.nonce(orfunction|nonce|useron newer builds) with its RSA private key - The child verifies the signature against the stored public key in the
mainwp_child_pubkeyoption usingopenssl_verify()with SHA-256 (or SHA-1 whenverifylibis set) - The child resolves the WordPress user named in the payload and confirms the user has
manage_burst_statistics - The child removes any prior
Burst MainWPApplication Passwords for that user and generates a fresh one viaWP_Application_Passwords::create_new_application_password() - The base64-encoded
user:passwordtoken is cached in a transient for one hour and returned to the dashboard along with a REST root URL and localization data
Subsequent REST requests from the dashboard use the returned token as an HTTP Basic credential and include the X-BurstMainWP: 1 header so the child can scope CORS headers to the paired dashboard origin stored in the burst_mainwp_dashboard_url option. On each such request, MainWP_Proxy::is_mainwp_authenticated() validates the credential via wp_validate_application_password() and confirms the resolved user still holds manage_burst_statistics before calling wp_set_current_user().
Token lifetime:
The plain-text token is stored only in the burst_mainwp_app_token_{user_id} transient for one hour. When the transient expires, the next signed request deletes the old Application Password and creates a new one — the raw credential is never persisted to user meta.
Signature requirements:
| Field | Description |
|---|---|
function | Identifier of the action being authorized |
nonce | Per-request random value to prevent replays |
user | WordPress login of the admin account on the child site |
mainwpsignature | Base64-encoded RSA signature over the payload |
verifylib | 1 for phpseclib (SHA-1), 0 for OpenSSL (SHA-256) |
dashboard_origin | Optional dashboard URL used for CORS pairing when the Origin header is missing |
CORS credentials:
Changed in v3.4.1: Access-Control-Allow-Credentials: true is only emitted when the request Origin exactly matches the paired dashboard origin stored in burst_mainwp_dashboard_url. During the unpaired bootstrap request to burst/v1/mainwp-auth, the response carries Access-Control-Allow-Origin but omits the credentials header — the first signed call must not depend on a logged-in cookie. Once pairing is complete, subsequent same-origin browser requests receive the credentials header and can use the session cookie alongside the issued Application Password.
Headless client authentication (Pro)
Pro - CreatorAvailable in the Creator tier
Headless tracking is only available in Burst Pro.
Added in v3.4.0: when BURST_HEADLESS_DOMAIN is defined, the plugin exposes a Burst Client plugin that tracks pageviews on a separate frontend (e.g. a decoupled Next.js site) and forwards hook-based goal completions back to the WordPress install.
Generate the client plugin by downloading the zip from Settings > Advanced > Download Burst Client plugin. The download endpoint (includes/Pro/Admin/Headless/download.php) generates a fresh random token with wp_generate_password( 32, false, false ), writes it into the bundled settings.php, and stores only its SHA-256 hash in the burst_headless_token_hash option. The raw token lives exclusively in the downloaded zip — it is never persisted to wp_options.
The client sends the token in the Authorization: Bearer <token> header on every request to burst/v1/client/hooks/get and burst/v1/client/register_hook:
curl -H "Authorization: Bearer <raw_token>" \
-H "Origin: https://headless.example.com" \
"https://example.com/wp-json/burst/v1/client/hooks/get"
The server hashes the incoming token with SHA-256 and compares it to the stored hash using hash_equals(), so timing attacks cannot leak information about the expected value.
Origin validation:
Each request is additionally checked against BURST_HEADLESS_DOMAIN. The Origin header is matched first, then the Referer header as a fallback. Exact host matches and subdomains of the configured domain are accepted; all other origins receive 403 Forbidden.
Note: this domain check is a misconfiguration guard, not a security boundary — Origin and Referer are set by the HTTP client and can be spoofed by any non-browser caller. The bearer token verified server-side is the only authentication on these routes.
Rotating the token:
Re-download the client plugin from the settings screen to issue a new token. The previous hash is overwritten, immediately invalidating the old credential.