Skip Navigation
Show nav
Heroku Dev Center
  • Get Started
  • Documentation
  • Changelog
  • Search
  • Get Started
    • Node.js
    • Ruby on Rails
    • Ruby
    • Python
    • Java
    • PHP
    • Go
    • Scala
    • Clojure
  • Documentation
  • Changelog
  • More
    Additional Resources
    • Home
    • Elements
    • Products
    • Pricing
    • Careers
    • Help
    • Status
    • Events
    • Podcasts
    • Compliance Center
    Heroku Blog

    Heroku Blog

    Find out what's new with Heroku on our blog.

    Visit Blog
  • Log inorSign up
View categories

Categories

  • Heroku Architecture
    • Dynos (app containers)
    • Stacks (operating system images)
    • Networking & DNS
    • Platform Policies
    • Platform Principles
  • Command Line
  • Deployment
    • Deploying with Git
    • Deploying with Docker
    • Deployment Integrations
  • Continuous Delivery
    • Continuous Integration
  • Language Support
    • Node.js
    • Ruby
      • Working with Bundler
      • Rails Support
    • Python
      • Working with Django
      • Background Jobs in Python
    • Java
      • Working with Maven
      • Java Database Operations
      • Working with the Play Framework
      • Java Advanced Topics
      • Working with Spring Boot
    • PHP
    • Go
      • Go Dependency Management
    • Scala
    • Clojure
  • Databases & Data Management
    • Heroku Postgres
      • Postgres Basics
      • Postgres Performance
      • Postgres Data Transfer & Preservation
      • Postgres Availability
      • Postgres Special Topics
    • Heroku Redis
    • Apache Kafka on Heroku
    • Other Data Stores
  • Monitoring & Metrics
    • Logging
  • App Performance
  • Add-ons
    • All Add-ons
  • Collaboration
  • Security
    • App Security
    • Identities & Authentication
    • Compliance
  • Heroku Enterprise
    • Private Spaces
      • Infrastructure Networking
    • Enterprise Accounts
    • Enterprise Teams
    • Heroku Connect (Salesforce sync)
    • Single Sign-on (SSO)
  • Patterns & Best Practices
  • Extending Heroku
    • Platform API
    • App Webhooks
    • Heroku Labs
    • Building Add-ons
      • Add-on Development Tasks
      • Add-on APIs
      • Add-on Guidelines & Requirements
    • Building CLI Plugins
    • Developing Buildpacks
    • Dev Center
  • Accounts & Billing
  • Troubleshooting & Support
  • Add-ons
  • All Add-ons
  • Stream
Stream

This add-on is operated by Stream.io, Inc.

The API for scalable feeds and chat.

Stream

Last updated June 12, 2020

Table of Contents

  • Build activity streams & news feeds
  • Tutorial
  • Demo: Django, Rails and Laravel
  • Provisioning the add-on
  • Local setup
  • Using Stream
  • The Ruby client
  • The Node client
  • The Python client
  • The PHP client
  • Dashboard
  • Troubleshooting
  • Migrating between plans
  • Removing the add-on
  • Support

Stream is an add-on which enables you to build scalable newsfeeds & activity streams in a few hours instead of weeks.

Build activity streams & news feeds

Examples of what you can build

Feed, activity stream, newsfeed there are many names for the same concept. Stream enables your site to show content from people you follow in a scalable manner. Some examples of what you can build are:

  • Activity streams such as seen on Github
  • A twitter style newsfeed
  • A feed like instagram/ pinterest
  • Facebook style newsfeeds
  • A notification system

Building your own feed solution can take many weeks. Stream has a free plan and allows you to get started now. Focus on the user experience and let us handle the scaling and maintaining of your feed infrastructure.

Stream is accessible via an API and has supported client libraries for Ruby, Python, Node and PHP. There are also high level integrations with Django, Rails and Laravel.

Tutorial

The interactive tutorial is the easiest way to get started with the API.

Demo: Django, Rails and Laravel

Have a look at this pinterest style example application. GetStream.io has high level integrations available for the Django, Rails and Laravel Frameworks.

  • Django: integration, example code Deploy Django
  • Rails: integration, example code Deploy Rails
  • Laravel: integration, example code Deploy Laravel

The rest of the documentation explains how to use the GetStream.io API. We advice that you start by understanding the basic API before trying to work from the framework integrations.

Provisioning the add-on

Stream can be attached to a Heroku application via the CLI:

A list of all plans available can be found here.

$ heroku addons:create stream
-----> Adding stream to sharp-mountain-4005... done, v18 (free)

Once Stream has been added a STREAM_URL setting will be available in the app configuration and will contain the url. This can be confirmed using the heroku config:get command.

$ heroku config:get STREAM_URL
http://user:pass@instance.ip/?app=1

After installing Stream the application should be configured to fully integrate with the add-on.

Local setup

Environment setup

After provisioning the add-on it’s necessary to locally replicate the config vars so your development environment can operate against the service.

Though less portable it’s also possible to set local environment variables using export STREAM_URL=value.

Use the Heroku Local command-line tool to configure, run and manage process types specified in your app’s Procfile. Heroku Local reads configuration variables from a .env file. To view all of your app’s config vars, type heroku config. Use the following command to add the STREAM_URL values retrieved from heroku config to your .env file.

$ heroku config -s | grep STREAM_URL >> .env
$ more .env

Credentials and other sensitive configuration values should not be committed to source-control. In Git exclude the .env file with: echo .env >> .gitignore.

For more information, see the Heroku Local article.

Using Stream

Stream is accessible via an API and has supported client libraries for Ruby, Python, Node and PHP. If you favourite language is missing be sure to contact support@getstream.io

The Ruby client

Installation

$ gem install "stream-ruby"

Usage

# Instantiate a new client
require 'stream'
client = Stream::Client.new()

# Instantiate a feed object
user_feed_1 = client.feed('user', '1')

# Get activities from 5 to 10 (slow pagination)
result = user_feed_1.get(:limit=>5, :offset=>5)
# (Recommended & faster) Filter on an id less than the given UUID
result = user_feed_1.get(:limit=>5, :id_lt=>'e561de8f-00f1-11e4-b400-0cc47a024be0')

# Create a new activity
activity_data = {:actor => 1, :verb => 'tweet', :object => 1, :foreign_id => 'tweet:1'}
activity_response = user_feed_1.add_activity(activity_data)
# Create a bit more complex activity
activity_data = {:actor => 1, :verb => 'tweet', :object => 1, :foreign_id => 'tweet:1',
    :course => {:name => 'Golden Gate park', :distance => 10},
    :participants => ['Thierry', 'Tommaso'],
    :started_at => DateTime.now()
};
activity_response = user_feed_1.add_activity(activity_data)

# Remove an activity by its id
user_feed_1.remove('e561de8f-00f1-11e4-b400-0cc47a024be0')

# Remove activities by their foreign_id
user_feed_1.remove('tweet:1', foreign_id=true)

# Follow another feed
user_feed_1.follow('flat', '42')

# Stop following another feed
user_feed_1.unfollow('flat', '42')

# Batch adding activities
activities = [
    [:actor => '1', :verb => 'tweet', :object => '1'],
    [:actor => '2', :verb => 'like', :object => '3']
];
user_feed_1.addActivities(activities);

# Add an activity and push it to other feeds too using the `to` field
data = [
    :actor_id => "1",
    :verb => "like",
    :object_id => "3",
    :to => ["user:44", "user:45"]
];
user_feed_1.add_activity(data);

# Remove a feed and its content
user_feed_1.delete

# Generating tokens for client side usage
token = user_feed_1.token

# Javascript client side feed initialization
# user1 = client.feed('user', '1', '{{ token }}');

# Retrieve first 10 followers of a feed
user_feed_1.followers(0, 10)

# Retrieve followers from 10 to 20
user_feed_1.followers(10, 10)

# Retrieve 10 feeds followed by user_feed_1
user_feed_1.following(10)

# Retrieve 10 feeds followed by user_feed_1 starting from the 11th
user_feed_1.following(10, 10)

# Check if user_feed_1 follows specific feeds
user_feed_1.following(0, 2, filter=['user:42', 'user:43'])

Links

Docs are available on GetStream.io.

Github repo.

The Node client

Installation

Install from NPM

$ npm install getstream

Install using bower

$ bower install getstream

Usage

var stream = require('getstream');
// Instantiate a new client (server side)
client = stream.connect();
// Instantiate a new client (client side)
client = stream.connect('YOUR_API_KEY');
// Find your API keys here https://getstream.io/dashboard/

// Instantiate a feed object server side
user1 = client.feed('user', '1');
// Instantiate a feed object client side
// Generate a feed's token using server side signing
user1 = client.feed('user', '1', 'FEED_TOKEN');

// Get activities from 5 to 10 (slow pagination)
user1.get({limit:5, offset:5}, callback);
// (Recommended & faster) Filter on an id less than a given UUID
user1.get({limit:5, id_lt:"e561de8f-00f1-11e4-b400-0cc47a024be0"}, callback);

// Create a new activity
activity = {'actor': 1, 'verb': 'tweet', 'object': 1, 'foreign_id': 'tweet:1'};
user1.addActivity(activity, callback);
// Create a bit more complex activity
activity = {'actor': 1, 'verb': 'run', 'object': 1, 'foreign_id': 'run:1',
    'course': {'name': 'Golden Gate park', 'distance': 10},
    'participants': ['Thierry', 'Tommaso'],
    'started_at': new Date()
};
user1.addActivity(activity, callback);

// Remove an activity by its id
user1.removeActivity("e561de8f-00f1-11e4-b400-0cc47a024be0");
// or remove by the foreign id
user1.removeActivity({foreignId: 'tweet:1'});


// Follow another feed
user1.follow('flat', '42');

// Stop following another feed
user1.unfollow('flat', '42');

// List followers, following
user1.followers({limit: '10', offset: '10'});
user1.following({limit: '10', offset: '0'});

// all methods support callback as the last argument
user1.follow('flat', '42', callback);
// with this signature
function(error, response, body) {
}

// adding multiple activities
activities = [
    {'actor': 1, 'verb': 'tweet', 'object': 1},
    {'actor': 2, 'verb': 'tweet', 'object': 3},
];
user1.addActivities(activities, callback);

// specifying additional feeds to push the activity to using the to param
// especially usefull for notification style feeds
to = ['user:2', 'user:3'];
activity = {'to': to, 'actor': 1, 'verb': 'tweet', 'object': 1, 'foreign_id': 'tweet:1'};
user1.addActivity(activity, callback);

// creating a feed token server side
token = user1.token;
// passed to client via template or api and initialized as such
user1 = client.feed('user', '1', token);

Faye

Stream uses Faye for realtime notifications. Below is quick quide to subcribing to feed changes

var stream = require('getstream');
// NOTE: the site id is needed for subscribing
// server side example:
client = stream.connect('YOUR_API_KEY', 'API_KEY_SECRET', 'SITE_ID');
user1 = client.feed('user', '1');
// same two lines but client side (generate the feed token server side)
client = stream.connect('YOUR_API_KEY', null, 'SITE_ID');
user1 = client.feed('user', '1', 'feedtoken');
// subscribe to the changes
user1.subscribe(function callback() {
});
// now whenever something changes to the feed user 1
// the callback will be called

Links

Github repo. API Docs are available on GetStream.io.

The Python client

Installation

Install from Pypi

$ pip install stream-python

Usage

# Instantiate a new client
import stream
client = stream.connect()
# Find your API keys here https://getstream.io/dashboard/

# Instantiate a feed object
user_feed_1 = client.feed('user', '1')

# Get activities from 5 to 10 (slow pagination)
result = user_feed_1.get(limit=5, offset=5)
# (Recommended & faster) Filter on an id less than the given UUID
result = user_feed_1.get(limit=5, id_lt="e561de8f-00f1-11e4-b400-0cc47a024be0")

# Create a new activity
activity_data = {'actor': 1, 'verb': 'tweet', 'object': 1, 'foreign_id': 'tweet:1'}
activity_response = user_feed_1.add_activity(activity_data)
# Create a bit more complex activity
activity_data = {'actor': 1, 'verb': 'run', 'object': 1, 'foreign_id': 'run:1',
    'course': {'name': 'Golden Gate park', 'distance': 10},
    'participants': ['Thierry', 'Tommaso'],
    'started_at': datetime.datetime.now()
}
user_feed_1.add_activity(activity_data)

# Remove an activity by its id
user_feed_1.remove_activity("e561de8f-00f1-11e4-b400-0cc47a024be0")
# or by foreign id
user_feed_1.remove_activity(foreign_id='tweet:1')

# Follow another feed
user_feed_1.follow('flat', '42')

# Stop following another feed
user_feed_1.unfollow('flat', '42')

# List followers/following
following = user_feed_1.following(offset=0, limit=2)
followers = user_feed_1.followers(offset=0, limit=10)

# Batch adding activities
activities = [
    {'actor': 1, 'verb': 'tweet', 'object': 1},
    {'actor': 2, 'verb': 'watch', 'object': 3}
]
user_feed_1.add_activities(activities)

# Add an activity and push it to other feeds too using the `to` field
activity = {
    "actor":"1",
    "verb":"like",
    "object":"3",
    "to":["user:44", "user:45"]
}
user_feed_1.add_activity(activity)

# Generating tokens for client side usage
token = user_feed_1.token
# Javascript client side feed initialization
# user1 = client.feed('user', '1', '{{ token }}');

Links

Github project. API Docs are available on GetStream.io. Python client docs are on Read the docs.

The PHP client

Installation

Install with Composer

If you’re using Composer to manage dependencies, you can add Stream with it.

{
    "require": {
        "get-stream/stream": "$VERSION"
    }
}

(replace $VERSION with one of the available versions on Packagist)

Composer will take care of the autoloading for you, so if you require the vendor/autoload.php, you’re good to go.

Usage

// Instantiate a new client
$client = new GetStream\Stream\Client();

// Instantiate a feed object
$user_feed_1 = $client->feed('user', '1');

// Get 20 activities starting from activity with id $last_id (fast id offset pagination)
$results = $user_feed_1->getActivities(0, 20, $last_id);

// Get 10 activities starting from the 5th (slow offset pagination)
$results = $user_feed_1->getActivities(5, 10);

// Create a new activity
$data = [
    "actor"=>"1",
    "verb"=>"like",
    "object"=>"3",
    "foreign_id"=>"post:42"
];
$user_feed_1->addActivity($data);
// Create a bit more complex activity
$now = new \DateTime("now", new \DateTimeZone('Pacific/Nauru'));
$data = ['actor' => 1, 'verb' => 'run', 'object' => 1, 'foreign_id' => 'run:1',
    'course' => ['name'=> 'Golden Gate park', 'distance'=> 10],
    'participants' => ['Thierry', 'Tommaso'],
    'started_at' => $now
];
$user_feed_1->addActivity($data);

// Remove an activity by its id
$user_feed_1->removeActivity("e561de8f-00f1-11e4-b400-0cc47a024be0");

// Remove activities by their foreign_id
$user_feed_1.remove('post:42', true)

// Let user 1 start following user 42's flat feed
$user_feed_1->followFeed('flat', '42');

// Let user 1 stop following user 42's flat feed
$user_feed_1->unfollowFeed('flat', '42');

// Batch adding activities
$activities = array(
    array('actor' => '1', 'verb' => 'tweet', 'object' => '1'),
    array('actor' => '2', 'verb' => 'like', 'object' => '3')
);
$user_feed_1->addActivities($activities);

// Add an activity and push it to other feeds too using the `to` field
$data = [
    "actor"=>"1",
    "verb"=>"like",
    "object"=>"3",
    "to"=>["user:44", "user:45"]
];
$user_feed_1->addActivity($data);

// Delete a feed (and its content)
$user_feed_1->delete();

// Generating tokens for client side usage
$token = $user_feed_1->getToken();

// Javascript client side feed initialization
// user1 = client.feed('user', '1', "$token");

// Retrieve first 10 followers of a feed
$user_feed_1->followers(0, 10);

// Retrieve 2 to 10 followers
$user_feed_1->followers(2, 10);

// Retrieve 10 feeds followed by $user_feed_1
$user_feed_1->following(0, 10);

// Retrieve 10 feeds followed by $user_feed_1 starting from the 10th (2nd page)
$user_feed_1->following(10, 20);

// Check if $user_feed_1 follows specific feeds
$user_feed_1->following(0, 2, ['user:42', 'user:43']);

Links

Github project. API Docs are available on GetStream.io.

Dashboard

For more information on the features available within the Stream dashboard please see the docs at getstream.io/docs.

The Stream dashboard allows you to configure your feeds and setup custom field definitions. The dashboard can be accessed via the CLI:

$ heroku addons:open stream
Opening stream for sharp-mountain-4005…

or by visiting the Heroku Dashboard and selecting the application in question. Select Stream from the Add-ons menu.

Troubleshooting

If you run into any issues please contact support@getstream.io and we’ll get back to you shortly.

Migrating between plans

Upgrading and downgrading plans does not cause any service interruption. Simply use the heroku addons:upgrade command to migrate to a new plan.

$ heroku addons:upgrade stream:newplan
-----> Upgrading stream:newplan to sharp-mountain-4005... done, v18 ($49/mo)
       Your plan has been updated to: stream:newplan

Removing the add-on

Stream can be removed via the CLI.

This will destroy all associated data and cannot be undone!

$ heroku addons:destroy stream
-----> Removing stream from sharp-mountain-4005... done, v20 (free)

Support

All Stream support and runtime issues should be submitted via on of the Heroku Support channels. Any non-support related issues or product feedback is welcome at support@getstream.io.

Keep reading

  • All Add-ons

Feedback

Log in to submit feedback.

Ziggeo Sumo Logic

Information & Support

  • Getting Started
  • Documentation
  • Changelog
  • Compliance Center
  • Training & Education
  • Blog
  • Podcasts
  • Support Channels
  • Status

Language Reference

  • Node.js
  • Ruby
  • Java
  • PHP
  • Python
  • Go
  • Scala
  • Clojure

Other Resources

  • Careers
  • Elements
  • Products
  • Pricing

Subscribe to our monthly newsletter

Your email address:

  • RSS
    • Dev Center Articles
    • Dev Center Changelog
    • Heroku Blog
    • Heroku News Blog
    • Heroku Engineering Blog
  • Heroku Podcasts
  • Twitter
    • Dev Center Articles
    • Dev Center Changelog
    • Heroku
    • Heroku Status
  • Facebook
  • Instagram
  • Github
  • LinkedIn
  • YouTube
Heroku is acompany

 © Salesforce.com

  • heroku.com
  • Terms of Service
  • Privacy
  • Cookies