Setup Wizard REST API
Endpoints used by the setup wizard and migration-related screens. Covers wizard step progression, episode import, migration redirect settings, and Patreon shadow subscriber visibility. All endpoints require manage_options and a valid X-WP-Nonce header unless noted otherwise.
Wizard Progression
POST /benecaster/v1/wizard/steps/{id}/complete
Marks a first-run wizard step as complete. {id} is the step’s id, as listed in benecaster_setup_wizard_steps — for example subscribers or tiers.
Body: optional.
| Field | Type | Description |
|---|---|---|
show_id |
integer | The show being set up. When greater than 0 it is recorded as the wizard’s show. |
membership_mode |
string | subscribers step only: paid or public. Any other value is ignored. |
Response:
{
"success": true,
"step_id": "subscribers"
}
Errors:
| Code | HTTP | Condition |
|---|---|---|
invalid_step |
404 | {id} is not a step in the wizard, or is done |
Step definitions are filterable via benecaster_setup_wizard_steps — add-ons can inject additional steps.
POST /benecaster/v1/wizard/complete
Marks the wizard as complete and fires the benecaster_setup_wizard_completed action with the show and its active bridge.
Body: optional. show_id (integer) names the show; without it, the show recorded by the step endpoint is used.
Response:
{
"success": true
}
There are no error responses beyond authentication: the call does not check that every step was completed.
POST /benecaster/v1/wizard/reset
Returns the wizard to its first-run state, for development and testing. Clears the completion and dismissal flags, the recorded show, the membership mode, every step’s completion marker, and every record of an add-on step offered after setup, on every show. Then fires benecaster_setup_wizard_reset. Shows, episodes and subscribers are untouched.
Body: none.
Response: { "success": true }
Errors:
| Code | HTTP | Condition |
|---|---|---|
disabled_in_production |
403 | The site is not a local, development or staging environment and WP_DEBUG is off |
Add-on Steps After Setup
An add-on installed after the wizard was finished can ask for its step to be run on a show with benecaster_request_wizard_step(). The setup page that runs those steps settles each one through these two endpoints. Each step is settled once per show: completing or declining it is final.
POST /benecaster/v1/wizard/shows/{show_id}/late-steps/{id}/complete
Completes a requested add-on step for one show. {id} is the step’s id. Completion is recorded for that show only; the site-wide step marker the first-run endpoint writes is not touched. Fires benecaster_wizard_late_step_completed the first time. Repeating the call for a completed step returns 200.
Body: none.
Response:
{
"success": true,
"step_id": "my-addon-config",
"show_id": 45,
"state": "complete"
}
Errors:
| Code | HTTP | Condition |
|---|---|---|
late_step_not_pending |
404 | The step was never requested for this show, or it was declined |
POST /benecaster/v1/wizard/shows/{show_id}/late-steps/{id}/decline
Declines a requested add-on step for one show, permanently: it is not offered on that show again. Fires benecaster_wizard_late_step_declined the first time; repeating the call for a declined step returns 200. The setup page calls this for a skipped step and, when the podcaster leaves part-way, for the step on screen and every step after it.
Body: none.
Response: as for complete, with "state": "declined".
Errors:
| Code | HTTP | Condition |
|---|---|---|
late_step_not_pending |
404 | The step was never requested for this show, or it was completed |
Episode Import
POST /benecaster/v1/shows/{id}/import
Starts a one-time bulk import of every episode in a source RSS feed. Distinct from the recurring feed sync — this imports everything, not just new items. Typically used during setup to bring existing episodes from a previous podcast host. Episodes arrive as drafts.
Body:
{
"feed_url": "https://feeds.buzzsprout.com/12345.rss"
}
The import runs in the background. The call returns straight away with the job’s first progress snapshot; poll GET below until status is complete or failed. Episodes an earlier import already brought in from a feed are skipped (matched on the source feed’s GUID), so re-running over the same feed does not duplicate them. An episode you created by hand in Benecaster has no source GUID, so importing your own Benecaster feed would duplicate it.
Response — 200:
{
"status": "running",
"imported": 0,
"total": 0,
"skipped": 0,
"errors": 0
}
One import per show at a time, and nothing enforces it. Starting a second import while one is running is not refused: the new job becomes the one GET reports on, and the running job’s progress can no longer be read, although it keeps working. Read GET first and do not start another while status is running.
Errors:
| Code | HTTP | Condition |
|---|---|---|
rest_not_found |
404 | Show ID does not exist |
invalid_feed_url |
400 | feed_url missing or not a valid URL |
A feed that cannot be fetched or read does not fail the request — the job starts, then reports status: "failed" with an error_msg.
GET /benecaster/v1/shows/{id}/import
Returns the progress of the show’s current import job — the same shape POST returns.
Response:
{
"status": "complete",
"imported": 16,
"total": 84,
"skipped": 68,
"errors": 0
}
status is idle (no import has been started for this show), running, complete or failed. error_msg is present only when status is failed. skipped counts episodes an earlier import already brought in; errors counts items that could not be created. The job ID is not exposed — this always reports the show’s most recent job.
Migration / Redirect Settings
PUT /benecaster/v1/shows/{id}/migration
Update migration and redirect settings for a show. Used by the setup wizard’s Migration step and the Show Settings → Migration tab.
Body:
{
"redirect_from_url": "https://feeds.buzzsprout.com/12345.rss",
"new_feed_url": null,
"redirect_expires": "2026-08-17"
}
| Field | Description |
|---|---|
redirect_from_url |
The old feed URL this show is replacing. Stored for reference and shown in setup UI. Not used to generate redirects — feed redirect is handled by a 301 rewrite rule. |
new_feed_url |
If set, Benecaster emits <itunes:new-feed-url> in its own feed pointing here. Use when migrating away from Benecaster. |
redirect_expires |
Date to stop emitting the <itunes:new-feed-url> tag. After this date, the tag is omitted from the feed. Fires benecaster_redirect_expiry_run when the cron removes it. |
All fields are optional — only provided fields are updated.
Response: Updated show object with migration fields.
Errors:
| Code | HTTP | Condition |
|---|---|---|
show_not_found |
404 | Show ID does not exist |
invalid_param |
400 | redirect_expires is not a valid date; new_feed_url or redirect_from_url not a valid URL |
Shadow Subscriber Visibility (Patreon Import)
These endpoints manage the “visibility” scorecard — a platform’s patron or subscriber list uploaded for comparison with Benecaster subscribers before a migration decision.
GET /benecaster/v1/shows/{id}/visibility
Returns the current shadow subscriber state for a show — one entry per uploaded platform.
Response:
{
"items": [
{
"platform": "patreon",
"patron_count": 89,
"uploaded_at": "2026-04-17T09:00:00",
"expires_at": "2026-07-16T09:00:00",
"expired": false
}
]
}
| Field | Description |
|---|---|
platform |
Platform identifier: patreon, supercast, or a custom slug |
patron_count |
Number of patron records in the uploaded dataset |
uploaded_at |
ISO 8601 datetime of the most recent upload |
expires_at |
ISO 8601 datetime when this data will be automatically removed (90 days from upload) |
expired |
true when past expires_at — data has been purged; re-upload required |
Errors:
| Code | HTTP | Condition |
|---|---|---|
show_not_found |
404 | Show ID does not exist |
POST /benecaster/v1/shows/{id}/visibility/csv
Upload a patron export CSV to populate the shadow subscriber scorecard.
Body: multipart/form-data with a file field containing the CSV.
Response:
{
"platform": "patreon",
"patrons_imported": 89,
"patrons_already_subscribed": 12,
"expires_at": "2026-07-16T09:00:00"
}
| Field | Description |
|---|---|
patrons_imported |
Total patron records in the uploaded CSV |
patrons_already_subscribed |
Patrons already found as active Benecaster subscribers (deduped on email) |
expires_at |
90 days from upload — when the data will be automatically removed |
The platform (e.g. patreon) is auto-detected from the CSV structure. Re-uploading for the same platform resets the uploaded_at and expires_at clocks and replaces all previous records.
Errors:
| Code | HTTP | Condition |
|---|---|---|
show_not_found |
404 | Show ID does not exist |
invalid_param |
400 | No file provided |
invalid_csv |
422 | CSV format not recognized |
POST /benecaster/v1/shows/{id}/visibility/count
Register a manual patron count without uploading a CSV. For platforms that don’t support CSV export or when only an aggregate number is available.
Body:
{
"platform": "patreon",
"count": 47
}
Response:
{
"platform": "patreon",
"patron_count": 47,
"uploaded_at": "2026-05-17T09:00:00",
"expires_at": "2026-08-15T09:00:00"
}
Manual count entries are not deduplicable (no individual records) and expire at the same 90-day schedule as CSV uploads.
DELETE /benecaster/v1/shows/{id}/visibility/{platform}
Removes all shadow subscriber data for a specific platform from a show. Equivalent to the Clear button on the show’s Visibility tab.
Response: 204 No Content
Errors:
| Code | HTTP | Condition |
|---|---|---|
show_not_found |
404 | Show ID does not exist |
rest_not_found |
404 | No visibility data for this platform on this show |
See Also
Need this built rather than just documented? See our services →