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 by collecting an events flow, should you need it.

Observing events

The FeedsClient exposes an events property to get a flow of events:

feedsClient
    .events
    .collect { event ->
        // Handle the event types you care about
        when (event) {
            is ActivityAddedEvent -> {
                println("New activity added: ${event.activity.text}")
            }
            is CommentAddedEvent -> {
                println("New comment added: ${event.comment.text}")
            }
            is FollowCreatedEvent -> {
                println("New follow created: ${event.follow.targetFeed}")
            }
            else -> {
                println("Received event: ${event::class.java.simpleName}")
            }
        }
    }

Leveraging the Flow API

With the events coming as a Flow, no special knowledge is needed to get started. You can use all the power of Kotlin's coroutines and Flow API to handle events in a way that suits your use cases.

For example, if you want to only listen for a specific event type, like new activities added, you can use the filterIsInstance operator:

feedsClient
    .events
    .filterIsInstance<ActivityAddedEvent>()
    .collect { event ->
        println("New activity added: ${event.activity.text}")
    }

Handling backpressure

If your event processing is slow, you might want to add explicit backpressure handling because the events flow will drop events if the consumer cannot keep up.

For example, you can use the buffer operator and specify your desired strategy:

feedsClient
    .events
    .buffer(capacity = 100, onBufferOverflow = BufferOverflow.DROP_OLDEST)
    .collect { event ->
        // Process the event
    }

Available Event Types

Below is a table of all available events:

Event NameDescription
Activity Events
ActivityAddedEventFired when a new activity is added to a feed.
ActivityUpdatedEventFired when an activity is modified.
ActivityDeletedEventFired when an activity is removed.
ActivityRestoredEventFired when an activity is restored.
ActivityRemovedFromFeedEventFired when an activity is removed from a specific feed.
ActivityMarkEventFired when activities are marked as read/seen.
ActivityPinnedEventFired when an activity is pinned to the top.
ActivityUnpinnedEventFired when an activity is unpinned.
Comment Events
CommentAddedEventFired when a new comment is added to an activity.
CommentUpdatedEventFired when a comment is modified.
CommentDeletedEventFired when a comment is removed.
CommentRestoredEventFired when a comment is restored.
Reaction Events
ActivityReactionAddedEventFired when a reaction is added to an activity.
ActivityReactionUpdatedEventFired when a reaction is modified on an activity.
ActivityReactionDeletedEventFired when a reaction is removed from an activity.
CommentReactionAddedEventFired when a reaction is added to a comment.
CommentReactionUpdatedEventFired when a reaction is modified on a comment.
CommentReactionDeletedEventFired when a reaction is removed from a comment.
Poll Events
PollClosedFeedEventFired when a poll is closed.
PollDeletedFeedEventFired when a poll is deleted.
PollUpdatedFeedEventFired when a poll is modified.
PollVoteCastedFeedEventFired when a vote is cast on a poll.
PollVoteChangedFeedEventFired when a vote is changed on a poll.
PollVoteRemovedFeedEventFired when a vote is removed from a poll.
Feed Events
FeedCreatedEventFired when a new feed is created.
FeedUpdatedEventFired when a feed is modified.
FeedDeletedEventFired when a feed is deleted.
FeedGroupChangedEventFired when a feed group is modified.
FeedGroupDeletedEventFired when a feed group is deleted.
FeedGroupRestoredEventFired when a feed group is restored.
NotificationFeedUpdatedEventFired when a notification feed has new content.
StoriesFeedUpdatedEventFired when a stories feed has new content.
Member Events
FeedMemberAddedEventFired when a member is added to a feed.
FeedMemberRemovedEventFired when a member is removed from a feed.
FeedMemberUpdatedEventFired when a member's role or permissions change.
Follow Events
FollowCreatedEventFired when a follow relationship is created.
FollowUpdatedEventFired when follow settings are modified.
FollowDeletedEventFired when a follow relationship is removed.
Bookmark Events
BookmarkAddedEventFired when an activity is bookmarked.
BookmarkUpdatedEventFired when bookmark metadata is modified.
BookmarkDeletedEventFired when a bookmark is removed.
BookmarkFolderUpdatedEventFired when a bookmark folder is modified.
BookmarkFolderDeletedEventFired when a bookmark folder is deleted.
User Events
UserUpdatedEventFired when a user's data is updated.
UserBannedEventFired when a user is banned from the app.
UserUnbannedEventFired when a user is unbanned.
UserDeactivatedEventFired when a user account is deactivated.
UserReactivatedEventFired when a user account is reactivated.
Moderation Events
ModerationFlaggedEventFired when content is flagged for moderation.
ModerationMarkReviewedEventFired when a moderator marks content as reviewed.
ModerationCustomActionEventFired when a custom moderation action is triggered.
Feedback Events
ActivityFeedbackEventFired when activity feedback is submitted.
System Events
AppUpdatedEventFired when there is a global app-level update.

You can configure your Stream app to receive webhook events as well as AWS SNS and AWS SQS. Webhooks are usually the simplest way to receive events from your app and to perform additional action based on what happens to your application.

The configuration can be done using the API or from the Dashboard. By default, all events are sent to your webhook/sqs/sns endpoint, you can also configure the events you want to receive in the dashboard.

import io.getstream.models.EventHook;
import io.getstream.models.UpdateAppRequest;

EventHook allEventsHook = new EventHook()
    .hookType(EventHook.HookTypeEnum.WEBHOOK)
    .enabled(true)
    .eventTypes(Collections.emptyList()) // empty list = all events
    .webhookUrl("<webhook url>");

EventHook specificEventsHook = new EventHook()
    .hookType(EventHook.HookTypeEnum.WEBHOOK)
    .enabled(true)
    .eventTypes(List.of("feeds.activity.added")) // specific events
    .webhookUrl("<webhook url>");

UpdateAppRequest request = new UpdateAppRequest()
    .eventHooks(List.of(allEventsHook, specificEventsHook));

common.updateApp(request).execute();

Some important points to consider:

  • The selection of events you want to receive applies to all the endpoints you have configured.
  • You can configure multiple endpoints for the same app (eg. AWS SNS and HTTP Webhook).
  • If your app is configured to receive all events, you can still filter the events you want to receive in your webhook handler.
  • If your app is configured to receive all events, newly introduced event types will be sent to your webhook handler by default.
  • If you pick specific events, newly introduced event types will not be sent to your webhook handler by default (you can still manually add them later on).

How to implement a webhook handler

Your webhook handler needs to follow these rules:

  • accept HTTP POST requests with JSON payload
  • be reachable from the public internet. Tunneling services like Ngrok are supported
  • respond with response codes from 200 to 299 as fast as possible

Your webhook handler can use the type field to handle events based correctly based on their type and payload.

All webhook requests contain these headers:

NameDescription
X-WEBHOOK-IDUnique ID of the webhook call. This value is consistent between retries and could be used to deduplicate retry calls
X-WEBHOOK-ATTEMPTNumber of webhook request attempt starting from 1
X-API-KEYYour application’s API key. Should be used to validate request signature
X-SIGNATUREHMAC signature of the request body. See Signature section

Best Practices

We highly recommend following common security guidelines to make your webhook integration safe and fast:

  • Use HTTPS with a certificate from a trusted authority
  • Verify the "X-Signature" header to ensure the request is coming from Stream
  • Support HTTP Keep-Alive
  • Use a highly available infrastructure such as AWS Elastic Load Balancer, Google Cloud Load Balancer, or similar
  • Offload the processing of the message if possible (read, store, and forget)
  • When decoding JSON into objects, ensure that your webhook can handle new fields being added to the JSON payload as well as new event types (eg. log unknown fields and event types instead of failing)

Error Handling

In case of the request failure Stream Chat attempts to retry a request. The amount of maximum attempts depends on the kind of the error it receives:

  • Response code is 408, 429 or >=500: 3 attempts
  • Network error: 2 attempts
  • Request timeout: 3 attempts

The timeout of one request is 6 seconds, and the request with all retries cannot exceed the duration of 15 seconds.

Available Event Types

Below is a comprehensive table of all available event types and their descriptions. WebhookEvent model definition can be found in Open API specification.

Event NameDescription
Activity Events
feeds.activity.addedFired when a new activity is added to a feed
feeds.activity.updatedFired when an activity is modified
feeds.activity.deletedFired when an activity is removed
feeds.activity.restoredFired when an activity is restored
feeds.activity.removed_from_feedFired when an activity is removed from a specific feed
feeds.activity.pinnedFired when an activity is pinned to the top
feeds.activity.unpinnedFired when an activity is unpinned
feeds.activity.feedbackFired when activity feedback is provided
feeds.activity.markedFired when an activity is marked
Notification Events
feeds.notification_feed.updatedFired when the notification status, or notification groups (aggregated activities) are updated
Comment Events
feeds.comment.addedFired when a new comment is added to an activity
feeds.comment.updatedFired when a comment is modified
feeds.comment.deletedFired when a comment is removed
Reaction Events
feeds.activity.reaction.addedFired when a reaction is added to an activity
feeds.activity.reaction.deletedFired when a reaction is removed from an activity
feeds.activity.reaction.updatedFired when a reaction on an activity is updated
feeds.comment.reaction.addedFired when a reaction is added to a comment
feeds.comment.reaction.deletedFired when a reaction is removed from a comment
feeds.comment.reaction.updatedFired when a reaction on a comment is updated
Poll Events
feeds.poll.closedFired when a poll is closed
feeds.poll.deletedFired when a poll is deleted
feeds.poll.updatedFired when a poll is modified
feeds.poll.vote_castedFired when a vote is cast
feeds.poll.vote_changedFired when a vote is changed
feeds.poll.vote_removedFired when a vote is removed
Feed Events
feeds.feed.createdFired when a new feed is created
feeds.feed.updatedFired when a feed is modified
feeds.feed.deletedFired when a feed is deleted
Feed Group Events
feeds.feed_group.changedFired when a feed group is changed
feeds.feed_group.deletedFired when a feed group is deleted
Member Events
feeds.feed_member.addedFired when a member is added to a feed
feeds.feed_member.removedFired when a member is removed from a feed
feeds.feed_member.updatedFired when a member's role/permissions change
Follow Events
feeds.follow.createdFired when a follow relationship is created
feeds.follow.deletedFired when a follow relationship is removed
feeds.follow.updatedFired when follow settings are modified
Bookmark Events
feeds.bookmark.addedFired when an activity is bookmarked
feeds.bookmark.deletedFired when a bookmark is removed
feeds.bookmark.updatedFired when bookmark metadata is modified
feeds.bookmark_folder.deletedFired when bookmark folder is deleted
feeds.bookmark_folder.updatedFired when bookmark folder is updated
Stories Events
feeds.stories_feed.updatedFired when a stories feed is updated
Moderation Events
moderation.custom_actionFired when a custom moderation action is performed
moderation.flaggedFired when content is flagged for moderation
moderation.mark_reviewedFired when content is marked as reviewed
User Events
user.bannedFired when a user is banned
user.deactivatedFired when a user is deactivated
user.mutedFired when a user is muted
user.reactivatedFired when a user is reactivated
user.updatedFired when a user is updated