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}")
}
}
}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:
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 Name | Description |
|---|---|
| Activity Events | |
ActivityAddedEvent | Fired when a new activity is added to a feed. |
ActivityUpdatedEvent | Fired when an activity is modified. |
ActivityDeletedEvent | Fired when an activity is removed. |
ActivityRestoredEvent | Fired when an activity is restored. |
ActivityRemovedFromFeedEvent | Fired when an activity is removed from a specific feed. |
ActivityMarkEvent | Fired when activities are marked as read/seen. |
ActivityPinnedEvent | Fired when an activity is pinned to the top. |
ActivityUnpinnedEvent | Fired when an activity is unpinned. |
| Comment Events | |
CommentAddedEvent | Fired when a new comment is added to an activity. |
CommentUpdatedEvent | Fired when a comment is modified. |
CommentDeletedEvent | Fired when a comment is removed. |
CommentRestoredEvent | Fired when a comment is restored. |
| Reaction Events | |
ActivityReactionAddedEvent | Fired when a reaction is added to an activity. |
ActivityReactionUpdatedEvent | Fired when a reaction is modified on an activity. |
ActivityReactionDeletedEvent | Fired when a reaction is removed from an activity. |
CommentReactionAddedEvent | Fired when a reaction is added to a comment. |
CommentReactionUpdatedEvent | Fired when a reaction is modified on a comment. |
CommentReactionDeletedEvent | Fired when a reaction is removed from a comment. |
| Poll Events | |
PollClosedFeedEvent | Fired when a poll is closed. |
PollDeletedFeedEvent | Fired when a poll is deleted. |
PollUpdatedFeedEvent | Fired when a poll is modified. |
PollVoteCastedFeedEvent | Fired when a vote is cast on a poll. |
PollVoteChangedFeedEvent | Fired when a vote is changed on a poll. |
PollVoteRemovedFeedEvent | Fired when a vote is removed from a poll. |
| Feed Events | |
FeedCreatedEvent | Fired when a new feed is created. |
FeedUpdatedEvent | Fired when a feed is modified. |
FeedDeletedEvent | Fired when a feed is deleted. |
FeedGroupChangedEvent | Fired when a feed group is modified. |
FeedGroupDeletedEvent | Fired when a feed group is deleted. |
FeedGroupRestoredEvent | Fired when a feed group is restored. |
NotificationFeedUpdatedEvent | Fired when a notification feed has new content. |
StoriesFeedUpdatedEvent | Fired when a stories feed has new content. |
| Member Events | |
FeedMemberAddedEvent | Fired when a member is added to a feed. |
FeedMemberRemovedEvent | Fired when a member is removed from a feed. |
FeedMemberUpdatedEvent | Fired when a member's role or permissions change. |
| Follow Events | |
FollowCreatedEvent | Fired when a follow relationship is created. |
FollowUpdatedEvent | Fired when follow settings are modified. |
FollowDeletedEvent | Fired when a follow relationship is removed. |
| Bookmark Events | |
BookmarkAddedEvent | Fired when an activity is bookmarked. |
BookmarkUpdatedEvent | Fired when bookmark metadata is modified. |
BookmarkDeletedEvent | Fired when a bookmark is removed. |
BookmarkFolderUpdatedEvent | Fired when a bookmark folder is modified. |
BookmarkFolderDeletedEvent | Fired when a bookmark folder is deleted. |
| User Events | |
UserUpdatedEvent | Fired when a user's data is updated. |
UserBannedEvent | Fired when a user is banned from the app. |
UserUnbannedEvent | Fired when a user is unbanned. |
UserDeactivatedEvent | Fired when a user account is deactivated. |
UserReactivatedEvent | Fired when a user account is reactivated. |
| Moderation Events | |
ModerationFlaggedEvent | Fired when content is flagged for moderation. |
ModerationMarkReviewedEvent | Fired when a moderator marks content as reviewed. |
ModerationCustomActionEvent | Fired when a custom moderation action is triggered. |
| Feedback Events | |
ActivityFeedbackEvent | Fired when activity feedback is submitted. |
| System Events | |
AppUpdatedEvent | Fired 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:
| Name | Description |
|---|---|
| X-WEBHOOK-ID | Unique ID of the webhook call. This value is consistent between retries and could be used to deduplicate retry calls |
| X-WEBHOOK-ATTEMPT | Number of webhook request attempt starting from 1 |
| X-API-KEY | Your application’s API key. Should be used to validate request signature |
| X-SIGNATURE | HMAC 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 Name | Description |
|---|---|
| Activity Events | |
feeds.activity.added | Fired when a new activity is added to a feed |
feeds.activity.updated | Fired when an activity is modified |
feeds.activity.deleted | Fired when an activity is removed |
feeds.activity.restored | Fired when an activity is restored |
feeds.activity.removed_from_feed | Fired when an activity is removed from a specific feed |
feeds.activity.pinned | Fired when an activity is pinned to the top |
feeds.activity.unpinned | Fired when an activity is unpinned |
feeds.activity.feedback | Fired when activity feedback is provided |
feeds.activity.marked | Fired when an activity is marked |
| Notification Events | |
feeds.notification_feed.updated | Fired when the notification status, or notification groups (aggregated activities) are updated |
| Comment Events | |
feeds.comment.added | Fired when a new comment is added to an activity |
feeds.comment.updated | Fired when a comment is modified |
feeds.comment.deleted | Fired when a comment is removed |
| Reaction Events | |
feeds.activity.reaction.added | Fired when a reaction is added to an activity |
feeds.activity.reaction.deleted | Fired when a reaction is removed from an activity |
feeds.activity.reaction.updated | Fired when a reaction on an activity is updated |
feeds.comment.reaction.added | Fired when a reaction is added to a comment |
feeds.comment.reaction.deleted | Fired when a reaction is removed from a comment |
feeds.comment.reaction.updated | Fired when a reaction on a comment is updated |
| Poll Events | |
feeds.poll.closed | Fired when a poll is closed |
feeds.poll.deleted | Fired when a poll is deleted |
feeds.poll.updated | Fired when a poll is modified |
feeds.poll.vote_casted | Fired when a vote is cast |
feeds.poll.vote_changed | Fired when a vote is changed |
feeds.poll.vote_removed | Fired when a vote is removed |
| Feed Events | |
feeds.feed.created | Fired when a new feed is created |
feeds.feed.updated | Fired when a feed is modified |
feeds.feed.deleted | Fired when a feed is deleted |
| Feed Group Events | |
feeds.feed_group.changed | Fired when a feed group is changed |
feeds.feed_group.deleted | Fired when a feed group is deleted |
| Member Events | |
feeds.feed_member.added | Fired when a member is added to a feed |
feeds.feed_member.removed | Fired when a member is removed from a feed |
feeds.feed_member.updated | Fired when a member's role/permissions change |
| Follow Events | |
feeds.follow.created | Fired when a follow relationship is created |
feeds.follow.deleted | Fired when a follow relationship is removed |
feeds.follow.updated | Fired when follow settings are modified |
| Bookmark Events | |
feeds.bookmark.added | Fired when an activity is bookmarked |
feeds.bookmark.deleted | Fired when a bookmark is removed |
feeds.bookmark.updated | Fired when bookmark metadata is modified |
feeds.bookmark_folder.deleted | Fired when bookmark folder is deleted |
feeds.bookmark_folder.updated | Fired when bookmark folder is updated |
| Stories Events | |
feeds.stories_feed.updated | Fired when a stories feed is updated |
| Moderation Events | |
moderation.custom_action | Fired when a custom moderation action is performed |
moderation.flagged | Fired when content is flagged for moderation |
moderation.mark_reviewed | Fired when content is marked as reviewed |
| User Events | |
user.banned | Fired when a user is banned |
user.deactivated | Fired when a user is deactivated |
user.muted | Fired when a user is muted |
user.reactivated | Fired when a user is reactivated |
user.updated | Fired when a user is updated |