Account REST API (Subscriber-Facing)
These are the endpoints called by the [benecaster_account] shortcode on the subscriber-facing account page. They use cookie authentication and verify the current user owns the resource — they do not use X-WP-Nonce or require manage_options. Each endpoint checks that the currently logged-in user is requesting their own data, so responses are always scoped to the caller’s own account.
Who this is for. Cookie authentication means these endpoints answer to a logged-in subscriber’s own browser session, so they are called from front-end JavaScript, not from server-side code. That is exactly what you want when you are replacing the account panel with your own interface — a custom theme template, a React or Vue account page, or a block that surfaces one piece of account data on its own. Your script runs in the subscriber’s session and gets their data back.
What you cannot do is call them server to server, or on behalf of another user. There is no application-password or token path here, and no endpoint will return a different subscriber’s data however it is called. For back-end work — provisioning, reporting, reacting to lifecycle events — use the hooks and public functions instead.
GET /benecaster/v1/account/subscriptions
Returns all active Benecaster subscriptions for the currently logged-in user — one entry per show the user holds an active token for.
Auth: Cookie (logged-in subscriber). No manage_options required.
Response:
{
"items": [
{
"show_id": 45,
"show_title": "My Podcast",
"show_artwork": "https://example.com/artwork.jpg",
"tier_name": "Premium",
"feed_url": "https://yoursite.com/podcast-feed/?token=abc...",
"status": "active",
"token_prefix": "abc12345"
}
]
}
Response fields:
| Field | Description |
|---|---|
show_id |
Show database ID |
show_title |
Show display name |
show_artwork |
Show artwork URL; null if no artwork set |
tier_name |
The display name of the subscriber’s current plan, from whichever tier list the show uses (built-in membership or a membership plugin). Falls back to the tier slug only when neither knows it |
feed_url |
Subscriber’s full private RSS feed URL |
status |
active (only active tokens returned) |
token_prefix |
First 8 characters of the token — displayed in the account UI for identification; the full token is in feed_url |
Errors:
| Code | HTTP | Condition |
|---|---|---|
rest_forbidden |
401 | User not logged in |
The [benecaster_account] shortcode calls this endpoint on render to populate the subscription list. The response is not cached — each page load reflects the current token state.
Rate limit: 300 requests per 5 minutes per IP (catch-all standard bucket — no bespoke bucket for this endpoint). Shared across all IPs on the same network (household NAT, coworking spaces). Returns 429 Too Many Requests with Retry-After header when exceeded. Operators can tighten this via the benecaster_rest_rate_limit_buckets filter.
POST /benecaster/v1/account/reset-token
Subscriber resets their own feed token for a specific show. Generates a new token and immediately invalidates the old one. The subscriber’s podcast app will receive the new URL on its next feed poll — the app doesn’t need to be manually updated unless the subscriber uses a direct feed subscription (not a token-aware app link).
Auth: Cookie (logged-in subscriber).
Body:
{
"show_id": 45
}
Response:
{
"feed_url": "https://yoursite.com/podcast-feed/?token=xyz...",
"token_prefix": "xyz98765",
"app_links": {
"apple_podcasts": "podcast://yoursite.com/podcast-feed/?token=xyz...",
"overcast": "overcast://x-callback-url/add?url=...",
"pocket_casts": "pktc://subscribe/yoursite.com/...",
"castro": "castro://subscribe/yoursite.com/..."
}
}
Response fields:
| Field | Description |
|---|---|
feed_url |
Complete new feed URL including the full token |
token_prefix |
First 8 characters of the new token |
app_links |
Deep links for major podcast apps, pre-loaded with the new feed URL |
Notes:
- This endpoint returns the full token in
feed_url. The admin endpoint (POST /subscribers/{id}/reset-token) truncates to a prefix — this endpoint does not, because the subscriber needs the complete URL. - Auth check: the endpoint only resets the token for the currently logged-in user — it is not possible to reset another subscriber’s token via this endpoint.
- A
404is returned when the user has no active token for the given show.
Errors:
| Code | HTTP | Condition |
|---|---|---|
invalid_param |
400 | show_id missing or not an integer |
rest_forbidden |
401 | User not logged in |
rest_not_found |
404 | User has no active token for show_id |
Rate limit: 5 requests per hour per user. Returns 429 Too Many Requests with Retry-After header when exceeded.
GET /benecaster/v1/account/qr-code
Returns QR code image data for the subscriber’s feed URL for a specific show.
Auth: Cookie (logged-in subscriber).
Parameters:
| Param | Type | Default | Description |
|---|---|---|---|
show_id |
int | — | Required |
format |
string | svg |
svg or png |
size |
int | 200 | Display size in pixels (does not affect download resolution) |
Response: Binary image data with Content-Type: image/svg+xml or Content-Type: image/png.
For SVG: print-ready at 50 mm × 50 mm regardless of size parameter. For PNG: 1000 × 1000 pixels regardless of size parameter.
The size parameter controls the width and height attributes on the <img> element when the [benecaster_qr_code] shortcode renders the image in the page — it is a display hint only.
Errors:
| Code | HTTP | Condition |
|---|---|---|
invalid_param |
400 | show_id missing; format not svg or png; size not a positive integer |
rest_forbidden |
401 | User not logged in |
rest_not_found |
404 | User has no active token for show_id |
Rate limit: 30 requests per 5 minutes. Returns 429 Too Many Requests with Retry-After header when exceeded.
GET /benecaster/v1/account/cadence-switch
Despite its name, this route also covers moving to another tier. A billing-period switch and a plan move share one mechanism and one pending slot, so there is no separate /account/tier-switch route: tier_options below lists the tiers, and POST accepts a price from either list.
Returns the subscriber’s current billing period, what it can switch to and at what price, why switching is blocked if it is, and any pending switch — for a Built-in Membership subscription. Bridge (external membership plugin) subscribers get 404; their membership plugin owns their billing.
Auth: Cookie (logged-in subscriber).
Parameters:
| Param | Type | Required | Description |
|---|---|---|---|
show_id |
int | Yes | Query parameter |
Response — 200 OK:
{
"current": {
"price_id": 12,
"label": "Monthly",
"amount_cents": 900,
"amount_formatted": "USD 9.00",
"currency": "USD",
"tier_slug": "gold",
"tier_name": "Gold"
},
"options": [
{
"price_id": 14,
"label": "Annual",
"interval_unit": "year",
"interval_count": 1,
"currency": "USD",
"amount_cents": 9000,
"amount_formatted": "USD 90.00",
"starts_at": "2027-03-01 00:00:00",
"starts_date": "1 March 2027",
"charged_today": 0,
"buyups": [
{ "buyup_id": 3, "amount_cents": 1200 }
],
"buyups_dropped": [],
"buyups_included": [
{ "buyup_id": 7, "name": "Transcripts" }
],
"buyups_amount_cents": 1200,
"total_amount_cents": 10200,
"total_formatted": "USD 102.00",
"later_change": null,
"available": true,
"unavailable_reason": null
}
],
"tier_options": [
{
"price_id": 21,
"label": "Monthly",
"tier_slug": "platinum",
"tier_name": "Platinum",
"direction": "up",
"amount_cents": 1500,
"amount_formatted": "USD 15.00",
"starts_date": "1 February 2027",
"charged_today": null,
"lands": "now",
"buyups_ending": [],
"…": "the same fields as options[]"
}
],
"blocked": null,
"pending": null,
"free_option": {
"tier_slug": "free",
"tier_name": "Free",
"switch_at": "2027-03-01 00:00:00",
"switch_date": "1 March 2027"
},
"pending_free": null,
"upgrade_url": ""
}
| Field | Meaning |
|---|---|
current |
The subscriber’s active price row, or null when it could not be resolved |
options |
Other billing periods of the same tier the subscriber could switch to. Empty when blocked is set |
options[].starts_at / starts_date |
When the switch would land — the subscriber’s current renewal — as a UTC timestamp and a formatted date |
options[].amount_cents / amount_formatted |
The tier price on that billing period, alone — not including buy-ups |
options[].buyups |
The buy-ups the subscriber holds that move with them, each { buyup_id, amount_cents } at that buy-up’s price for the target period. A buy-up they hold free today that the target period sells for money is here too, at its paid price |
options[].buyups_amount_cents |
The sum of buyups[].amount_cents — what the buy-ups will cost per period from the switch date |
options[].total_amount_cents / total_formatted |
Tier price plus buy-ups: what the subscriber will actually pay per period from the switch date |
options[].buyups_included |
Buy-ups free on the target period that the subscriber will be given when the switch lands, each { buyup_id, name }. A buy-up whose subscriber cap is already full is not listed |
options[].buyups_dropped |
Buy-ups the subscriber holds free today that the target period doesn’t sell at all, each { buyup_id, name }. They end when the switch lands, at no cost |
options[].charged_today |
Always 0 — nothing is ever charged by scheduling a switch |
options[].later_change |
Set when the podcaster has already scheduled a price change on that billing period taking effect after the switch would land — carries new_amount_cents, new_amount_formatted, effective_at, effective_date. null otherwise |
options[].available / unavailable_reason |
false when the subscriber pays for a buy-up that the target period doesn’t sell. There is nothing to move it onto, and the plugin won’t drop something they pay for. unavailable_reason carries the translated message, naming the buy-ups: “You pay for Transcripts, which is not sold on this billing period. Remove it first, or stay on your current period.” If a name can’t be resolved, the message gives a count instead (“You hold 2 extras that…”). A free buy-up in the same position doesn’t block; it appears in buyups_dropped instead |
blocked |
{ code, message } when no switch can be scheduled right now (see the cadence_switch_* codes below), null otherwise |
tier_options |
Other tiers the subscriber could move to, in the same shape as options plus tier_slug, tier_name, direction (up, down or same) and lands. A tier is listed only when it sells the subscriber’s current billing period in the same currency. The show’s free tier is never listed here, because it has no price to post; it has its own field, free_option. Empty when blocked is set |
tier_options[].lands |
now for an upgrade — a tier priced higher, at the subscriber’s billing period, than their current price — and renewal for every other move. A label for the list, not the quote. It is worked out from Benecaster’s price rows so the page doesn’t call Stripe on every load. Before asking the subscriber to agree, call POST /account/cadence-switch/preview, which reads Stripe and is what decides |
tier_options[].charged_today / starts_date |
For a lands: now option, charged_today is null — the amount isn’t known until the preview, and a 0 would be untrue — and starts_date is today |
tier_options[].buyups_ending |
Paid buy-ups the subscriber holds that the target tier doesn’t offer (its Available to tiers leaves it out), each { buyup_id, name }. They don’t block the move: each ends at the end of the current billing period, with no refund, exactly as if the subscriber had removed it. Name them before the subscriber confirms. Tier moves only — a billing-period switch still blocks on a paid buy-up the new period doesn’t sell |
current.tier_slug / current.tier_name |
The tier the subscriber is on now |
pending |
The subscriber’s already-scheduled change onto a price — price_id, label, switch_at, switch_date, plus is_tier_change (true for a plan move; a missing value means a billing-period switch), tier_slug and awaiting_payment — or null |
pending.awaiting_payment |
true for an upgrade whose payment the bank hasn’t confirmed yet (the subscriber left a 3D Secure check unfinished). Nothing has moved and nothing is scheduled for a date: it lands the moment the payment clears, or is withdrawn with /cancel. switch_at is then only when Stripe stops waiting |
free_option |
The show’s free tier and when a move onto it would land — tier_slug, tier_name, switch_at, switch_date — or null when the show has no free tier or blocked is set. Schedule it with POST /account/cadence-switch/free |
pending_free |
An already-scheduled move onto the free tier, in the same shape as free_option, or null. It is present whatever blocked says (which is then pending). A subscriber has at most one of pending and pending_free |
upgrade_url |
For a subscription with no Stripe billing behind it (a member on the free tier), the page where they can take out a paid plan — the show’s page by default, filterable with benecaster_signup_url. An empty string for anyone paying |
Errors:
| Code | HTTP | Condition |
|---|---|---|
rest_forbidden |
401 | User not logged in |
rest_invalid_param |
400 | show_id missing or zero |
rest_not_found |
404 | No active Built-in Membership subscription for this show — including bridge (Phase 1) subscribers |
POST /benecaster/v1/account/cadence-switch
Moves the subscriber to another billing period of their current tier, or to another tier.
- A tier upgrade is charged and lands now. The subscriber pays the difference for the rest of the current billing period, prorated, and moves tier as soon as the payment succeeds. Call
/previewfirst and send its figures back — see Upgrades below. - Everything else lands at the next renewal, with nothing charged — a billing-period switch, a move down, or a move to a tier at the same price. The new price is billed starting at the renewal it replaces.
Auth: Cookie (logged-in subscriber).
Body:
{
"show_id": 45,
"price_id": 14,
"confirm_amount_cents": 9000,
"confirm_new_amount_cents": null,
"confirm_buyups_amount_cents": 1200,
"declined_buyups": [7]
}
| Field | Type | Required | Meaning |
|---|---|---|---|
show_id |
int | Yes | |
price_id |
int | Yes | The target price row’s id, from GET /account/cadence-switch’s options[].price_id or tier_options[].price_id. A price on another tier schedules a plan move |
confirm_amount_cents |
int | Yes | The tier price the subscriber saw and is agreeing to pay from the switch date, in minor units — options[].amount_cents, not the total |
confirm_new_amount_cents |
int | Only when options[].later_change was shown |
The later price the subscriber is agreeing to, when the target billing period has a price change taking effect after the switch |
confirm_buyups_amount_cents |
int | When options[].buyups_amount_cents is more than 0 |
The buy-up total the subscriber is agreeing to pay from the switch date. Ignored otherwise |
declined_buyups |
int[] | No | IDs of free buy-ups from options[].buyups_included that the subscriber unticked. Each is recorded as declined and not given when the switch lands. An ID the switch isn’t offering is ignored and not recorded |
confirm_prorated_cents |
int | Upgrades, except during a trial | The amount charged today, from /preview’s prorated_cents. Ignored for every other move |
proration_date |
int | Upgrades, except during a trial | /preview’s proration_date, sent back unchanged so the invoice charges exactly the amount quoted. A date in the future, or one more than a short while old, is refused with fresh figures |
GET /account/cadence-switch lists every free buy-up the target period includes, even one the subscriber declined before. Choosing a period is a new decision, so the list is what the period offers, not what the subscriber hasn’t refused.
Response — 200 OK: the same shape as GET /account/cadence-switch, refreshed — pending is now set.
Upgrades
For an upgrade, confirm_amount_cents (and confirm_buyups_amount_cents, if sent) is the recurring price from the renewal, and confirm_prorated_cents is what is charged today. During a free trial nothing is charged today, so the two upgrade fields are not needed.
The answer is the refreshed GET shape plus one of:
| Answer | Meaning |
|---|---|
upgraded: true |
The payment went through and the subscriber is on the new tier now |
upgraded: false, requires_action: true, client_secret, stripe_publishable_key |
The bank wants to verify the payment (3D Secure). Nothing has moved. Run Stripe.js handleNextAction( { clientSecret } ) with that publishable key, then call /confirm. pending.awaiting_payment is true until it clears |
402 payment_declined |
The card was declined. Nothing moved and the invoice is voided, so nothing is collected later. The message is the card issuer’s reason when Stripe gives one |
An upgrade that also asks for a different billing period is split: the tier moves today at the current period, and the new period is scheduled for the renewal. The same combination on a move down is refused — change the plan and the billing period one at a time.
An upgrade doesn’t send the Plan Change Scheduled email and doesn’t fire benecaster_subscription_tier_switch_scheduled — nothing is scheduled. It fires benecaster_subscription_tier_changed when the payment succeeds, and the Tier Change email goes out then.
confirm_amount_cents, confirm_new_amount_cents and confirm_buyups_amount_cents — the consent fields
Never a blind POST, the same pattern as buy-up purchase: the caller states the price (and, when relevant, the later price) the subscriber actually saw, and the server refuses if either no longer matches what it would charge — so a price edited between render and click is rejected rather than silently applied at the new amount.
confirm_amount_cents is the tier price alone, not the total. When buy-ups move with the subscriber, send the tier price in confirm_amount_cents and the buy-up total in confirm_buyups_amount_cents. Sending total_amount_cents in confirm_amount_cents is refused with 409 amount_mismatch on every call.
Free buy-ups, whether gained or lost, cost nothing and aren’t part of any consent value. Show buyups_included and buyups_dropped to the subscriber anyway, so nothing is added or taken away without being named.
A mismatch on either field returns 409 amount_mismatch carrying the live figures, so the client re-asks rather than guesses:
{
"code": "amount_mismatch",
"message": "The price of this billing period has changed. Please review the new price and try again.",
"data": {
"status": 409,
"amount_cents": 9000,
"new_amount_cents": null,
"buyups_amount_cents": 1200,
"total_amount_cents": 10200,
"currency": "USD"
}
}
Errors:
| Code | HTTP | Condition |
|---|---|---|
rest_forbidden |
401 | User not logged in |
rest_invalid_param |
400 | show_id or price_id missing or zero |
confirm_amount_invalid |
400 | A confirmation field sent but not a whole number |
confirm_amount_required |
400 | confirm_amount_cents missing, or confirm_buyups_amount_cents missing when buy-ups with a cost move with the subscriber |
rest_not_found |
404 | No active Built-in Membership subscription for this show |
cadence_unavailable |
400 | price_id is in neither options nor tier_options — not another billing period of their tier, and not a price on another tier the show sells at their billing period |
409 amount_mismatch |
409 | Confirmed amount(s) no longer match the live price. On an upgrade the error data also carries fresh prorated_cents and proration_date, so the page re-asks once |
confirm_amount_required (upgrade) |
400 | An upgrade outside a trial sent without confirm_prorated_cents |
402 payment_declined |
402 | An upgrade’s payment was declined — nothing changed |
409 cadence_switch_not_billed |
409 | The membership is not billed through Stripe |
409 cadence_switch_pending |
409 | A billing change is already scheduled — cancel it first |
409 cadence_switch_billing_problem |
409 | The subscription is not active or trialing (e.g. a payment has failed) |
409 cadence_switch_paused |
409 | Billing for the membership is paused |
409 cadence_switch_cancelling |
409 | The membership is set to end — resume it first |
409 cadence_switch_unknown_plan |
409 | The subscriber’s current tier or price could not be resolved |
409 cadence_switch_buyups |
409 | Billing-period switches only: the subscriber pays for a buy-up that the target billing period doesn’t sell — they can remove it or stay on their current period. A tier move never gets this; the buy-up ends instead (buyups_ending) |
409 benecaster_billing_unavailable |
409 | This install is a copy of another site, so the change is refused — see Buy-ups Subscriber REST API |
502 stripe_error |
502 | Stripe could not be reached |
On success the plugin sends the subscriber the Billing Change Scheduled email (see Built-in Membership Billing Emails) and fires benecaster_subscription_cadence_switch_scheduled.
POST /benecaster/v1/account/cadence-switch/preview
Quotes a tier move from Stripe — what the account page shows in its confirm step before the subscriber agrees. Changes nothing.
Auth: Cookie (logged-in subscriber).
Body: { "show_id": 45, "price_id": 21 } — a price_id from tier_options.
Response — an upgrade (200 OK):
{
"price_id": 21,
"tier_slug": "platinum",
"tier_name": "Platinum",
"currency": "USD",
"renewal_at": "2027-03-01 00:00:00",
"renewal_date": "1 March 2027",
"lands": "now",
"trialing": false,
"changes_period": false,
"prorated_cents": 412,
"prorated_formatted": "USD 4.12",
"prorated_before_tax": false,
"proration_date": 1790000000,
"amount_cents": 1500,
"amount_formatted": "USD 15.00",
"buyups_amount_cents": 0,
"total_amount_cents": 1500,
"total_formatted": "USD 15.00",
"later_change": null
}
prorated_cents is charged today (0 while trialing). On a subscription that collects tax it includes the tax; prorated_before_tax is true only when Stripe could not work the tax out for this preview, so the figure is before tax, and is always false on an untaxed subscription. Send prorated_cents back unchanged either way; amount_cents / total_amount_cents is the price from renewal_date. changes_period is true when the chosen price is on another billing period, in which case the tier moves today and the period follows at the renewal. Send prorated_cents back as confirm_prorated_cents, and proration_date unchanged.
Response — any other tier move: the same first six fields, plus lands: "renewal", amount_cents and amount_formatted. Nothing is charged today.
Errors: 400 tier_unavailable when the price isn’t a tier the subscriber can move to (or is a move down that also changes billing period), the 409 cadence_switch_* refusals of the main route, and 502 stripe_error.
POST /benecaster/v1/account/cadence-switch/confirm
Lands an upgrade once the subscriber has passed their bank’s 3D Secure check, without waiting for Stripe’s webhook. The webhook lands it anyway if this is never called.
Auth: Cookie (logged-in subscriber).
Body: { "show_id": 45 }
Response — 200 OK: the refreshed GET shape plus upgraded — true once Stripe has applied the upgrade, false if it hasn’t yet (or there was no upgrade waiting). A false isn’t a failure; the webhook finishes it.
POST /benecaster/v1/account/cadence-switch/cancel
Withdraws the subscriber’s pending change — a scheduled billing-period switch or plan move, or an upgrade still waiting on the bank (pending.awaiting_payment), whose invoice is voided so nothing is charged. No email is sent.
Auth: Cookie (logged-in subscriber).
Body:
{
"show_id": 45
}
Response — 200 OK: the same shape as GET /account/cadence-switch — pending is now null.
Errors:
| Code | HTTP | Condition |
|---|---|---|
rest_forbidden |
401 | User not logged in |
rest_invalid_param |
400 | show_id missing or zero |
rest_not_found |
404 | No active Built-in Membership subscription for this show |
409 cadence_switch_not_pending |
409 | Nothing is currently scheduled to cancel |
POST /benecaster/v1/account/cadence-switch/free
Schedules a move onto the show’s free tier, landing at the end of the period the subscriber has already paid for. Nothing is charged by this call, and nothing is charged afterwards: at Stripe’s level the subscription is set to cancel at the period end, and when it ends the subscriber becomes a member on the free tier with the same feed URL. Buy-ups they pay for end on the same date.
Auth: Cookie (logged-in subscriber).
Body:
{
"show_id": 45
}
There is no consent amount: the move takes the subscriber’s bill to nothing, so there is no figure to confirm.
Response — 200 OK: the same shape as GET /account/cadence-switch, refreshed — pending_free is now set and blocked.code is pending.
Errors:
| Code | HTTP | Condition |
|---|---|---|
rest_forbidden |
401 | User not logged in |
rest_invalid_param |
400 | show_id missing or zero |
rest_not_found |
404 | No active Built-in Membership subscription for this show |
free_tier_unavailable |
400 | The show has no free tier to move to |
409 cadence_switch_* |
409 | The same refusals as POST /account/cadence-switch: not billed through Stripe, a change already pending, a failed payment, billing paused, set to cancel, or plan unknown |
409 benecaster_billing_unavailable |
409 | This install is a copy of another site |
502 stripe_error |
502 | Stripe could not be reached |
On success the plugin sends the subscriber the Move to Free Plan Scheduled email (see Built-in Membership Billing Emails) and fires benecaster_subscription_free_switch_scheduled.
POST /benecaster/v1/account/cadence-switch/free/cancel
Withdraws a pending move onto the free tier. The subscriber’s paid plan and billing carry on as before. No email is sent.
Auth: Cookie (logged-in subscriber).
Body:
{
"show_id": 45
}
Response — 200 OK: the same shape as GET /account/cadence-switch — pending_free is now null.
Errors:
| Code | HTTP | Condition |
|---|---|---|
rest_forbidden |
401 | User not logged in |
rest_invalid_param |
400 | show_id missing or zero |
rest_not_found |
404 | No active Built-in Membership subscription for this show |
409 cadence_switch_not_pending |
409 | No move onto the free tier is scheduled |
409 benecaster_billing_unavailable |
409 | This install is a copy of another site |
502 stripe_error |
502 | Stripe could not be reached |
There is no route for the other direction. A member on the free tier has no card on file, so they take out a paid plan through the ordinary signup form at upgrade_url, and are charged straight away. | 409 benecaster_billing_unavailable | 409 | This install is a copy of another site, so the change is refused | | 502 stripe_error | 502 | Stripe could not be reached |
Fires benecaster_subscription_cadence_switch_cancelled with reason: subscriber.
POST /benecaster/v1/account/supporter-wall-visibility
Sets whether the currently logged-in subscriber appears on the Supporter Wall for their show(s). Called by the opt-in checkbox in the Profile picture / Badges block of [benecaster_account].
Auth: Cookie (logged-in subscriber).
Body:
{
"visible": true
}
Response:
{
"visible": true
}
Behavior:
- Writes
_benecaster_subscriber_wall_visibleuser meta and returns the value that was written. - Idempotent — submitting
visible: truewhen the subscriber is already opted in still succeeds and still fires thebenecaster_subscriber_wall_visibleaction (always-fires semantics; seebenecaster_subscriber_wall_visible). - Returns
401when the request is not authenticated. - The checkbox on the account page only renders when
benecaster_supporter_wall_activereturnstruefor the subscriber — i.e. at least one of their active shows has the wall enabled. The endpoint itself does not enforce this gate server-side; it accepts requests regardless.
Errors:
| Code | HTTP | Condition |
|---|---|---|
invalid_param |
400 | visible missing or not a boolean |
rest_forbidden |
401 | User not logged in |
Rate limit: 300 requests per 5 minutes per IP (catch-all standard bucket — no bespoke bucket for this endpoint). Operators can tighten this via the benecaster_rest_rate_limit_buckets filter.
Authentication Note
All /account/* endpoints reject requests that are not from a logged-in WordPress user — they return 401 rest_forbidden. This means they cannot be called from server-to-server contexts or external tools without a valid session cookie. If you need to read or modify subscriber data programmatically, use the admin subscriber endpoints (GET /shows/{id}/subscribers, POST /subscribers/{id}/reset-token, etc.) with manage_options + nonce authentication instead.
See Also
Need this built rather than just documented? See our services →