Skip to main content
Two events report how a fan stands relative to a creator: whether the creator has muted them, and whether they’re online. They carry the same fan_status resource and are discriminated by change_type, but ride separate topics so you can subscribe to one without the other. Neither has a legacy flat equivalent. Both require the read:chat scope, and presence events are sent only for creators who have presence enabled. Each event arrives in the envelope, and the tables below describe data.

Fan status resource

Fan object

handle and display_name are omitted from the payload rather than sent as null, so treat an absent key as “not resolved”. The message and payment events use the same convention. Both are public profile fields, and no email is carried on any creator.* event. The identity lookup is best-effort and runs after the delivery decision. A lookup failure omits handle and display_name rather than delaying or dropping the event, so don’t treat their absence as a change to the fan’s profile.

Examples

creator.fan.status_changed (mute)

creator.fan.presence_changed (online)

creator.fan.presence_changed (offline)

Identical apart from state. changed_at is when the platform stopped considering the fan online, not the moment they closed the app.

Delivery

Both topics use the same delivery rule. Each event reaches:
  • apps holding read:chat for the creator, and
  • the creator’s connector destination, when one is subscribed.
Delivery is filtered per topic, so taking read:chat doesn’t opt you into presence; subscribe to creator.fan.presence_changed explicitly. Presence is much higher volume than mute, with one event per fan per online/offline transition for every creator that fan is a contact of. Mute changes, by contrast, fire for every creator on every mute or unmute action.

When presence fires

  • online fires when the fan’s first socket connects. Repeated connections while already online don’t re-fire.
  • offline fires when the fan’s presence record lapses. There is no disconnect signal to key off, so offline is reported when the platform stops considering the fan online, which is later than the moment they actually left.
A fan who has turned off their online status in their own privacy settings produces neither transition, so an absence of presence events is not evidence a fan is offline.

Treat presence as a hint, not a ledger

Presence describes state that is true only for a moment, and webhook delivery retries. A redelivered online can arrive after the offline that superseded it. Build for that rather than assuming ordered, exactly-once delivery:
  • Compare changed_at against the state you already hold and discard anything older. Don’t apply an event just because it arrived.
  • Reconcile from GET /creators/{creatorUserUuid}/subscribers/online on reconnect, and periodically if presence drives anything a user sees. That endpoint is the source of truth, and the event tells you when to look.
  • Expect offline to be missed more often than online. Don’t build a session timer that depends on receiving both halves.