Quick Start

Stream lets you build activity feeds at scale. The largest apps on Stream have over 100 M+ users. V3 keeps that scalability while giving you more flexibility over the content shown in your feed.

What’s new in V3

  • For-You feed: Most modern apps combine a “For You” feed with a regular “Following” feed. V3 introduces activity selectors so you can:

    • surface popular activities
    • show activities near the user
    • match activities to a user’s interests
    • mix-and-match these selectors to build an engaging personalized feed.
  • Performance: 20–30 % faster flat feeds. Major speedups for aggregation and ranking, with benchmarks in the architecture guide.

  • SDK coverage: SDKs are available for JavaScript, React, React Native, iOS, Kotlin, Flutter, Node, Go, Python, Java, PHP, C#, and Ruby.

  • Activity filtering: Filter activity feeds with almost no hit to performance

  • Comments: Voting, ranking, threading, images, URL previews, @mentions & notifications. Basically all the features of Reddit style commenting systems.

  • Advanced feed features: Activity expiration • visibility controls • feed visibility levels • feed members • bookmarking • follow-approval flow • stories support.

  • Search & queries: Activity search, query activities, and query feeds endpoints.

  • Modern essentials: Permissions • OpenAPI spec • GDPR endpoints • realtime WebSocket events • push notifications • “own capabilities” API.

  • Dashboard support: Use the Stream Dashboard for app and feeds administration.

  • Migration tools: Migrate from V2 to V3 with the migration guide.

  • Activity metrics: User-engagement stats are available via activity metrics.

What is next

  • For-you feed improvements, including more AI-driven ranking options
  • See the roadmap and changelog for updates

Server side vs client side

  • Most API calls can be made client side
  • Client side API calls use the permission system. Server side API calls have full access

Most apps will default to making API calls client side, and server side do the following:

  • Updating feed groups or feed views for ranking and aggregation
  • Syncing users
  • Returning tokens for authenticating users
  • Writing to feeds that do not belong to the current user (since the user does not have access client side to do this)

Getting Started

For SDK-accurate examples generated from the OpenAPI spec, use the Stream snippets reference: TypeScript SDK - Feeds API. Replace node in the URL with the SDK language you want to inspect.

require 'getstream_ruby'

# Initialize the client
client = GetStreamRuby.manual(
  api_key: 'your_api_key',
  api_secret: 'your_api_secret'
)

# Create a feed (or get its data if exists)
feed_response = client.feeds.get_or_create_feed(
  'user',
  'john',
  GetStream::Generated::Models::GetOrCreateFeedRequest.new(user_id: 'john')
)

# Add activity
activity_request = GetStream::Generated::Models::AddActivityRequest.new(
  type: 'post',
  text: 'Hello, Stream Feeds!',
  user_id: 'john',
  feeds: ['user:john']
)

response = client.feeds.add_activity(activity_request)

Key Concepts

Activities

Activities are the core content units in Stream Feeds. They can represent posts, photos, videos, polls, and any custom content type you define.

Feeds

Feeds are collections of activities. They can be personal feeds, timeline feeds, notification feeds, or custom feeds for your specific use case.

Real-time Updates

Stream Feeds provides real-time updates through WebSocket connections, ensuring your app stays synchronized with the latest content.

Social Features

Built-in support for reactions, comments, bookmarks, and polls makes it easy to build engaging social experiences.

Common Use Cases

Social Media Feed

# Create a timeline feed
timeline_response = client.feeds.get_or_create_feed(
  'timeline',
  'john',
  GetStream::Generated::Models::GetOrCreateFeedRequest.new(user_id: 'john')
)

# Add a reaction to activity
reaction_request = GetStream::Generated::Models::AddReactionRequest.new(
  type: 'like',
  user_id: 'john'
)
reaction_response = client.feeds.add_reaction('activity_123', reaction_request)

# Add a comment to activity
comment_request = GetStream::Generated::Models::AddCommentRequest.new(
  comment: 'Great post!',
  object_id: 'activity_123',
  object_type: 'activity',
  user_id: 'john'
)
comment_response = client.feeds.add_comment(comment_request)

# Add a reaction to comment
comment_reaction_request = GetStream::Generated::Models::AddCommentReactionRequest.new(
  type: 'love',
  user_id: 'john'
)
comment_reaction_response = client.feeds.add_comment_reaction(
  comment_response.comment.id,
  comment_reaction_request
)

Notification Feed

# Create a notification feed
notifications_response = client.feeds.get_or_create_feed(
  'notification',
  'john',
  GetStream::Generated::Models::GetOrCreateFeedRequest.new(user_id: 'john')
)

# Mark notifications as read
mark_request = GetStream::Generated::Models::MarkActivityRequest.new(
  mark_all_read: true
)
client.feeds.mark_activity('notification', 'john', mark_request)

Polls

# Create a poll
poll_request = GetStream::Generated::Models::CreatePollRequest.new(
  name: 'What is your favorite color?',
  user_id: 'john',
  options: [
    GetStream::Generated::Models::PollOptionInput.new(text: 'Red'),
    GetStream::Generated::Models::PollOptionInput.new(text: 'Blue'),
    GetStream::Generated::Models::PollOptionInput.new(text: 'Green')
  ]
)
poll_response = client.common.create_poll(poll_request)

# Attach poll to an activity
activity_request = GetStream::Generated::Models::AddActivityRequest.new(
  type: 'poll',
  text: 'What is your favorite color?',
  poll_id: poll_response.poll.id,
  user_id: 'john',
  feeds: ['user:john']
)
activity_response = client.feeds.add_activity(activity_request)

# Cast a vote
vote_request = GetStream::Generated::Models::CastPollVoteRequest.new(
  vote: GetStream::Generated::Models::VoteData.new(
    option_id: poll_response.poll.options.first.id
  ),
  user_id: 'john'
)
vote_response = client.feeds.cast_poll_vote(
  activity_response.activity.id,
  poll_response.poll.id,
  vote_request
)

Advanced Features

Custom Activity Types

Create custom activity types to represent your app's specific content:

# Add custom activity with custom fields
workout_activity = GetStream::Generated::Models::AddActivityRequest.new(
  type: 'workout',
  text: 'Just finished my run',
  user_id: 'john',
  feeds: ['user:john'],
  custom: {
    distance: 5.2,
    duration: 1800,
    calories: 450
  }
)

response = client.feeds.add_activity(workout_activity)

Real-time Updates with State Layer

Only for client-side SDKs

@MainActor class FeedViewModel: ObservableObject {
    private var cancellables = Set<AnyCancellable>()
    private let feed: Feed
    @Published var activities: [ActivityData] = []

    init(feed: Feed) {
        self.feed = feed
        setupRealtimeUpdates()
    }

    private func setupRealtimeUpdates() {
        feed.state.$activities
            .sink { [weak self] activities in
                self?.activities = activities
            }
            .store(in: &cancellables)
    }
}