Create a webhook subscription

Subscribe a public HTTPS URL to one or more platform events. Every requested event is delivered to the same URL and signed with the single signingSecret returned in the response — store it, as it is only returned at creation time. The token must hold the OAuth scope each requested event needs: read:creator for subscription.new, subscription.renewed, subscription.cancelled, subscription.expired, follow.new, purchase.new, tip.new, the checkout_link.* and payout.paid events, and the creator.payment.succeeded, creator.subscription.*, creator.refund.created, and creator.dispute.* events; read:post for creator.post.liked and creator.post.commented; read:chat for message.received, message.read, creator.message.received, creator.message.sent, creator.message.mass_sent, creator.message.read, creator.message.read_by_fan, creator.message.reaction, creator.message.deleted, and creator.chat.marked_unread; read:experience for the creator.experience_subscription.* events.

creator.experience_subscription.deactivated fires whenever a fan's paid fan-experience subscription stops granting access — they cancelled and the period ran out, a renewal failed, the charge was refunded or charged back, or we or the creator ended it. Act on access_ends_at, the moment access was revoked, which is not always expires_at (a refund, chargeback, ban or unpublish ends access mid-period). A cancellation on its own does not fire it, because access continues to period end. Treat expires_at as a deadline in its own right rather than waiting only for this event: access also lapses on the clock when a renewal is still settling or an upstream lookup fails, and nothing is sent until a later hourly sweep resolves the subscription.

Pair it with creator.experience_subscription.activated, which fires when access starts: activation_reason is subscribed on the fan's initial purchase and renewal_recovered when a renewal charge that had already failed is recovered by a later retry. Handling the recovery case is required if you act on the deactivated event, because a failed renewal revokes access before the retries that may still pay for the period are exhausted.

The two read receipts are separate directions and neither replaces the other: creator.message.read fires when the creator reads the fan's messages, creator.message.read_by_fan when the fan reads the creator's. Their topic names the actor while the object in the payload (fan_message_read / creator_message_read) names whose messages were read, so the two names run on different axes.

creator.chat.marked_unread is the other half of the inbox badge: the creator deliberately marked a conversation unread, where creator.message.read is the event that clears it. It is conversation state, not message state — no message's read status changes, so do not revert the read ticks you took from creator.message.read_by_fan. unread_messages_count is the conversation's real unread count and is unchanged by the mark, so 0 is normal: render a chat as unread when the marker arrives OR that count is above zero. The two halves are delivered independently and are not ordered against each other, so compare marked_at with the read_at on creator.message.read and apply whichever is later rather than whichever arrives last. It reports the transition into unread, so re-marking a conversation that is already unread emits nothing.

Mass messages are delivered on creator.message.mass_sent, never on creator.message.sent, so subscribe to both to see every creator-to-fan send. The event describes the send, not each copy of it: one mass_message per broadcast, carrying the broadcast's uuid, its message_type and recipient_count. There is no fan — a broadcast has no single recipient — and text is the authored body with its personalisation tokens ({{handle}}) left intact, because there is no one recipient to render it for. Substitute per fan if you need the rendered text. Which fans received a send is not carried on the event; that list is not yet exposed on the API.

post/webhooks/subscriptions

Headers

X-Fanvue-API-Versionstring required
Example:2025-06-26

API version to use for the request

Request body

urlstring uri required

Public HTTPS URL the event payloads are delivered to (no redirects, no localhost)

eventsstring[] required

One or more platform events this subscription delivers

Response

Webhook subscription created successfully

idstring uuid required

ID of the created webhook subscription

signingSecretstring required

HMAC signing secret for verifying delivery signatures. Returned only on creation — store it securely now.

Changes