Promote to Bridge REST API
Admin REST endpoints for the Promote to Bridge wizard and Promotion History panel. All endpoints require manage_options capability and a valid WP REST nonce.
Base path: /wp-json/benecaster/v1/shows/{show_id}/promote
Get Writable Bridge Targets
GET /shows/{show_id}/promote/targets
Returns all bridges that implement BridgeWritable — the destination options shown in the wizard’s first step. Each entry includes the bridge’s available tiers (external membership levels).
Response:
[
{
"slug": "memberpress",
"name": "MemberPress",
"tiers": [
{ "id": "1", "name": "Gold Membership" },
{ "id": "2", "name": "Silver Membership" }
]
}
]
Preview a Promotion Run
GET /shows/{show_id}/promote/preview?target_bridge_slug={slug}&tier_map[native_slug]={external_id}
Returns subscriber counts per mapped tier without executing the run. Used by the wizard’s confirmation step to show how many subscribers will be affected.
Response:
{
"tiers": [
{ "slug": "gold", "external_id": "1", "count": 47 },
{ "slug": "silver", "external_id": "2", "count": 23 }
],
"total": 70
}
Run a Promotion
POST /shows/{show_id}/promote/run
Executes the promotion. Long-running for large subscriber lists; runs synchronously.
Request body:
{
"target_bridge_slug": "memberpress",
"tier_map": {
"gold": "1",
"silver": "2"
},
"grace_days": 30
}
grace_days is the default for the run rather than a flat value for every row: the benecaster_promote_grace_length_days filter can vary it per tier or per subscriber, so individual rows may differ from the number sent. The grace_period_ends_at in the response is calculated from this baseline and is not a summary of what each row actually received — read promote_grace_period_ends_at per row from the Promotion History listing when the filter is in use.
Response: 200 OK
{
"ok": true,
"promoted": 68,
"skipped": 2,
"errors": 0,
"grace_period_ends_at": "2026-07-28T00:00:00Z",
"rows": [
{ "user_id": 12, "email": "alice@example.com", "status": "promoted" },
{ "user_id": 15, "email": "bob@example.com", "status": "skipped" }
]
}
Get Promotion History
GET /shows/{show_id}/promote/history
Returns all subscriber rows that have ever been through a promotion run, with current grace status.
Response — array of subscriber rows:
[
{
"subscription_id": 88,
"user_id": 12,
"email": "alice@example.com",
"promoted_to_bridge": "memberpress",
"grace_period_ends_at": "2026-07-28T00:00:00Z",
"grace_status": "active"
}
]
grace_status — one of active (within grace period), expired (token revoked), cleared (manually cleared by admin).
Clear a Grace Period
POST /shows/{show_id}/promote/history/{subscription_id}/clear-grace
Removes the grace period marker and re-enables the subscriber’s feed token. Used by the Promotion History panel’s “Clear grace” action.
Response: 200 OK with { "ok": true } when a row was found and cleared, or { "ok": false } when no subscription has that id. Both are 200 — read ok, not the status code.
{ "ok": false } here means nothing was changed — a client that treats this endpoint as always succeeding will be wrong about a mistyped id.
Extend a Grace Period
POST /shows/{show_id}/promote/history/{subscription_id}/extend-grace
Request body:
{ "days": 14 }
days must be a positive integer; a zero or negative value is rejected with 400. Omitting it entirely applies a default of 7.
Adds days to the subscriber’s existing grace period end date. If that date is already in the past, the extension is measured from it, not from now — extending an expired row by 3 days when it lapsed a week ago leaves it still in the past. Extend by enough to clear the elapsed time, or clear the grace period instead.
Response: 200 OK with { "ok": true }, or { "ok": false } when the subscription has no grace period set or no row has that id.
The response carries no other fields. In particular there is no grace_period_ends_at — read the new date back from the Promotion History listing rather than from this response.
See Also
Need this built rather than just documented? See our services →