Ruby

"In its simplest form, an activity consists of an actor, a verb, and an object. It tells the story of a person performing an action on or with an object."

Activity Streams Specification 1.0

Adding Activities: Basic

Copied!

Adding an activity in its simplest form means passing an object with the following basic properties:

  • Actor

  • Verb

  • Object

  • Recommended:

    • Foreign Id

    • Time

Here's an example:

“Erik is pinning Hawaii to his Places to Visit board.”

Let's break the example down:

  • Actor: "Eric" (User:1)

  • Verb: "pin"

  • Object: "Hawaii" (Place:42)

  • Foreign Id: "Eric's board activity" (Activity:1)

  • Time: 2017-07-01T20:30:45.123

As seen above time doesn't have any timezone information but it's always in UTC.

Now, let's show you how to add an activity to a feed using your Stream API client:

1
2
3
4
5
# Instantiate a feed object 
user_feed_1 = client.feed('user', '1') 
# Add an activity to the feed, where actor, object and target are references to objects (`Eric`, `Hawaii`, `Places to Visit`) 
activity_data = {:actor => "User:1", :verb => "pin", :object => "Place:42"} 
activity_response = user_feed_1.add_activity(activity_data)
1
2
3
4
5
6
# Instantiate a feed object 
user_feed_1 = client.feed('user', '1') 
 
# Add an activity to the feed, where actor, object and target are references to objects (`Eric`, `Hawaii`, `Places to Visit`) 
activity_data = {"actor": "User:1", "verb": "pin", "object": "Place:42"} 
activity_response = user_feed_1.add_activity(activity_data)
1
2
3
4
5
6
7
8
9
10
11
12
// Instantiate a feed object 
FlatFeed userFeed = client.flatFeed("user", "1"); 
 
// Add an activity to the feed, where actor, object and target  
// are references to objects (`Eric`, `Hawaii`, `Places to Visit`) 
Activity activity = Activity.builder() 
        .actor("User:1") 
        .verb("pin") 
        .object("Place:42") 
        .target("Board:1") 
        .build(); 
userFeed.addActivity(activity).get();
1
2
3
4
5
6
7
8
9
10
11
12
13
// Instantiate a feed object 
userFeed := client.FlatFeed("user", "1") 
 
// Add an activity to the feed, where actor, object and target are references to objects (`Eric`, `Hawaii`, `Places to Visit`) 
activity := stream.Activity{ 
    Actor:  "User:1", 
    Verb:   "pin", 
    Object: "Place:42", 
} 
_, err := userFeed.AddActivity(activity) 
if err != nil { 
    panic(err) 
}
1
2
3
4
5
6
7
8
9
10
11
// Instantiate a feed object 
$userFeed1 = $client->feed('user', '1'); 
 
// Add an activity to the feed, where actor, object and target are references to objects (`Eric`, `Hawaii`, `Places to Visit`) 
$data = [ 
    "actor"=>"User:1", 
    "verb"=>"pin", 
    "object"=>"Place:42" 
]; 
 
$userFeed1->addActivity($data);
1
2
3
4
5
6
7
// Instantiate a feed object 
var userFeed1 = client.Feed("user", "1"); 
 
// Add an activity to the feed, where actor, object and target are references to objects (`Eric`, `Hawaii`, `Places to Visit`) 
 
var activity = new Activity("User:1", "pin", "Place:42"); 
userFeed1.AddActivity(activity);
1
2
3
4
5
6
7
8
9
let userFeed = Client.shared.flatFeed(feedSlug: "user") 
let activity = Activity(actor: User.current!, verb: "pin", object: "Place:42") 
 
userFeed?.add(activity) { result in 
    if let activity = try? result.get() { 
        // Added activity 
        print(activity.id) 
    } 
}
1
2
3
4
5
6
7
8
9
10
11
12
// Server-side: Instantiate a feed using feed group 'user' and user id '1' 
const user1 = client.feed('user', '1'); 
 
// Client-side: Instantiate a feed for feed group 'user', user id '1'  
// and a security token generated server side 
const user1 = client.feed('user', '1', token); 
 
// Create an activity object 
const activity = { actor: 'User:1', verb: 'pin', object: 'Place:42' }; 
 
// Add an activity to the feed 
await user1.addActivity(activity);

Listed below are the mandatory and recommended fields when adding Activities.

Fields

Copied!
nametypedescriptiondefaultoptional
actorstringthe actor performing the activity-
verbstringThe verb of the activity with a maximum length of 255 bytes-
objectstringThe object of the activity-
timestringThe time of the activity, iso format (UTC local time). Required to ensure activity uniqueness and also to later update activities by Time + Foreign IDCurrent time
tolistSee the documentation on Targeting & "TO" support.-
foreign_idstringA unique ID from you application for this activity. IE: pin:1 or like:300. Required to later update activities by Time + Foreign ID.-
*string / list / object / pointAdd as many custom fields as needed.-

Custom Fields

Copied!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// Server-side: Instantiate a feed using feed class 'user' and user id '1' 
const user1 = client.feed('user', '1'); 
 
// Client-side: Instantiate a feed for feed group 'user', user id '1'  
// and a security token generated server side 
const user1 = client.feed('user', '1', userToken); 
 
// Create a bit more complex activity 
const activity = { 
    'actor': 'User:1',  
    'verb': 'run',  
    'object': 'Exercise:42', 
    'course': { 'name': 'Golden Gate park', 'distance': 10 }, 
    'participants': ['Thierry', 'Tommaso'], 
    'started_at': new Date(), 
    'foreign_id': 'run:1', 
    'location': { 'type': 'point', 'coordinates': [37.769722,-122.476944] } 
}; 
 
await user1.addActivity(activity);
1
2
3
4
5
6
7
8
9
# Create a bit more complex activity 
activity_data = {:actor => 'User:1', :verb => 'run', :object => 'Exercise:42', 
    :course => {:name => 'Golden Gate park', :distance => 10}, 
    :participants => ['Thierry', 'Tommaso'], 
    :started_at => DateTime.now(), 
    :foreign_id => 'run:1', 
    :location => {:type => 'point', :coordinates => [37.769722,-122.476944] } 
} 
activity_response = user_feed_1.add_activity(activity_data)
1
2
3
4
5
6
7
8
9
10
11
import datetime 
 
# Create a bit more complex activity 
activity_data = {'actor': 'User:1', 'verb': 'run', 'object': 'Exercise:42', 
    'course': {'name': 'Golden Gate park', 'distance': 10}, 
    'participants': ['Thierry', 'Tommaso'], 
    'started_at': datetime.datetime.utcnow(), 
    'foreign_id': 'run:1', 
    'location': {'type': 'point', 'coordinates': [37.769722,-122.476944] } 
} 
user_feed_1.add_activity(activity_data)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// Create a bit more complex activity 
Activity activity = Activity.builder() 
        .actor("User:1") 
        .verb("run") 
        .object("Exercise:42") 
        .foreignID("run:1") 
        .extra(new ImmutableMap.Builder<String, Object>() 
                .put("course", new ImmutableMap.Builder<String, Object>() 
                        .put("name", "Golden Gate park") 
                        .put("distance", 10) 
                        .build()) 
                .put("participants", new String[]{ 
                        "Thierry", 
                        "Tommaso", 
                }) 
                .put("started_at", LocalDateTime.now()) 
                .put("location", new ImmutableMap.Builder<String, Object>() 
                        .put("type", "point") 
                        .put("coordinates", new double[]{37.769722, -122.476944}) 
                        .build()) 
                .build()) 
        .build(); 
userFeed.addActivity(activity).join();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// Create a bit more complex activity 
activity := stream.Activity{ 
    Actor:     "User:1", 
    Verb:      "run", 
    Object:    "Exercise:42", 
    ForeignID: "run:1", 
    Extra: map[string]interface{}{ 
        "course": map[string]interface{}{ 
            "name":     "Golden Gate park", 
            "distance": 10, 
        }, 
        "participants": []string{ 
            "Thierry", 
            "Tommaso", 
        }, 
        "started_at": time.Now(), 
    }, 
} 
_, err := userFeed.AddActivity(activity) 
if err != nil { 
    panic(err) 
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// Create a bit more complex activity 
$now = new DateTime('now'); 
 
$data = [ 
    'actor' => 'User:1', 
    'verb' => 'run', 
    'object' => 1, 
    'course' => ['name'=> 'Golden Gate park', 'distance'=> 10], 
    'participants' => ['Thierry', 'Tommaso'], 
    'started_at' => $now, 
    'foreign_id' => 'run:1', 
    'location' => [ 
        'type'=> 'point', 
        'coordinates'=> [ 
            37.769722, -122.476944, 
        ], 
    ], 
]; 
 
$userFeed1->addActivity($data);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// Create a bit more complex activity 
var activity = new Activity("User:1", "run", "Exercise:42") 
{ 
	ForeignId = "run:1" 
}; 
var course = new Dictionary<string, object>(); 
course["name"] = "Shevlin Park"; 
course["distance"] = 10; 
 
var participants = new string[] { "Thierry", "Tommaso" }; 
 
var location = new Dictionary<string, object>(); 
location.Add("type", "point"); 
location.Add("coordinates", new float[] {37.769722F, -122.476944F}); 
 
activity.SetData("location", location); 
activity.SetData("course", course); 
activity.SetData("participants", participants);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
// Create a custom Activity class. 
final class ExerciseActivity: EnrichedActivity<User, String, DefaultReaction> { 
    private enum CodingKeys: String, CodingKey { 
        case course 
        case participants 
        case startDate = "started_at" 
    } 
     
    var course: Course 
    var participants: [String] = [] 
    var startDate: Date = Date() 
     
    init(verb: Verb,  
         object: String,  
         course: Course, 
         participants: [String], 
         startDate: Date = Date()) { 
        super.init(actor: User.current!, verb: verb, object: object) 
        self.course = course 
        self.participants = participants 
        self.startDate = startDate 
    } 
     
    required init(from decoder: Decoder) throws { 
        let container = try decoder.container(keyedBy: CodingKeys.self) 
        course = try container.decode(Course.self, forKey: .course) 
        participants = try container.decode([String].self, forKey: .participants) 
        startDate = try container.decode(Date.self, forKey: .startDate) 
        try super.init(from: decoder) 
    } 
     
    override public func encode(to encoder: Encoder) throws { 
        var container = encoder.container(keyedBy: CodingKeys.self) 
        try container.encode(course, forKey: .course) 
        try container.encode(participants, forKey: .participants) 
        try container.encode(startDate, forKey: .startDate) 
        try super.encode(to: encoder) 
    } 
} 
 
struct Course: Codable { 
    let name: String 
    let distance: Float 
} 
 
let exerciseActivity = ExerciseActivity(verb: "run",  
                                        object: "Exercise:42",  
                                        course: Course(name: "Golden Gate Park", distance: 10),  
                                        participants: ["Thierry", "Tommaso"]) 
 
// Add the exercise activity to the user feed.  
userFeed?.add(exerciseActivity) { result in 
    print(result) 
} 
 
// Get a list of exercise activities. 
userFeed?.get(typeOf: ExerciseActivity.self) { result in 
    print(result) 
}

In the above example, the  course,  location,  participants  and  started_at  fields will be stored with the Activity and included whenever the Activity is retrieved.

For performance reasons, activities are limited in size (4KB) and must not contain blob/binary data (e.g. base64 encoded images). Use references and identifiers to facilitate Activity enrichment by your backend or client.

These reserved words must not be used as field names:  activity_idactivityanalyticsextra_contextidis_readis_seenoriginscoresite_idto.
In one add call, at max 100 activities can be included.

Foreign IDs

The example above also specified a foreign_id.

The foreign id is a unique identifier for the activity that can be stored and used within the app. Making use of the the foreign id field is highly recommended as it is needed in order to update Activities.

Add Activity Response Data

Copied!

When an activity is successfully added, the Stream API includes activity id in the serialized JSON response, like so:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{   
   id:"ef696c12-69ab-11e4-8080-80003644b625", 
   actor:"User:1", 
   course:{   
      distance:10, 
      name:"Golden Gate Park" 
   }, 
   object:"Exercise:42", 
   participants:[   
      "Thierry", 
      "Tommaso" 
   ], 
   started_at:"2014-11-11T15:06:16+01:00", 
   target:null, 
   time:"2014-11-11T14:06:30.494", 
   verb:"run" 
}

Retrieving Activities

Copied!

The example below shows how to retrieve the Activities in a feed:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
// Get activities from 5 to 10 
 
user1.get({ limit:5, offset:5 }) 
  .then(activitiesSuccess) 
  .catch(activitiesError); 
 
// Get the 5 activities added after lastActivity  
 
user1.get({ limit:5, id_lt: lastActivity.id }) 
  .then(activitiesSuccess) 
  .catch(activitiesError); 
 
// Get the 5 activities added before lastActivity  
 
user1.get({ limit:5, id_gt: lastActivity.id }) 
  .then(activitiesSuccess) 
  .catch(activitiesError); 
 
// Get activities sorted by rank (Ranked Feeds Enabled) 
 
user1.get({ limit:20, ranking:'popularity'}) 
  .then(activitiesSuccess) 
  .catch(activitiesError); 
 
// Get the 5 activities and enrich them with reactions and collections 
 
user1.get({  
  limit:20, enrich:true, 
  reactions: {own: true, counts: true, recent: true}, 
}) 
  .then(activitiesSuccess) 
  .catch(activitiesError); 
 
function activitiesSuccess(successData) { 
  console.log(successData); 
} 
 
function activitiesError(errorData) { 
  console.log(errorData); 
}
1
2
3
4
5
6
7
8
9
10
11
# Get activities from 5 to 10 
result = user_feed_1.get(:limit=>5, :offset=>5) 
 
# Get the 5 activities added after last_activity  
result = user_feed_1.get(:limit=>5, :id_lt=>last_activity.id) 
 
# Get the 5 activities added before last_activity  
result = user_feed_1.get(:limit=>5, :id_gt=>last_activity.id) 
 
# Get activities sorted by rank (Ranked Feeds Enabled): 
result = user_feed_1.get(:limit=>5, :ranking=>'popularity')
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# Get activities from 5 to 10 
result = user_feed_1.get(limit=5, offset=5) 
 
# Get the 5 activities added after last_activity  
result = user_feed_1.get(limit=5, id_lt=last_activity.id) 
 
# Get the 5 activities added before last_activity  
result = user_feed_1.get(limit=5, id_gt=last_activity.id) 
 
# Get activities sorted by rank (Ranked Feeds Enabled): 
result = user_feed_1.get(limit=5, ranking="popularity") 
 
# Get first 5 activities and enrich them with reactions and collections 
result = user_feed_1.get( 
    limit=5, enrich=True, reactions={"counts": True, "recent": True}, 
)
1
2
3
4
5
6
// Get 5 activities with id less than the given UUID (Faster - Recommended!) 
response = userFeed.getActivities(new Filter().idLessThan("e561de8f-00f1-11e4-b400-0cc47a024be0").limit(5)).join(); 
// Get activities from 5 to 10 (Pagination-based - Slower) 
response = userFeed.getActivities(new Pagination().offset(0).limit(5)).join(); 
// Get activities sorted by rank (Ranked Feeds Enabled): 
response = userFeed.getActivities(new Pagination().limit(5), "popularity").join();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// Get activities from 5 to 10 
resp, err = userFeed.GetActivities( 
    stream.WithActivitiesLimit(5), 
    stream.WithActivitiesOffset(5), 
) 
if err != nil { 
    panic(err) 
} 
 
// Get the 5 activities added after lastActivity  
resp, err := userFeed.GetActivities( 
    stream.WithActivitiesLimit(5), 
    stream.WithActivitiesIDLT(lastActivity.ID), 
) 
if err != nil { 
    panic(err) 
} 
 
// Get activities sorted by rank (Ranked Feeds Enabled): 
resp, err = userFeed.GetActivitiesWithRanking( 
    "popularity", 
    stream.WithActivitiesLimit(5), 
) 
if err != nil { 
    panic(err) 
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Get activities from 5 to 10 
$results = $userFeed1->getActivities(5, 5); 
 
# Get the 5 activities added after last_activity  
$options = ['id_lt' => $last_activity_id]; 
$results = $userFeed1->getActivities(0, 5, $options); 
 
# Get the 5 activities added before last_activity  
$options = ['id_gt' => $last_activity_id]; 
$results = $userFeed1->getActivities(0, 5, $options); 
 
// Get 5 enriched activities - using limit, offset, enrich - and sorted by rank (Ranked Feeds Enabled): 
$options = ['ranking' => 'popularity']; 
$results = $userFeed1->getActivities(0, 5, $options, $enrich=true);
1
2
3
4
5
6
7
8
// Get activities from 5 to 10 
var result = await userFeed1.GetActivities(5, 5); 
 
# Get the 5 activities added after lastActivity  
var result = await userFeed1.GetActivities(0, 5, FeedFilter.Where().IdLessThan(lastActivity.id)); 
 
// Get activities sorted by rank (Ranked Feeds Enabled): 
var flatActivities = await userFeed1.GetFlatActivities(GetOptions.Default.WithLimit(5).WithRanking("popularity"));
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Get activities from 5 to 10. 
userFeed?.get(pagination: .limit(5) + .offset(5)) { result in /* ... */ } 
 
// Get the 5 activities added after lastActivity. 
userFeed?.get(pagination: .limit(5) + .lessThan(lastActivity.id)) { result in /* ... */ } 
 
// Get the 5 activities added before lastActivity. 
userFeed?.get(pagination: .limit(5) + .greaterThan(lastActivity.id)) { result in /* ... */ } 
 
// Get activities sorted by rank (Ranked Feeds Enabled). 
userFeed?.get(pagination: .limit(5), ranking: "popularity") { result in /* ... */ } 
 
// Get the 5 activities and enrich them with reactions and collections. 
userFeed?.get(enrich: true, pagination: .limit(5), includeReactions: [.own, .latest, .counts]) { result in /* ... */ }

Parameters

Copied!
nametypedescriptiondefaultoptional
limitintegerThe number of Activities to retrieve (max: 100)25
id_gtestringFilter the feed on ids greater than or equal to the given value-
id_gtstringFilter the feed on ids greater than the given value-
id_ltestringFilter the feed on ids smaller than or equal to the given value-
id_ltstringFilter the feed on ids smaller than the given value-
offsetintegerThe offset0
rankingstringThe custom ranking formula used to sort the feed, must be defined in the dashboard-
enrichbooleanWhen using collections, you can request Stream to enrich activities to include themfalse
reactions.ownbooleanInclude reactions added by current user to all activities (see reaction docs)false
reactions.recentbooleanInclude recent reactions to activities (see reaction docs)false
reaction.countsbooleanInclude reaction counts to activities (see reaction docs)false
reaction.kindsarrayFilter reactions with given kinds (support differs by SDKs, request if missing)-

Activity reads returns at most 100 Activities. Requests with a limit greater than 100 are automatically capped.

Pagination

Copied!

The recommended way to paginate feeds is with offset and limit parameters. Such approach makes for simpler code and it works for all types of feeds.

When using id_lte to paginate an aggregated feed, use the ID of the group that is returned from the API. Using an ID of an individual activity within the group will not work and result in an error.
Sorting using a custom ranking formula is only available on paid plans.

Retrieve Feed Response Data

Copied!

When a feed is successfully retrieved, the Stream API returns the following payload:

1
2
3
4
{ 
  results: [], 
  next: '/api/v1.0/feed/<< feed_group >>/<< feed_id >>/?api_key=<< api_key >>&id_lt=<< next_activity_id >>&limit=<< activity_limit >>' 
}

The format for results array depends on the type of feed associated with the notification. When a Flat Feed is retrieved, the array contains Activities. Whereas when an Aggregated or Notification Feed is retrieved, the array contains Activity Groups.

The 'next' property in the response contains a URL that may be used to retrieve the next page of activities within the feed.

Removing Activities

Copied!

There are two ways to remove an activity:

  • Activity Id - found in the serialized response from server

  • Foreign Id - optionally specified when adding an activity

Have a look at the section on Using Foreign IDs.

1
2
3
4
5
// Remove an activity by its id 
user1.removeActivity("ACTIVITY_ID"); 
 
// Remove activities foreign_id 'run:1' 
user1.removeActivity({foreignId: 'run:1'});
1
2
3
4
5
# Remove an activity by its id 
user_feed_1.remove_activity('ACTIVITY_ID') 
 
# Remove activities with foreign_id 'run:1' 
user_feed_1.remove_activity('run:1', foreign_id=true)
1
2
3
4
5
6
7
8
# Remove an activity by its id 
response = user_feed_1.remove_activity("e561de8f-00f1-11e4-b400-0cc47a024be0") 
 
removed_activity_id = response["removed"] 
 
# Remove activities with foreign_id 'run:1' 
response = user_feed_1.remove_activity(foreign_id='run:1') 
removed_foreign_id = response["removed"]
1
2
3
4
5
// Remove an activity by its id 
userFeed.removeActivityByID("e561de8f-00f1-11e4-b400-0cc47a024be0").join(); 
 
// Remove activities with foreign_id 'run:1' 
userFeed.removeActivityByForeignID("run:1").join();
1
2
3
4
5
6
7
8
9
10
// Remove an activity by its id 
err := userFeed.RemoveActivityByID("e561de8f-00f1-11e4-b400-0cc47a024be0") 
if err != nil { 
    panic(err) 
} 
// Remove activities with foreign_id 'run:1' 
err = userFeed.RemoveActivityByForeignID("run:1") 
if err != nil { 
    panic(err) 
}
1
2
3
4
5
// Remove an activity by its id 
$userFeed1->removeActivity('e561de8f-00f1-11e4-b400-0cc47a024be0'); 
 
// Remove activities with foreign_id 'run:1' 
$userFeed1->removeActivity('run:1', true)
1
2
3
4
5
// Remove an activity by its id 
feed.RemoveActivity("e561de8f-00f1-11e4-b400-0cc47a024be0"); 
 
// Remove activities by their foreign_id 
feed.RemoveActivity("run:1", true);
1
2
3
4
5
// Remove an activity by its id. 
userFeed?.remove(activityId: "50539e71-d6bf-422d-ad21-c8717df0c325") 
 
// Remove activities foreign_id "run:1". 
userFeed?.remove(foreignId: "run:1")
When you remove by foreign_id field, all activities in the feed with the provided foreign_id will be removed.

Updating Activities

Copied!

Activities that have both foreign_id and time defined can be updated via the APIs. Changes to activities immediately show up on every feed.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const now = new Date(); 
 
const activity = { 
    "actor": "1", 
    "verb":"like", 
    "object": "3", 
    "time": now.toISOString(), 
    "foreign_id": "like:3", 
    "popularity": 100, 
}; 
 
// first time the activity is added 
user1.addActivity(activity); 
 
// update the popularity value for the activity 
activity.popularity = 10; 
 
// send the update to the APIs 
client.updateActivities([activity]);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
activity = { 
  :actor => "1", 
  :verb => "like", 
  :object => "3", 
  :time => DateTime.now, 
  :foreign_id => "like:3", 
  :popularity => 100 
} 
 
# first time the activity is added 
user_feed_1.add_activity(activity) 
 
# update the popularity value for the activity 
activity[:popularity] = 10 
 
# send the update to the APIs 
client.update_activities([activity])
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
activity = { 
    "actor": "1", 
    "verb":"like", 
    "object": "3", 
    "time": datetime.datetime.utcnow(), 
    "foreign_id": "like:3", 
    "popularity": 100 
} 
 
# first time the activity is added 
user_feed_1.add_activity(activity) 
 
# update the popularity value for the activity 
activity['popularity'] = 10 
 
# send the update to the APIs 
client.update_activities([activity])
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Activity activity = Activity.builder() 
        .actor("1") 
        .verb("like") 
        .object("3") 
        .time(new Date()) 
        .foreignID("like:3") 
        .extraField("popularity", 100) 
        .build(); 
 
// first time the activity is added 
userFeed.addActivity(activity).join(); 
 
// update the popularity value for the activity 
activity = Activity.builder() 
        .fromActivity(activity) 
        .extraField("popularity", 10) 
        .build(); 
 
client.batch().updateActivities(activity);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
activity := stream.Activity{ 
    Actor:     "1", 
    Verb:      "like", 
    Object:    "3", 
    Time:      stream.Time{time.Now()}, 
    ForeignID: "like:3", 
    Extra: map[string]interface{}{ 
        "popularity": 100, 
    }, 
} 
 
// first time the activity is added 
_, err := userFeed.AddActivity(activity) 
if err != nil { 
    panic(err) 
} 
 
// update the popularity value for the activity 
activity.Extra["popularity"] = 10 
 
// send the update to the APIs 
err = userFeed.UpdateActivities(activity) 
if err != nil { 
    panic(err) 
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
$now = new DateTime('now'); 
$activities = []; 
 
$activity = [ 
    'actor' => 1, 
    'verb' => 'tweet', 
    'object' => 1, 
    'time' => $now->format(DateTime::ISO8601), 
    'foreign_id' => 'batch1', 
    'popularity' => 100, 
]; 
 
// add the activity to a feed 
$userFeed1->addActivity(activity); 
 
// change a field of the activity data 
$activity['popularity'] = 10; 
 
$activities = [$activity]; 
 
// update the activity 
$client->updateActivities($activities);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var activity = new Activity("1", "like", "3") 
{ 
    Time = DateTime.Now, 
    ForeignId = "like:3" 
}; 
activity.SetData("popularity", 100); 
 
// first time the activity is added 
await userFeed1.AddActivity(activity); 
 
// update the popularity value for the activity 
activity.SetData("popularity", 10); 
 
// send the update to the APIs 
await client.Batch.UpdateActivity(activity);
1
2
3
4
5
6
7
// Create a custom activity with a `popularity` property. 
let activity = Activity(actor: User.current!, verb: "like", object: "3", popularity: 100) 
 
userFeed?.add(activity) { _ in 
    activity.popularity = 10 
    Client.shared.update(activities: [activity]) { result in /* ... */ } 
}
When you update an activity, you must include the following fields both when adding and updating the activity:time & foreign_id
It is not possible to update more than 100 activities per request with this method.
When updating an activity, any changes to the to field are ignored.

This API method works particularly well in combination with the ranked feeds. You can, for instance, issue an update if an activity is promoted or not and use the ranked feeds to show it higher in the feed. Similarly, you could update the like and comment counts and use a ranking method based on popularity to sort the activities.

Activity Partial Update

Copied!

It is possible to update only a part of an activity with the partial update request. You can think of it as a quick "patching operation".

The activity to update can be selected by its ID or Foreign ID and Time combination.

set and an unset params can be provided to add, modify, or remove attributes to/from the target activity. The set and unset params can be used separately or combined together (see below).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// partial update by activity ID 
client.activityPartialUpdate({ 
  id: '54a60c1e-4ee3-494b-a1e3-50c06acb5ed4', 
  set: { 
    'product.price': 19.99, 
    'shares': { 
      'facebook': '...', 
      'twitter': '...' 
    }, 
  }, 
  unset: [ 
    'daily_likes', 
    'popularity' 
  ] 
}) 
 
// partial update by foreign ID 
client.activityPartialUpdate({ 
  foreign_id: 'product:123', 
  time: '2016-11-10T13:20:00.000000', 
  set: { 
    ... 
  }, 
  unset: [ 
    ... 
  ] 
})