BetterFans Link SDK — OnlyFans APIBetterFans Link SDK
WebSocket

Event reference

Complete reference of all EventBus event types and their payloads.

The EventBus emits typed events as they occur across your managed accounts. Register handlers with .onEnvelope(type, handler); each handler receives a dispatch context whose accountId identifies the account the event originated from, and whose payload carries the typed event body.

Event types

EventDescription
chat_messageA new chat message was received or sent
system_messageA system-generated message (auto-replies, welcome messages)
onlineAn account's online status changed
countsUnread counts updated (chats, notifications)
typingA user started or stopped typing in a chat
chat_message_likeA chat message was liked
chat_message_unlikeA chat message was unliked
tipA tip was received
new_subscriberA new user subscribed
returning_subscriberA previously expired subscriber resubscribed
ppv_purchaseA pay-per-view message was purchased
ppv_sentA pay-per-view message was sent

Event payloads

Every event handler receives a typed payload. Here are the most common events and their key fields.

chat_message

Fired when a message is received or sent in any chat.

ws.onEnvelope("chat_message", (ctx) => {
  ctx.accountId               // string | null — which account it belongs to
  ctx.payload.api2_chat_message // the raw OF chat message (text, fromUser, media, ...)
})

tip

Fired when a tip is received on any account.

ws.onEnvelope("tip", (ctx) => {
  ctx.payload.accountId          // string — which account received it
  ctx.payload.fanId              // number — who tipped
  ctx.payload.amountCents        // number — tip amount in cents
  ctx.payload.payload.fanUsername // string — tipper's username (optional)
})

new_subscriber

Fired when someone subscribes to one of your accounts.

ws.onEnvelope("new_subscriber", (ctx) => {
  ctx.payload.accountId   // string — which account got a subscriber
  ctx.payload.fanId       // number — new subscriber's user ID
  ctx.payload.amountCents // number | null — subscription price in cents
})

returning_subscriber

Fired when a previously expired subscriber resubscribes.

ws.onEnvelope("returning_subscriber", (ctx) => {
  ctx.payload.accountId // string
  ctx.payload.fanId     // number
})

ppv_purchase

Fired when a user purchases a pay-per-view message.

ws.onEnvelope("ppv_purchase", (ctx) => {
  ctx.payload.accountId     // string
  ctx.payload.chatMessageId // number — the purchased message
  ctx.payload.fanId         // number — who purchased
  ctx.payload.amountCents   // number | null — amount in cents
})

online

Fired when an account's online status changes.

ws.onEnvelope("online", (ctx) => {
  ctx.accountId       // string | null — which account this belongs to
  ctx.payload.online  // array — online status entries
})

typing

Fired when a user starts or stops typing.

ws.onEnvelope("typing", (ctx) => {
  ctx.accountId      // string | null — which account this belongs to
  ctx.payload.typing // the raw OF typing frame
})

counts

Fired when unread counts change.

ws.onEnvelope("counts", (ctx) => {
  ctx.accountId                 // string | null — which account this belongs to
  ctx.payload.chat_messages     // number — unread chat messages
  ctx.payload.count_priority_chat // number — priority chats
  ctx.payload.unread_tips       // number — unread tips
})

TypeScript types

All event types are exported for use in your own type definitions:

import type {
  BusEventMap,
  BusEventType,
  BusChatMessageEvent,
  BusOnlineEvent,
  BusEventEnvelope,
} from "@betterfans/link-sdk"

type MyHandler = (event: BusChatMessageEvent) => void

The BusEventMap type maps event names to their payload types, so you can build generic event handling:

function handleEvent<T extends BusEventType>(
  type: T,
  handler: (event: BusEventMap[T]) => void,
) {
  ws.onEnvelope(type, (ctx) => handler(ctx.payload as BusEventMap[T]))
}

On this page