Event Handling

The state layer provides a way to be notified about state updates easily. However, it's also possible to watch for WebSocket events directly, should you need it.

Available Event Types

Below is a comprehensive table of all available event types and their descriptions:

Event NameDescriptionWhere is it published?
Activity Events
feeds.activity.addedFired when a new activity is added to a feedclient, feed, activity
feeds.activity.updatedFired when an activity is modifiedclient, feed, activity
feeds.activity.deletedFired when an activity is removedclient, feed, activity
feeds.activity.restoredFired when an activity is restoredclient, feed, activity
feeds.activity.removed_from_feedFired when an activity is removed from a specific feedclient, feed, activity
feeds.activity.markedFired when activities are marked as read/seenclient, feed, activity
feeds.activity.pinnedFired when an activity is pinned to the topclient, feed, activity
feeds.activity.unpinnedFired when an activity is unpinnedclient, feed, activity
feeds.activity.feedbackFired when a user provides an activity feedback (for example "show more")client
Notification Events
feeds.notification_feed.updatedFired when a feed with notification configuration has new notifications, or a notification is marked as read/seenclient, feed
Comment Events
feeds.comment.addedFired when a new comment is added to an activityclient, feed , activity
feeds.comment.updatedFired when a comment is modifiedclient, feed, activity
feeds.comment.deletedFired when a comment is removedclient, feed, activity
Reaction Events
feeds.activity.reaction.addedFired when a reaction is added to an activityclient, feed, activity
feeds.activity.reaction.deletedFired when a reaction is removed from an activityclient, feed, activity
feeds.activity.reaction.updatedFired when a reaction is updated (used if enforce_unique is true)client, feed, activity
feeds.comment.reaction.addedFired when a reaction is added to a commentclient, feed, activity
feeds.comment.reaction.deletedFired when a reaction is removed from a commentclient, feed, activity
feeds.comment.reaction.updatedFired when a reaction is updated (used if enforce_unique is true)client, feed, activity
Poll Events
feeds.poll.closedFired when a poll is closedclient
feeds.poll.deletedFired when a poll is deletedclient
feeds.poll.updatedFired when a poll is modifiedclient
feeds.poll.vote_castedFired when a vote is castclient
feeds.poll.vote_changedFired when a vote is changedclient
feeds.poll.vote_removedFired when a vote is removedclient
Feed Events
feeds.feed.createdFired when a new feed is createdclient, feed
feeds.feed.updatedFired when a feed is modifiedclient, feed
feeds.feed.deletedFired when a feed is deletedclient, feed
feeds.feed_group.changedFired when a feed group is modifiedclient, feed
feeds.feed_group.deletedFired when a feed group is deletedclient, feed
Member Events
feeds.feed_member.addedFired when a member is added to a feedclient, feed
feeds.feed_member.removedFired when a member is removed from a feedclient, feed
feeds.feed_member.updatedFired when a member's role/permissions changeclient, feed
Follow Events
feeds.follow.createdFired when a follow relationship is createdclient, feed
feeds.follow.deletedFired when a follow relationship is removedclient, feed
feeds.follow.updatedFired when follow settings are modifiedclient, feed
Bookmark Events
feeds.bookmark.addedFired when an activity is bookmarkedclient
feeds.bookmark.deletedFired when a bookmark is removedclient
feeds.bookmark.updatedFired when bookmark metadata is modifiedclient
feeds.bookmark_folder.deletedFired when bookmark folder is deletedclient
feeds.bookmark_folder.updatedFired when bookmark folder is updatedclient
Story Feed Events
feeds.stories_feed.updatedFired when a user marks a story as watchedclient, feed
Connection Events
health.checkFired when health check is receivedclient
User Events
user.updatedFired when a user is updatedclient

Feed events

Feed events are related to a specific feed. This is how you can subscribe to them:

// Watch for a specific event
const unsubscribe = feed.on("feeds.activity.added", (event) =>
  console.log(event),
);

// Watch for all events
const unsubscribe = feed.on("all", (event) => console.log(event));

To receive feed event, you need to watch the feed:

const feed = client.feed("user", "sara");
// Provide the watch flag to receive state updates via WebSocket events
await feed.getOrCreate({ watch: true });

// Query multiple feeds using a filter
const feeds = client.queryFeeds({
  filter: {
    // Your query
  },
  // Provide the watch flag to receive state updates via WebSocket events
  watch: true,
});

Activity events

When reading an activity outside of a feed, you can only watch for WebSocket events, if the feed the activity belongs to is watched:

const activityWithStateUpdates =
  client.activityWithStateUpdates(activityId);
await activityWithStateUpdates.get({
  // Optionally fetch comments too
  comments: {
    limit: 10,
    depth: 2,
  },
});

// Optionally start watching the feed
// If activity belongs to multiple feeds, it's up to you to choose which feed to watch
const fid = activityWithStateUpdates.currentState.activity!.feeds[0];
const [group, id] = fid.split(':');
const feed = client.feed(group, id);
let shouldWatch = false;
if (!feed.currentState.watch) {
  await feed.getOrCreate({
    watch: true,
    limit: 0,
    followers_pagination: { limit: 0 },
    following_pagination: { limit: 0 },
  });
}

const unsubscribe = activityWithStateUpdates.on("feeds.activity.updated", (event) =>
  console.log(event),
);

Client events

Client events contain

  • all events related to currently watched feeds
  • all poll vote events related to currently watched feeds
  • events related to a specific user (for example bookmark event)
  • events related to network connection
// Watch for a specific event
const unsubscribe = client.on("connection.changed", (event) =>
  console.log(event),
);

// Watch for all events
const unsubscribe = client.on("all", (event) =>
  console.log(`Client is ${event.online ? "online" : "offline"}`),
);

Server-side webhooks

Webhooks are configured with your API secret, so they belong on your backend rather than in the app you ship. Setting up an endpoint, verifying signatures, retries and event failover are covered under Event handling in the server-side docs, with the full transport reference in the platform webhooks guide.

Adding your own data to ext

Events delivered to your backend carry a request_info object describing the client that caused them: auth type, IP, user agent and SDK version. The ext field is the one you control. Whatever you send in the x-stream-ext header arrives on the event unchanged, so use it for context the payload does not otherwise carry, such as a device identifier or an app build number.

Set it as a custom header when you construct the client:

import { FeedsClient } from "@stream-io/feeds-react-native-sdk";

const client = new FeedsClient("<API key>", {
  custom_headers: { "x-stream-ext": "device-id=abc123" },
});

The value is passed through as-is, so the format is yours to pick: a bare value, comma-separated pairs, or JSON. Encode binary data as a string, for example with base64 or hex. Reserved headers such as Authorization and X-Stream-Client always win, so a custom header cannot overwrite them. Custom headers apply to API requests only, not to the WebSocket connection.

custom_headers requires @stream-io/feeds-client 2.7.0 or later, and the matching React and React Native SDK releases.

The payload your backend receives is documented under Request info.