Listener Support Donations REST API
REST endpoints for recording and retrieving listener donation references. These endpoints are part of the benecaster/v1 namespace and live on the main yoursite.com WordPress installation — not on updates.benecaster.com.
POST /benecaster/v1/listener-support/donations
Records a donation reference after a listener has donated on an external platform (Ko-fi, PayPal, Buy Me a Coffee, etc.).
Auth: Public — no nonce required. This is intentional: external platforms (Ko-fi, PayPal, Buy Me a Coffee) send webhook-style callbacks without WordPress credentials, so requiring authentication would block them. Cookie authentication is optional: when a logged-in user submits, their user_id is stored with the row; anonymous submissions store user_id = NULL.
Security note: Because this endpoint is public, anyone who knows a valid show_id can submit a fabricated donation reference. This does not represent financial risk — no money changes hands through this endpoint — but it could result in fake records in your donation log and unwanted thank-you emails sent to submitted addresses. Benecaster rate-limits this endpoint per IP. If you do not use the webhook integration (for example, you record donations manually or via the admin), contact support to discuss restricting this endpoint on your installation. For verified, fraud-resistant donations, use Stripe mode instead — Stripe payments are server-verified and cannot be fabricated.
Request body:
{
"show_id": 1,
"platform": "ko-fi",
"donor_email": "listener@example.com",
"amount": 12.50,
"currency": "USD",
"reference": "TX-123ABC",
"note": "Love the show, keep it going!",
"donated_at": "2026-06-13T14:30:00Z"
}
Field reference:
| Field | Required | Type | Notes |
|---|---|---|---|
show_id |
Yes | int |
Must reference a published benecaster_show post. |
platform |
Yes | string |
Platform slug, e.g. 'ko-fi', 'paypal', 'buymeacoffee'. No validation against a fixed list — any non-empty string is accepted. |
donor_email |
No | string |
Sanitized via sanitize_email + is_email. Stored null when absent or invalid. |
amount |
No | number |
Non-negative. Stored null when absent. |
currency |
No | string |
ISO 4217 code; uppercased before storage (e.g. "usd" → "USD"). |
reference |
No | string |
Platform transaction ID or order number; max 255 characters. |
note |
No | string |
Supporter-supplied message. |
donated_at |
No | string |
ISO 8601 datetime. Defaults to current_time('mysql') when absent or unparseable. |
Success response — HTTP 201:
{
"id": 42,
"show_id": 1,
"user_id": 17,
"platform": "ko-fi",
"donated_at": "2026-06-13T14:30:00Z",
"row": { }
}
user_id is null for anonymous submissions. row contains the full inserted row from benecaster_listener_support_donations.
After the row is written, the benecaster_listener_support_donation_logged action fires synchronously. If the submitted donor_email is a valid address, a donation_thank_you email is queued for that address.
Error responses:
| HTTP | Code | Condition |
|---|---|---|
400 |
— | show_id or platform is missing from the request body. |
403 |
signature_invalid |
A webhook secret is configured for this platform and the incoming signature or token failed verification. Body: { "code": "signature_invalid", "message": "Webhook signature verification failed." } |
404 |
— | show_id does not match a published benecaster_show post. |
500 |
— | Database insert failure. |
GET /benecaster/v1/listener-support/donations
Returns a paginated list of logged donation references.
Auth: manage_options + X-WP-Nonce
Query parameters:
| Parameter | Default | Notes |
|---|---|---|
show_id |
(none) | Filter to a single show. Omit for the site-wide list. |
page |
1 |
Page number. |
per_page |
20 |
Results per page. Clamped to a maximum of 100. |
Response:
{
"items": [
{
"id": 42,
"show_id": 1,
"user_id": 17,
"platform": "ko-fi",
"amount": 12.50,
"currency": "USD",
"reference": "TX-123ABC",
"note": "Love the show, keep it going!",
"donated_at": "2026-06-13T14:30:00Z"
}
],
"total": 156,
"page": 1,
"per_page": 20
}
Rows are ordered by donated_at DESC, id DESC. user_id is null for anonymous submissions. amount, currency, reference, and note are null when not provided at submission time.
Use cases:
- Building a donor board or “thank-you wall” on your site — pull the list server-side and render it in a template.
- Syncing donation references to a CRM or analytics platform — poll this endpoint periodically or use the
benecaster_listener_support_donation_loggedaction for real-time sync. - Displaying a running donation total — aggregate
amountvalues on the client or in a server-side cron.
Webhook Signature Verification
When a webhook secret is configured for a platform via DonationWebhookSecrets (see Settings → Listener Support), this endpoint verifies the incoming request’s signature or token before writing the donation row.
Per-platform verification mechanism:
| Platform | Header inspected | Verification method |
|---|---|---|
| Ko-fi | X-KoFi-Token |
Constant-time string compare against stored token |
| PayPal | PAYPAL-TRANSMISSION-SIG |
base64(HMAC-SHA256(request_body, webhook_id)) compare |
| Buy Me a Coffee | X-BMAC-Token |
Constant-time string compare against stored secret |
Behavior when a secret is configured:
- Verification passes → donation row written;
benecaster_donation_webhook_verifiedfires - Verification fails → HTTP 403
signature_invalidreturned; row not written;benecaster_donation_webhook_rejectedfires; debug log line written
Behavior when no secret is configured for a platform: Requests are accepted as before — no verification runs, no action fires. Verification is strictly opt-in.
Platform slug normalization: The platform field is normalized before the secret lookup — Ko-Fi, ko_fi, kofi, and KoFi all resolve to the canonical kofi slug. The raw value is preserved in the logged row.
Stripe bypass: Requests with platform=stripe are rejected at this endpoint (Stripe payments process through /stripe-webhook). No verification runs for them here.
See Webhook Signature Verification → for the setup walkthrough and full behavior reference.
Donation Verification
This endpoint records donation references — it does not verify that a payment actually occurred on the external platform. Platforms like Ko-fi and PayPal do not offer a public API to verify individual transactions, and many podcasters use platforms with no API at all.
If you need verified donations (amount confirmed, fraud-resistant), use Stripe mode instead. Stripe mode processes payments directly and records verified transactions automatically.