Skip to main content
Two events report how a fan stands relative to a creator. 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 are delivered in the Standard-Webhooks envelope; the fields below describe the data object.

Delivery

Both topics use the same delivery model. 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 does not opt you into presence, subscribe to creator.fan.presence_changed explicitly. Presence is much higher volume than mute: one event per fan per online/offline transition, for every creator that fan is a contact of.
Presence is rolling out per creator, so a creator who has not been enabled produces no presence events yet. Mute changes fire on every mute/unmute action with no such gate.

When presence fires

  • online, the fan’s first socket connects. Repeated connections while already online do not re-fire.
  • offline, 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 “show online status” in their own privacy settings produces neither transition. 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. Do not apply an event just because it arrived.
  • Reconcile from GET /creators//subscribers/online on reconnect, and periodically if presence drives anything a user sees. That endpoint is the source of truth; the event tells you when to look.
  • Expect offline to be missed more often than online. Do not build a session timer that depends on receiving both halves.

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 same convention the message and payment events use. Both are public profile fields; 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 do not treat their absence as a change to the fan’s profile.

Example: creator.fan.status_changed (mute)

Example: creator.fan.presence_changed (online)

Example: 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.