Skip to main content

Promote to Bridge REST API

Required add-on: Core

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 →