MCPcopy Index your code
hub / github.com/GetStream/stream-go2

github.com/GetStream/stream-go2 @v8.9.0

Chat with this repo
repository ↗ · DeepWiki ↗ · release v8.9.0 ↗ · + Follow
536 symbols 1,725 edges 47 files 267 documented · 50%
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

Official Go SDK for Stream Feeds

<img src="https://github.com/GetStream/stream-go2/raw/v8.9.0/assets/logo.svg" width="50%" height="50%">






Official Go API client for Stream Feeds, a service for building applications with activity feeds.



<a href="https://getstream.io/activity-feeds/docs/"><strong>Explore the docs »</strong></a>






<a href="https://github.com/GetStream/stream-go2/issues">Report Bug</a>
·
<a href="https://github.com/GetStream/stream-go2/issues">Request Feature</a>

🚨 Breaking change in v7.0 <

From version 7.0.0, all methods' first argument is context.Context. The reason is that we internally changed http.NewRequest() to http.NewRequestWithContext() so that it's easier to handle cancellations, timeouts and deadlines for our users.

About Stream

stream-go2 is a Go client for Stream Feeds API.

You can sign up for a Stream account at our Get Started page.

You can use this library to access chat API endpoints server-side.

For the client-side integrations (web and mobile) have a look at the JavaScript, iOS and Android SDK libraries (docs).

💡 Note: this is a library for the Feeds product. The Chat SDKs can be found here.

build godoc Go Report Card

Contents

Installation

Get the client:

$ go get github.com/GetStream/stream-go2/v8

For v4, use github.com/GetStream/stream-go2/v4 but updating to the last version is highly recommended.

Creating a Client

import stream "github.com/GetStream/stream-go2/v8"

key := "YOUR_API_KEY"
secret := "YOUR_API_SECRET"

client, err := stream.New(key, secret)
if err != nil {
    // ...
}

You can pass additional options when creating a client using the available ClientOption functions:

client, err := stream.NewClient(key, secret,
    stream.WithAPIRegion("us-east"),
    stream.WithAPIVersion("1.0"),
    stream.WithTimeout(5 * time.Second),
    ...,
)

You can also create a client using environment variables:

client, err := stream.NewFromEnv()

Available environment variables:

  • STREAM_API_KEY
  • STREAM_API_SECRET
  • STREAM_API_REGION
  • STREAM_API_VERSION

Rate Limits

API has different rate limits for each distinct endpoint and this information is returned to the client in response headers and SDK parses headers into Rate type.

This info is provided to the user in 2 ways: * in responses; resp, _ := feed.GetActivities; resp.Rate. * in errors; if request doesn't succeed then error is a type of APIError and headers are accessible via err.(APIError).Rate.

Creating a Feed

Create a flat feed from slug and user ID:

flat, err := client.FlatFeed("user", "123")

Create an aggregated feed from slug and user ID:

aggr, err := client.AggregatedFeed("aggregated", "123")

Create a notification feed from slug and user ID:

notif, err := client.NotificationFeed("notification", "123")

Flat, aggregated, and notification feeds implement the Feed interface methods.

In the snippets below, feed indicates any kind of feed, while flat, aggregated, and notification are used to indicate that only that kind of feed has certain methods or can perform certain operations.

Retrieving activities

Flat feeds

resp, err := flat.GetActivities()
if err != nil {
    // ...
}

fmt.Println("Duration:", resp.Duration)
fmt.Println("Rate:", resp.Rate)
fmt.Println("Next:", resp.Next)
fmt.Println("Activities:")
for _, activity := range resp.Results {
    fmt.Println(activity)
}

You can retrieve flat feeds with custom ranking, using the dedicated method:

resp, err := flat.GetActivitiesWithRanking(ctx, "popularity")
if err != nil {
    // ...
}

Aggregated feeds

resp, err := aggregated.GetActivities(ctx)
if err != nil {
    // ...
}

fmt.Println("Duration:", resp.Duration)
fmt.Println("Rate:", resp.Rate)
fmt.Println("Next:", resp.Next)
fmt.Println("Groups:")
for _, group := range resp.Results {
    fmt.Println("Group:", group.Name, "ID:", group.ID, "Verb:", group.Verb)
    fmt.Println("Activities:", group.ActivityCount, "Actors:", group.ActorCount)
    for _, activity := range group.Activities {
        // ...
    }
}

Notification feeds

resp, err := notification.GetActivities(ctx)
if err != nil {
    // ...
}

fmt.Println("Duration:", resp.Duration)
fmt.Println("Rate:", resp.Rate)
fmt.Println("Next:", resp.Next)
fmt.Println("Unseen:", resp.Unseen, "Unread:", resp.Unread)
fmt.Println("Groups:")
for _, group := range resp.Results {
    fmt.Println("Group:", group.Group, "ID:", group.ID, "Verb:", group.Verb)
    fmt.Println("Seen:", group.IsSeen, "Read:", group.IsRead)
    fmt.Println("Activities:", group.ActivityCount, "Actors:", group.ActorCount)
    for _, activity := range group.Activities {
        // ...
    }
}

Options

You can pass supported options and filters when retrieving activities:

resp, err := flat.GetActivities(
    ctx,
    stream.WithActivitiesIDGTE("f505b3fb-a212-11e7-..."),
    stream.WithActivitiesLimit(5),
    ...,
)

Adding activities

Add a single activity:

resp, err := feed.AddActivity(ctx, stream.Activity{Actor: "bob", ...})
if err != nil {
    // ...
}

fmt.Println("Duration:", resp.Duration)
fmt.Println("Rate:", resp.Rate)
fmt.Println("Activity:", resp.Activity) // resp wraps the stream.Activity type

Add multiple activities:

a1 := stream.Activity{Actor: "bob", ...}
a2 := stream.Activity{Actor: "john", ...}
a3 := stream.Activity{Actor: "alice", ...}

resp, err := feed.AddActivities(ctx, a1, a2, a3)
if err != nil {
    // ...
}

fmt.Println("Duration:", resp.Duration)
fmt.Println("Rate:", resp.Rate)
fmt.Println("Activities:")
for _, activity := range resp.Activities {
    fmt.Println(activity)
}

Updating activities

_, err := feed.UpdateActivities(ctx, a1, a2, ...)
if err != nil {
    // ...
}

Partially updating activities

You can partial update activities identified either by ID:

changesetA := stream.NewUpdateActivityRequestByID("f505b3fb-a212-11e7-...", map[string]any{"key": "new-value"}, []string{"removed", "keys"})
changesetB := stream.NewUpdateActivityRequestByID("f707b3fb-a212-11e7-...", map[string]any{"key": "new-value"}, []string{"removed", "keys"})
resp, err := client.PartialUpdateActivities(ctx, changesetA, changesetB)
if err != nil {
    // ...
}

or by a ForeignID and timestamp pair:

changesetA := stream.NewUpdateActivityRequestByForeignID("dothings:1", stream.Time{...}, map[string]any{"key": "new-value"}, []string{"removed", "keys"})
changesetB := stream.NewUpdateActivityRequestByForeignID("dothings:2", stream.Time{...}, map[string]any{"key": "new-value"}, []string{"removed", "keys"})
resp, err := client.PartialUpdateActivities(ctx, changesetA, changesetB)
if err != nil {
    // ...
}

Removing activities

You can either remove activities by ID or ForeignID:

_, err := feed.RemoveActivityByID(ctx, "f505b3fb-a212-11e7-...")
if err != nil {
    // ...
}

_, err := feed.RemoveActivityByForeignID(ctx, "bob:123")
if err != nil {
    // ...
}

Following another feed

_, err := feed.Follow(ctx, anotherFeed)
if err != nil {
    // ...
}

Beware that it's possible to follow only flat feeds.

Options

You can pass options to the Follow method. For example:

_, err := feed.Follow(ctx,
    anotherFeed,
    stream.WithFollowFeedActivityCopyLimit(15),
    ...,
)

Retrieving followers and followings

Following

Get the feeds that a feed is following:

resp, err := feed.GetFollowing(ctx)
if err != nil {
    // ...
}

fmt.Println("Duration:", resp.Duration)
for _, followed := range resp.Results {
    fmt.Println(followed.FeedID, followed.TargetID)
}

You can pass options to GetFollowing:

resp, err := feed.GetFollowing(
    ctx,
    stream.WithFollowingLimit(5),
    ...,
)

Followers

resp, err := flat.GetFollowers(ctx)
if err != nil {
    // ...
}

fmt.Println("Duration:", resp.Duration)
fmt.Println("Rate:", resp.Rate)
for _, follower := range resp.Results {
    fmt.Println(follower.FeedID, follower.TargetID)
}

Note: this is only possible for FlatFeed types.

You can pass options to GetFollowers:

resp, err := feed.GetFollowing(
    ctx,
    stream.WithFollowersLimit(5),
    ...,
)

Unfollowing a feed

_, err := flat.Unfollow(ctx, anotherFeed)
if err != nil {
    // ...
}

You can pass options to Unfollow:

_, err := flat.Unfollow(ctx,
    anotherFeed,
    stream.WithUnfollowKeepHistory(true),
    ...,
)

Updating an activity's to targets

Remove all old targets and set new ones (replace):

newTargets := []stream.Feed{f1, f2}

_, err := feed.UpdateToTargets(ctx, activity, stream.WithToTargetsNew(newTargets...))
if err != nil {
    // ...
}

Add some targets and remove some others:

add := []stream.Feed{target1, target2}
remove := []stream.Feed{oldTarget1, oldTarget2}

_, err := feed.UpdateToTargets(
    ctx,
    activity,
    stream.WithToTargetsAdd(add),
    stream.WithToTargetsRemove(remove),
)
if err != nil {
    // ...
}

Note: you can't mix stream.WithToTargetsNew with stream.WithToTargetsAdd or stream.WithToTargetsRemove.

Batch adding activities

You can add the same activities to multiple feeds at once with the (*Client).AddToMany method (docs):

_, err := client.AddToMany(ctx,
    activity, feed1, feed2, ...,
)
if err != nil {
    // ...
}

Batch creating follows

You can create multiple follow relationships at once with the (*Client).FollowMany method (docs):

relationships := []stream.FollowRelationship{
    stream.NewFollowRelationship(source, target),
    ...,
}

_, err := client.FollowMany(ctx, relationships)
if err != nil {
    // ...
}

Realtime tokens

You can get a token suitable for client-side real-time feed updates as:

// Read+Write token
token := feed.RealtimeToken(false)

// Read-only token
readonlyToken := feed.RealtimeToken(true)

Analytics

If your app is enabled for analytics collection you can use the Go client to track events. The main documentation for the analytics features is available in our Docs page.

Obtaining an Analytics client

You can obtain a specialized Analytics client (*stream.AnalyticsClient) from a regular client, which you can use to track events:

// Create the client
analytics := client.Analytics()

Tracking engagement

Engagement events can be tracked with the TrackEngagement method of AnalyticsClient. It accepts any number of EngagementEvents.

Events' syntax is not checked by the client, so be sure to follow our documentation about it.

Events are simple maps, but the stream package offers handy helpers to populate such events easily.

// Create the event
event := stream.EngagementEvent{}.
    WithLabel("click").
    WithForeignID("event:1234").
    WithUserData(stream.NewUserData().String("john")).
    WithFeatures(
        stream.NewEventFeature("color", "blue"),
        stream.NewEventFeature("shape", "rectangle"),
    ).
    WithLocation("homepage")

// Track the event(s)
_, err := analytics.TrackEngagement(ctx, event)
if err != nil {
    // ...
}

Tracking impressions

Impression events can be tracked with the TrackImpression method of AnalyticsClient (syntax docs):

```go // Create the impression events imp := stream.ImpressionEventData{}. WithF

Extension points exported contracts — how you extend this code

Requester (Interface)
Requester performs HTTP requests. [2 implementers]
client.go
Feed (Interface)
Feed is a generic Stream feed, exporting the generic functions common to any Stream feed. [1 implementers]
feed.go
FollowFeedOption (FuncType)
FollowFeedOption is a function used to customize FollowFeed API calls.
options.go
FollowRelationshipOption (FuncType)
FollowRelationshipOption customizes a FollowRelationship.
types.go
ClientOption (FuncType)
ClientOption is a function used for adding specific configuration options to a Stream client.
client.go
UpdateToTargetsOption (FuncType)
UpdateToTargetsOption determines what operations perform during an UpdateToTargets API call.
options.go
UnfollowRelationshipOption (FuncType)
UnfollowRelationshipOption customizes an UnfollowRelationship.
types.go
AddObjectOption (FuncType)
AddObjectOption is an option usable by the Collections.Add method.
options.go

Core symbols most depended-on inside this repo

makeRequestOption
called by 69
options.go
makeEndpoint
called by 52
client.go
Error
called by 47
errors.go
addQueryParam
called by 36
client.go
Get
called by 33
users.go
Reactions
called by 22
client.go
feedAuth
called by 21
authenticator.go
post
called by 21
client.go

Shape

Method 214
Function 195
Struct 110
FuncType 8
Interface 5
TypeAlias 4

Languages

Go100%

Modules by API surface

types.go81 symbols
options.go81 symbols
client.go67 symbols
feed.go30 symbols
analytics_types.go28 symbols
moderation.go17 symbols
authenticator.go17 symbols
url.go16 symbols
feed_test.go14 symbols
client_test.go14 symbols
reactions_test.go12 symbols
reactions.go12 symbols

For agents

$ claude mcp add stream-go2 \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact