Tours REST API
Product tours are the guided walkthroughs shown in the Benecaster admin. The REST surface has two endpoints: one records that a user finished a tour, and one records that they turned down an updated version of it.
Tour state is tracked per user, not per site. Finishing or declining a tour on your own account has no effect on anyone else’s.
Benecaster’s own tour runtime calls both endpoints for you. An add-on registering a tour does not need to call either one; its only part is the tour’s contentVersion (see Register a guided product tour from an add-on JS bundle).
POST /tours/{id}/complete
Marks a product tour as completed for the current user, at the version they took.
Auth: Cookie + nonce. Any logged-in user. This is not restricted to administrators, because tours are shown to whoever is using the admin.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
id |
path | string | Tour identifier, e.g. overview |
version |
body | integer ≥ 1 | Optional. The tour’s contentVersion at completion. Defaults to 1 |
Response — 200
{
"tour_id": "overview",
"completed_at": "2026-10-02 14:23:00",
"version": 1
}
completed_at is a UTC MySQL datetime (Y-m-d H:i:s).
Re-completing overwrites. Posting again for a tour already completed returns 200 and replaces both completed_at and the stored version, so the record always reflects the most recent completion. A double submission is harmless.
There is no “tour not found” error. Tours are registered in the browser, so the server has no list to check against. Any id made of lowercase letters, digits, hyphens and underscores is accepted and stored.
POST /tours/{id}/decline-reprompt
Records that the current user answered No thanks to the bar offering an updated tour again.
Auth: Cookie + nonce. Any logged-in user.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
id |
path | string | Tour identifier |
version |
body | integer ≥ 1 | Required. The contentVersion being declined |
Response — 200
{
"tour_id": "overview",
"declined": 2
}
The server keeps the higher of the version sent and the version already stored, and declined is that stored value. An older browser tab answering an older offer therefore cannot undo a newer decline.
A decline lasts for that version only. When the tour’s contentVersion is raised again, the user is offered it again.
Notes for Add-on Developers
There is no endpoint to un-complete a tour or to read tour state. If you need to re-show a tour during development, launch it with ?bc_tour={id} or clear the stored state directly. It is held in user meta as benecaster_tour_{id}_completed_at, benecaster_tour_{id}_version and benecaster_tour_{id}_reprompt_declined.
Pointing a step at an episode-editor tab. Give the step screen: 'episode-tab:{tabId}', where {tabId} is a tab’s id: one of Benecaster’s own tabs (media, more, …) or one your add-on declares with benecaster_episode_editor_tabs. The tour opens the current show’s most recent episode on that tab. To choose the episode yourself, register window.BenecasterExtensions.registerEpisodeTabLookup( tabId, showId => episodeId | null ); it is called once, when the tour launches, may return a Promise, and returns an unregister function. The step is dropped rather than shown when there is no current show, the tab is hidden for that show (your add-on is switched off there), the show has no episode, your lookup returns null, or a lookup fails. Never write a fixed /episodes/123?tab=… path into a step: that episode may not exist on the podcaster’s site.
To stop updated tours being offered again on a site, use the benecaster_tour_reprompt_enabled filter rather than these endpoints.
See Also
Need this built rather than just documented? See our services →