Skip to content

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 Name Description Where is it published?
Activity Events
feeds.activity.added Fired when a new activity is added to a feed client, feed, activity
feeds.activity.updated Fired when an activity is modified client, feed, activity
feeds.activity.deleted Fired when an activity is removed client, feed, activity
feeds.activity.restored Fired when an activity is restored client, feed, activity
feeds.activity.removed_from_feed Fired when an activity is removed from a specific feed client, feed, activity
feeds.activity.marked Fired when activities are marked as read/seen client, feed, activity
feeds.activity.pinned Fired when an activity is pinned to the top client, feed, activity
feeds.activity.unpinned Fired when an activity is unpinned client, feed, activity
feeds.activity.feedback Fired when a user provides an activity feedback (for example "show more") client
Notification Events
feeds.notification_feed.updated Fired when a feed with notification configuration has new notifications, or a notification is marked as read/seen client, feed
Comment Events
feeds.comment.added Fired when a new comment is added to an activity client, feed , activity
feeds.comment.updated Fired when a comment is modified client, feed, activity
feeds.comment.deleted Fired when a comment is removed client, feed, activity
Reaction Events
feeds.activity.reaction.added Fired when a reaction is added to an activity client, feed, activity
feeds.activity.reaction.deleted Fired when a reaction is removed from an activity client, feed, activity
feeds.activity.reaction.updated Fired when a reaction is updated (used if enforce_unique is true) client, feed, activity
feeds.comment.reaction.added Fired when a reaction is added to a comment client, feed, activity
feeds.comment.reaction.deleted Fired when a reaction is removed from a comment client, feed, activity
feeds.comment.reaction.updated Fired when a reaction is updated (used if enforce_unique is true) client, feed, activity
Poll Events
feeds.poll.closed Fired when a poll is closed client
feeds.poll.deleted Fired when a poll is deleted client
feeds.poll.updated Fired when a poll is modified client
feeds.poll.vote_casted Fired when a vote is cast client
feeds.poll.vote_changed Fired when a vote is changed client
feeds.poll.vote_removed Fired when a vote is removed client
Feed Events
feeds.feed.created Fired when a new feed is created client, feed
feeds.feed.updated Fired when a feed is modified client, feed
feeds.feed.deleted Fired when a feed is deleted client, feed
feeds.feed_group.changed Fired when a feed group is modified client, feed
feeds.feed_group.deleted Fired when a feed group is deleted client, feed
Member Events
feeds.feed_member.added Fired when a member is added to a feed client, feed
feeds.feed_member.removed Fired when a member is removed from a feed client, feed
feeds.feed_member.updated Fired when a member's role/permissions change client, feed
Follow Events
feeds.follow.created Fired when a follow relationship is created client, feed
feeds.follow.deleted Fired when a follow relationship is removed client, feed
feeds.follow.updated Fired when follow settings are modified client, feed
Bookmark Events
feeds.bookmark.added Fired when an activity is bookmarked client
feeds.bookmark.deleted Fired when a bookmark is removed client
feeds.bookmark.updated Fired when bookmark metadata is modified client
feeds.bookmark_folder.deleted Fired when bookmark folder is deleted client
feeds.bookmark_folder.updated Fired when bookmark folder is updated client
Story Feed Events
feeds.stories_feed.updated Fired when a user marks a story as watched client, feed
Connection Events
health.check Fired when health check is received client
User Events
user.updated Fired when a user is updated client

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