Skip to main content

Listener Support Stripe Settings REST API

REST endpoints for reading and writing Stripe-mode configuration and non-Stripe donation webhook secrets. All endpoints require manage_options + a valid X-WP-Nonce header.


GET /benecaster/v1/listener-support/stripe

Returns the current Stripe-mode configuration and the saved state of the three non-Stripe webhook secrets.

Auth: manage_options + X-WP-Nonce

Response:

{
  "intended": true,
  "mode": "live",
  "public_key": "pk_live_...",
  "secret_key_set": true,
  "webhook_secret_set": true,
  "webhook_url": "https://example.com/wp-json/benecaster/v1/stripe-webhook",
  "donor_data_retention_days": 0,
  "turnstile": {
    "site_key": "0x4AAA...",
    "secret_key_set": true,
    "enabled": true,
    "half_configured": false
  },
  "donation_webhook_secrets": {
    "kofi_set": true,
    "paypal_set": false,
    "bmac_set": false
  }
}

Field reference:

Field Type Description
intended bool The operator’s declared intent to collect Stripe donations. Drives the setup reminder; it does not gate whether donations are accepted — the presence of keys does.
mode string The site default keyset mode, test or live. Discloses which keyset this panel is about to edit; it is not a toggle, and it is not any show’s mode.
public_key string The Stripe publishable key (safe to expose). Empty string when not configured.
secret_key_set bool Whether a Stripe secret key is saved. The key itself is never returned.
webhook_secret_set bool Whether a Stripe webhook signing secret is saved. Never returned in plaintext.
webhook_url string The URL to paste into Stripe’s webhook dashboard. Read-only.
donor_data_retention_days int Donation retention window in days. 0 retains indefinitely.
turnstile object Cloudflare Turnstile state — see below.
donation_webhook_secrets object Saved state for the three non-Stripe platform secrets — kofi_set, paypal_set, bmac_set (each a bool). The secrets themselves are never returned.

The turnstile object:

Field Type Description
site_key string The saved public site key, echoed as stored.
secret_key_set bool Whether a secret is saved. Never returned in plaintext.
enabled bool True only when both keys are present.
half_configured bool True when exactly one key is present.

enabled requires both keys, and half_configured exists so an admin screen can say why protection is off. With one key saved, enabled is false, half_configured is true, and donations continue to work normally — a half-filled optional setting must not refuse every donation on the site. Once both keys are present, verification does fail closed.

site_key here is not the same value the public config route returns. This admin route echoes the stored key whatever the configuration state, so the settings screen can show what was pasted. The public GET /shows/{id}/listener-support/config returns an empty string unless Turnstile is fully enabled, so a donation form never renders a challenge widget whose verification would refuse everyone.


POST /benecaster/v1/listener-support/stripe

Saves Stripe-mode configuration and/or non-Stripe webhook secrets. All fields are optional — omitted fields are left unchanged.

Auth: manage_options + X-WP-Nonce

Request body:

{
  "intended": true,
  "public_key": "pk_live_...",
  "secret_key": "sk_live_...",
  "webhook_secret": "whsec_...",
  "donor_data_retention_days": 0,
  "turnstile_site_key": "0x4AAA...",
  "turnstile_secret_key": "0x4AAA...",
  "kofi_webhook_secret": "my-kofi-token",
  "paypal_webhook_secret": "WEBHOOK-ID-FROM-PAYPAL-DASHBOARD",
  "bmac_webhook_secret": "my-bmac-secret"
}

Field reference:

Field Type Behavior
intended bool The operator’s declared intent to collect Stripe donations.
public_key string Stored as-is (not encrypted — safe to expose).
secret_key string Encrypted at rest via libsodium. Omit to keep current; send empty string to clear.
webhook_secret string Encrypted at rest. Written on its own, independently of the key pair. Omit to keep current; send empty string to clear.
donor_data_retention_days int Donation retention window in days. Negative values are clamped to 0.
turnstile_site_key string Cloudflare Turnstile site key. Stored as-is.
turnstile_secret_key string Cloudflare Turnstile secret. Encrypted at rest, same layer as the Stripe secret. Omit to keep current; send empty string to clear.
kofi_webhook_secret string Ko-fi verification token. Encrypted at rest. Omit to keep current; send whitespace-only to clear.
paypal_webhook_secret string PayPal Webhook ID. Encrypted at rest. Omit to keep current; send whitespace-only to clear.
bmac_webhook_secret string Buy Me a Coffee webhook secret. Encrypted at rest. Omit to keep current; send whitespace-only to clear.

The key pair is written into the site default mode’s keyset, so this route can never write into a show’s override. A save here can return benecaster_stripe_key_prefix_mismatch rather than 200 — most often on an install holding a live secret key in the retired mode-less slot while the site is in test mode, where the key cannot be promoted into the test keyset and the save says so rather than blanking it.

Omit-to-preserve, whitespace-to-clear semantics: For all secret fields, omitting the key from the request body leaves the stored credential unchanged. Sending an empty string or a whitespace-only string clears it. This lets the admin UI load without pre-filling password fields and still preserve secrets the user hasn’t intentionally changed.

Response: The saved state in the same shape as GET /stripe (no plaintext secrets).

Example — save only Ko-fi token, leaving everything else untouched:

{
  "kofi_webhook_secret": "MY-KOFI-VERIFICATION-TOKEN"
}

Example — clear the PayPal webhook ID:

{
  "paypal_webhook_secret": ""
}

GET /benecaster/v1/listener-support/amounts

Returns the donation amount configuration — currency, suggested amounts, whether a supporter may type their own figure, and the floor a typed figure must clear.

This is a separate concern from the routes above, which own Stripe credentials. Three controllers share the one admin tab: credentials, amounts, and link-mode prompt copy.

Auth: manage_options + X-WP-Nonce

Query parameters:

Parameter Type Description
show_id int Optional. When present and positive, the response also carries a show block for that show.

Response:

{
  "site": {
    "currency": "USD",
    "suggested_amounts": [500, 1000, 2500],
    "allow_custom_amount": true,
    "minimum_custom_amount": 100
  },
  "defaults": {
    "currency": "USD",
    "suggested_amounts": [500, 1000, 2500],
    "allow_custom_amount": true,
    "minimum_custom_amount": 100
  },
  "show": {
    "show_id": 12,
    "override_enabled": true,
    "overrides": { "suggested_amounts": [300, 700] },
    "effective": {
      "currency": "USD",
      "suggested_amounts": [300, 700],
      "allow_custom_amount": true,
      "minimum_custom_amount": 100
    }
  }
}
Field Description
site The saved site-wide values.
defaults The shipped defaults, so a screen can offer a reset and show what “unset” means.
show.override_enabled Whether this show uses its own values instead of the site’s.
show.overrides Only the keys this show actually overrides — not a full merged set.
show.effective What the donation form actually enforces for this show.

All amounts are integers in the smallest currency unit — 500 is $5.00 in USD and ¥500 in JPY.

effective is not site merged with overrides. It is post-filter: it runs benecaster_donation_suggested_amounts and benecaster_donation_minimum_amount. On an install using either filter it disagrees with both site and overrides, and that is the point — a screen showing only saved values would tell the podcaster something the donation form does not do. Read effective to answer “what will a supporter see”, and site / overrides to answer “what is saved”.


POST /benecaster/v1/listener-support/amounts

Saves the site-wide amount configuration.

Auth: manage_options + X-WP-Nonce

Request body — any of currency, suggested_amounts, allow_custom_amount, minimum_custom_amount. Values are validated and clamped on save, so the response is the authoritative record of what was stored.

{
  "currency": "GBP",
  "suggested_amounts": [300, 500, 1000],
  "allow_custom_amount": true,
  "minimum_custom_amount": 200
}

Response: 200 — { "site": { … }, "defaults": { … } }, carrying the saved values as stored rather than as submitted.


POST /benecaster/v1/listener-support/amounts/show/{id}

Saves per-show overrides.

Auth: manage_options + X-WP-Nonce

Request body:

Field Type Behavior
override_enabled bool Whether this show uses its own values.
overrides object Same keys as the site configuration.

With override_enabled set to false the stored overrides are retained but ignored, so a show can be switched back to site defaults and back again without retyping them.

Response: 200 — { "show": { … } }, the same show block GET returns, effective included.

Errors: benecaster_invalid_show (400) when the ID is not a positive integer.

See Also

Need this built rather than just documented? See our services →