// Add an activity to 1 feed
let activity = try await feed.addActivity(
request: .init(
text: "hello world",
type: "post"
)
)
// Add an activity to multiple feeds
let multiFeedActivity = try await client.addActivity(
request: .init(
feeds: ["user:1", "stock:apple"],
text: "apple stock will go up",
type: "post"
)
)
Activity Feeds V3 is in closed alpha — do not use it in production (just yet).
Activities
Creating Activities
The example below shows how to create an activity and add it to a feed.
// Add an activity to 1 feed
val activity: Result<ActivityData> = feed.addActivity(
request = FeedAddActivityRequest(
text = "hello world",
type = "post"
)
)
// Add an activity to multiple feeds
val multiFeedActivity: Result<ActivityData> = client.addActivity(
request = AddActivityRequest(
fids = listOf("user:1", "stock:apple"),
text = "apple stock will go up",
type = "post"
)
)
// Add an activity to 1 feed
const response = await feed.addActivity({
type: "post",
text: "apple stock will go up",
});
console.log(response.activity);
//...or multiple feeds
const response = await client.addActivity({
feeds: ["user:1", "stock:apple"],
type: "post",
text: "apple stock will go up",
});
// Add an activity to 1 feed or multiple feeds
const response = await client.feeds.addActivity({
feeds: ["user:1", "stock:apple"],
type: "post",
text: "apple stock will go up",
// Provide user id, the owner of the activity
user_id: "<user id>",
});
console.log(response.activity);
// Add an activity to 1 feed
final activity = await feed.addActivity(
request: const FeedAddActivityRequest(text: 'Hello world', type: 'post'),
);
// Add an activity to multiple feeds
final multiFeedActivity = await feed.addActivity(
request: const FeedAddActivityRequest(
feeds: ['user:1', 'stock:apple'],
text: 'apple stock will go up',
type: 'post',
),
);
feedsClient := client.Feeds()
response, err := feedsClient.AddActivity(context.Background(), &getstream.AddActivityRequest{
Type: "post",
Feeds: []string{"user:john", "stock:apple"},
Text: getstream.PtrTo("apple stock will go up"),
UserID: getstream.PtrTo("john"),
})
if err != nil {
log.Fatal("Error adding activity:", err)
}
log.Printf("Activity added successfully: %+v", response)
AddActivityRequest activity =
AddActivityRequest.builder()
.type("post")
.feeds(List.of(testFeedId))
.text("This is a test activity from Java SDK")
.userID(testUserId)
.build();
AddActivityResponse response = feeds.addActivity(activity).execute().getData();
// Add an activity to 1 feed or multiple feeds
$activity = new GeneratedModels\AddActivityRequest(
type: 'post',
feeds: ['user:1', 'stock:apple'],
text: 'apple stock will go up',
userID: '<user id>',
custom: (object)[
'test_field' => 'test_value',
'timestamp' => time()
]
);
$response = $feedsClient->addActivity($activity);
var activity = new AddActivityRequest
{
Type = "post",
Text = "This is a test activity from .NET SDK",
UserID = _testUserId,
Feeds = new List<string> { $"user:{_testFeedId}" }
};
var response = await _feedsV3Client.AddActivityAsync(activity);
response = self.client.feeds.add_activity(
type="post",
feeds=[self.test_feed.get_feed_identifier()],
text="This is a test activity from Python SDK",
user_id=self.test_user_id,
custom={
"test_field": "test_value",
"timestamp": int(datetime.now().timestamp()),
},
)
# Add an activity to 1 feed
activity_request = GetStream::Generated::Models::AddActivityRequest.new(
type: 'post',
text: 'hello world',
user_id: 'user123',
feeds: ['user:user123']
)
response = client.feeds.add_activity(activity_request)
# Add an activity to multiple feeds
multi_feed_request = GetStream::Generated::Models::AddActivityRequest.new(
type: 'post',
text: 'apple stock will go up',
user_id: 'user123',
feeds: ['user:1', 'stock:apple']
)
response = client.feeds.add_activity(multi_feed_request)
The above example was quite simple. Here are a few more examples:
Image & Video
let imageActivity = try await feed.addActivity(
request: .init(
attachments: [
Attachment(
imageUrl: "https://example.com/image.jpg",
type: "image"
)
],
text: "look at NYC",
type: "post"
)
)
val imageActivity: Result<ActivityData> = feed.addActivity(
request = FeedAddActivityRequest(
attachments = listOf(
Attachment(
imageUrl = "https://example.com/image.jpg",
type = "image"
)
),
text = "look at NYC",
type = "post"
)
)
feed.addActivity({
type: "post",
text: "look at NYC",
attachments: [
{
type: "image",
image_url: "https://example.com/image.png",
custom: {},
},
],
});
client.feeds.addActivity({
feeds: ["user:1"],
type: "post",
text: "look at NYC",
attachments: [
{
type: "image",
image_url: "https://example.com/image.png",
custom: {},
},
],
// Provide user id, the owner of the activity
user_id: "<user id>",
});
final imageActivity = await feed.addActivity(
request: const FeedAddActivityRequest(
attachments: [
Attachment(
imageUrl: 'https://example.com/image.jpg',
type: 'image',
custom: {'width': 600, 'height': 400},
),
],
text: 'look at NYC',
type: 'post',
),
);
response, err := client.Feeds().AddActivity(context.Background(), &getstream.AddActivityRequest{
Type: "post",
Feeds: []string{"user:john"},
Text: getstream.PtrTo("look at NYC"),
UserID: getstream.PtrTo("john"),
Attachments: []getstream.Attachment{
{
AssetUrl: getstream.PtrTo("https://example.com/image.png"),
Type: getstream.PtrTo("image"),
Title: getstream.PtrTo("Amazing Video"),
Custom: map[string]interface{}{},
},
},
})
AddActivityRequest activity =
AddActivityRequest.builder()
.type("video")
.feeds(List.of(testFeedId))
.text("Check out this amazing video!")
.userID(testUserId)
.build();
AddActivityResponse response = feeds.addActivity(activity).execute().getData();
$activity = new GeneratedModels\AddActivityRequest(
type: 'post',
feeds: ['user:1'],
text: 'look at NYC',
userID: '<user id>',
attachments: [
new GeneratedModels\Attachment(
imageUrl: 'https://example.com/image.png',
type: 'image',
custom: (object)[]
)
]
);
$response = $feedsClient->addActivity($activity);
var activity = new AddActivityRequest
{
Type = "video",
Text = "Check out this amazing video!",
UserID = _testUserId,
Feeds = new List<string> { $"user:{_testFeedId}" }
// Note: Video attachments would be added here in a real scenario
};
var response = await _feedsV3Client.AddActivityAsync(activity);
response = self.client.feeds.add_activity(
type="video",
feeds=[self.test_feed.get_feed_identifier()],
text="Check out this amazing video!",
user_id=self.test_user_id,
attachments=[
Attachment(
custom={"duration": 120},
asset_url="https://example.com/amazing-video.mp4",
type="video",
title="Amazing Video",
)
],
custom={"video_quality": "4K", "duration_seconds": 120},
)
# Image activity
attachment = GetStream::Generated::Models::Attachment.new(
image_url: 'https://example.com/image.jpg',
type: 'image',
title: 'Test Image'
)
activity_request = GetStream::Generated::Models::AddActivityRequest.new(
type: 'post',
text: 'look at NYC',
user_id: 'user123',
feeds: ['user:user123'],
attachments: [attachment]
)
response = client.feeds.add_activity(activity_request)
# Video activity
video_attachment = GetStream::Generated::Models::Attachment.new(
asset_url: 'https://example.com/amazing-video.mp4',
type: 'video',
title: 'Amazing Video',
custom: { duration: 120 }
)
video_request = GetStream::Generated::Models::AddActivityRequest.new(
type: 'video',
text: 'Check out this amazing video!',
user_id: 'user123',
feeds: ['user:user123'],
attachments: [video_attachment],
custom: {
video_quality: '4K',
duration_seconds: 120
}
)
response = client.feeds.add_activity(video_request)
Overview of All Activity Fields
Here’s an overview of all the fields you can add when creating an activity:
Field | Description |
---|---|
id | Either set your own id, or let our server generate it. Setting your own ID can be convenient if your activity maps 1 to 1 to something in your database. |
type | The type of activity. Defaults to “post” if not provided. |
feeds | The list of feeds (format: “group id:feed id”) to add this activity to |
text | The text for this activity |
attachments | A list of attachments. Video, images, location, etc. Also supports custom attachments |
custom | Any custom data you want to add |
visibility | Visibility levels for the activity |
location | Specify an activity location. This allows for feeds to show content close to you. Format: ActivityLocation(lat: 40.014984, lng: -105.270546) |
expiresAt | When the activity expires. After this timestamp it’s only visible to the person who created this activity (or server side API calls) |
mentionedUserIds | A list of users mentioned in this activity |
parentId | The parent activity. Used for replies/reshares etc |
searchData | Any extra data you want to search on for this activity |
filterTags | Array of strings that you can filter on when querying the feed |
interestTags | Either set the interest tags manually or enable an activity processor to have AI determine the topics for this activity. Used for “for you” style feeds |
Adding Many Activities
You can also batch add activities. Here’s an example:
let activities = [
ActivityRequest(
feeds: ["user:123"],
id: "1",
text: "hi",
type: "post"
),
ActivityRequest(
feeds: ["user:456"],
id: "2",
text: "hi",
type: "post"
)
]
let upsertedActivities = try await client.upsertActivities(activities)
val activities = listOf(
ActivityRequest(
feeds = listOf("user:123"),
id = "1",
text = "hi",
type = "post"
),
ActivityRequest(
feeds = listOf("user:456"),
id = "2",
text = "hi",
type = "post"
)
)
val upsertedActivities: Result<List<ActivityData>> = client.upsertActivities(activities)
client.upsertActivities({
activities: [
{
feeds: ["user:123"],
id: "1",
type: "post",
text: "hi",
},
{
feeds: ["user:456"],
id: "2",
type: "post",
text: "hi",
},
],
});
client.feeds.upsertActivities({
activities: [
{
feeds: ["user:123"],
id: "1",
type: "post",
text: "hi",
user_id: "<user id>",
},
{
feeds: ["user:456"],
id: "2",
type: "post",
text: "hi",
user_id: "<user id>",
},
],
});
final activities = [
const ActivityRequest(
feeds: ['user:123'],
id: '1',
text: 'hi',
type: 'post',
),
const ActivityRequest(
feeds: ['user:456'],
id: '2',
text: 'hi',
type: 'post',
),
];
final upsertedActivities = await client.upsertActivities(
activities: activities,
);
activities := []getstream.ActivityRequest{
{
Type: "post",
Feeds: []string{"user:123"},
Text: getstream.PtrTo("Batch activity 1"),
UserID: getstream.PtrTo("john"),
},
{
Type: "post",
Feeds: []string{"user:456"},
Text: getstream.PtrTo("Batch activity 2"),
UserID: getstream.PtrTo("alice"),
},
}
response, err := client.Feeds().UpsertActivities(context.Background(), &getstream.UpsertActivitiesRequest{
Activities: activities,
})
List<ActivityRequest> activities =
List.of(
ActivityRequest.builder()
.type("post")
.text("Batch activity 1")
.userID(testUserId)
.build(),
ActivityRequest.builder()
.type("post")
.text("Batch activity 2")
.userID(testUserId)
.build());
UpsertActivitiesRequest request =
UpsertActivitiesRequest.builder().activities(activities).build();
UpsertActivitiesResponse response = feeds.upsertActivities(request).execute().getData();
$activities = [
[
'feeds' => ['user:123'],
'id' => '1',
'type' => 'post',
'text' => 'hi',
'user_id' => '<user id>',
],
[
'feeds' => ['user:456'],
'id' => '2',
'type' => 'post',
'text' => 'hi',
'user_id' => '<user id>',
]
];
$response = $feedsClient->upsertActivities(
new GeneratedModels\UpsertActivitiesRequest(activities: $activities)
);
var activities = new List<ActivityRequest>
{
new ActivityRequest
{
Type = "post",
Text = "Batch activity 1",
UserID = _testUserId
},
new ActivityRequest
{
Type = "post",
Text = "Batch activity 2",
UserID = _testUserId
}
};
var response = await _feedsV3Client.UpsertActivitiesAsync(
new UpsertActivitiesRequest { Activities = activities }
);
activities = [
ActivityRequest(
type="post",
text="Batch activity 1",
user_id=self.test_user_id,
feeds=[self.test_feed.get_feed_identifier()],
),
ActivityRequest(
type="post",
text="Batch activity 2",
user_id=self.test_user_id,
feeds=[self.test_feed.get_feed_identifier()],
),
]
response = self.client.feeds.upsert_activities(activities=activities)
activities = [
{
type: 'post',
text: 'Batch activity 1',
user_id: 'user123',
feeds: ['user:user123']
},
{
type: 'post',
text: 'Batch activity 2',
user_id: 'user123',
feeds: ['user:user123']
}
]
upsert_request = GetStream::Generated::Models::UpsertActivitiesRequest.new(
activities: activities
)
response = client.feeds.upsert_activities(upsert_request)
Updating & Deleting Activities
This example shows how to update or delete an activity:
// Update an activity
let updatedActivity = try await feed.updateActivity(
id: "123",
request: .init(
custom: ["custom": "custom"],
text: "Updated text"
)
)
// Delete an activity
let hardDelete = false // Soft delete sets deleted at but retains the data, hard delete fully removes it
try await feed.deleteActivity(id: "123", hardDelete: hardDelete)
// Batch delete activities
try await client.deleteActivities(
request: .init(
activityIds: ["123", "456"],
hardDelete: false
)
)
// Update an activity
val updatedActivity: Result<ActivityData> = feed.updateActivity(
id = "123",
request = UpdateActivityRequest(
custom = mapOf("custom" to "custom"),
text = "Updated text"
)
)
// Delete an activity
val hardDelete = false // Soft delete sets deleted at but retains the data, hard delete fully removes it
feed.deleteActivity(id = "123", hardDelete = hardDelete)
// Batch delete activities
client.deleteActivities(
request = DeleteActivitiesRequest(
ids = listOf("123", "456"),
hardDelete = false
)
)
// Update an activity
client.updateActivity({
id: "123",
text: "Updated text",
custom: {
color: "blue",
},
});
client.deleteActivity({
id: "123",
hard_delete: false, // Soft delete sets deleted at but retains the data, hard delete fully removes it
});
// Batch delete activities
client.deleteActivities({
id: ["123", "456"],
hard_delete: false,
});
// Update an activity
client.feeds.updateActivity({
id: "123",
text: "Updated text",
custom: {
color: "blue",
},
user_id: "<user id>",
});
client.feeds.deleteActivity({
id: "123",
hard_delete: false, // Soft delete sets deleted at but retains the data, hard delete fully removes it
user_id: "<user id>",
});
// Batch delete activities
client.feeds.deleteActivities({
id: ["123", "456"],
user_id: "<user id>",
hard_delete: false,
});
// Update an activity
final updatedActivity = await feed.updateActivity(
id: '123',
request: const UpdateActivityRequest(
text: 'Updated text',
custom: {'custom': 'custom'},
),
);
// Delete an activity
await feed.deleteActivity(
id: '123',
// Soft delete sets deleted at but retains the data, hard delete fully removes it
hardDelete: false,
);
// Batch delete activities
await client.deleteActivities(
ids: ['123', '456'],
hardDelete: false,
);
// Update an activity
updateRequest := &getstream.UpdateActivityRequest{
Text: stringPtr("Updated text"),
UserID: stringPtr("john"),
Custom: map[string]any{
"color": "blue",
},
}
updateResponse, err := client.Feeds().UpdateActivity(context.Background(), "123", updateRequest)
if err != nil {
log.Fatal("Error updating activity:", err)
}
log.Printf("Activity updated successfully: %+v", updateResponse)
// Delete a single activity (soft delete)
deleteRequest := &getstream.DeleteActivityRequest{
HardDelete: boolPtr(false), // Soft delete
}
deleteResponse, err := client.Feeds().DeleteActivity(context.Background(), "123", deleteRequest)
if err != nil {
log.Fatal("Error deleting activity:", err)
}
log.Printf("Activity deleted successfully: %+v", deleteResponse)
// Batch delete activities
batchDeleteRequest := &getstream.DeleteActivitiesRequest{
Ids: []string{"123", "456"},
UserID: stringPtr("john"),
HardDelete: boolPtr(false), // Soft delete
}
batchDeleteResponse, err := client.Feeds().DeleteActivities(context.Background(), batchDeleteRequest)
if err != nil {
log.Fatal("Error batch deleting activities:", err)
}
log.Printf("Activities batch deleted successfully: %+v", batchDeleteResponse)
Map<String, Object> customData = new HashMap<>();
customData.put("updated", true);
customData.put("update_time", System.currentTimeMillis() / 1000);
UpdateActivityRequest updateRequest =
UpdateActivityRequest.builder()
.text("Updated activity text from Java SDK")
.userID(testUserId) // Required for server-side auth
.custom(customData)
.build();
UpdateActivityResponse response =
feeds.updateActivity(activityId, updateRequest).execute().getData();
// Update an activity
$response = $feedsClient->updateActivity(
'123',
new GeneratedModels\UpdateActivityRequest(
text: 'Updated text',
userID: '<user id>',
custom: (object)[
'color' => 'blue'
]
)
);
// Delete an activity (soft delete sets deleted at but retains the data, hard delete fully removes it)
$response = $feedsClient->deleteActivity('123', false);
// Batch delete activities
$response = $feedsClient->deleteActivities(
new GeneratedModels\DeleteActivitiesRequest(
ids: ['123', '456'],
userID: '<user id>',
hardDelete: false
)
);
var response = await _feedsV3Client.UpdateActivityAsync(
activityId,
new UpdateActivityRequest
{
Text = "Updated activity text from .NET SDK",
UserID = _testUserId, // Required for server-side auth
Custom = new Dictionary<string, object>
{
["updated"] = true,
["update_time"] = DateTimeOffset.UtcNow.ToUnixTimeSeconds()
}
}
);
response = self.client.feeds.update_activity(
activity_id,
text="Updated activity text from Python SDK",
user_id=self.test_user_id, # Required for server-side auth
custom={"updated": True, "update_time": int(datetime.now().timestamp())},
)
# Update an activity
update_request = GetStream::Generated::Models::UpdateActivityRequest.new(
text: 'Updated activity text from Ruby SDK',
user_id: 'user123',
custom: {
updated: true,
update_time: Time.now.to_i
}
)
response = client.feeds.update_activity(activity_id, update_request)
# Delete an activity (soft delete)
delete_request = GetStream::Generated::Models::DeleteActivityRequest.new(
hard_delete: false # Soft delete sets deleted at but retains the data
)
response = client.feeds.delete_activity(activity_id, delete_request)
# Batch delete activities
batch_delete_request = GetStream::Generated::Models::DeleteActivitiesRequest.new(
activity_ids: ['123', '456'],
hard_delete: false
)
response = client.feeds.delete_activities(batch_delete_request)