{"id":27261549,"url":"https://github.com/getstream/stream-js","last_synced_at":"2026-02-11T11:04:02.035Z","repository":{"id":38859036,"uuid":"21035996","full_name":"GetStream/stream-js","owner":"GetStream","description":"JS / Browser Client - Build Activity Feeds \u0026 Streams with GetStream.io","archived":false,"fork":false,"pushed_at":"2025-04-10T11:25:15.000Z","size":7346,"stargazers_count":331,"open_issues_count":44,"forks_count":114,"subscribers_count":41,"default_branch":"main","last_synced_at":"2025-05-12T16:13:33.377Z","etag":null,"topics":["activity-feed","feed","getstream","javascript","news-feed","notification-feed","stream-js","timeline"],"latest_commit_sha":null,"homepage":"https://getstream.io","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/GetStream.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2014-06-20T11:42:33.000Z","updated_at":"2025-04-10T11:24:41.000Z","dependencies_parsed_at":"2023-12-21T19:29:24.143Z","dependency_job_id":"23271875-35b6-417c-9b47-f3c9ef522980","html_url":"https://github.com/GetStream/stream-js","commit_stats":{"total_commits":1355,"total_committers":48,"mean_commits":"28.229166666666668","dds":0.8287822878228782,"last_synced_commit":"281f36bd61fc3db188f291dc18119a1d8c18302c"},"previous_names":["tschellenbach/stream-js"],"tags_count":201,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GetStream%2Fstream-js","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GetStream%2Fstream-js/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GetStream%2Fstream-js/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GetStream%2Fstream-js/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/GetStream","download_url":"https://codeload.github.com/GetStream/stream-js/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254140772,"owners_count":22021221,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["activity-feed","feed","getstream","javascript","news-feed","notification-feed","stream-js","timeline"],"created_at":"2025-04-11T05:34:53.539Z","updated_at":"2026-02-11T11:04:02.021Z","avatar_url":"https://github.com/GetStream.png","language":"JavaScript","readme":"# Official JavaScript SDK for [Stream Feeds](https://getstream.io/activity-feeds/)\n\n[![build](https://github.com/GetStream/stream-js/workflows/build/badge.svg)](https://github.com/GetStream/stream-js/actions)\n[![NPM](https://nodei.co/npm/getstream.png)](https://nodei.co/npm/getstream/)\n\n\u003cp align=\"center\"\u003e\n    \u003cimg src=\"./assets/logo.svg\" width=\"50%\" height=\"50%\"\u003e\n\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n    Official JavaScript API client for Stream Feeds, a web service for building scalable newsfeeds and activity streams.\n    \u003cbr /\u003e\n    \u003ca href=\"https://getstream.io/activity-feeds/docs/?language=javascript\"\u003e\u003cstrong\u003eExplore the docs »\u003c/strong\u003e\u003c/a\u003e\n    \u003cbr /\u003e\n    \u003cbr /\u003e\n    \u003ca href=\"https://github.com/GetStream/stream-js/issues\"\u003eReport Bug\u003c/a\u003e\n    ·\n    \u003ca href=\"https://github.com/GetStream/stream-js/issues\"\u003eRequest Feature\u003c/a\u003e\n\u003c/p\u003e\n\n## 📝 About Stream\n\n[stream-js](https://github.com/GetStream/stream-js) is the official JavaScript client for [Stream](https://getstream.io/), a web service for building scalable newsfeeds and activity streams.\n\nNote that there is also a [higher level Node integration](https://github.com/getstream/stream-node-orm) which hooks into your ORM.\n\nYou can sign up for a Stream account at https://getstream.io/get_started.\n\n\u003e 💡 Note: this is a library for the **Feeds** product. The Chat SDKs can be found [here](https://getstream.io/chat/docs/).\n\n## ⚙️ Installation\n\n### Install from NPM/YARN\n\n```bash\nnpm install getstream\n```\n\nor if you are using yarn\n\n```bash\nyarn add getstream\n```\n\n### Using JS deliver\n\n```html\n\u003cscript src=\"https://cdn.jsdelivr.net/npm/getstream/dist/js_min/getstream.js\"\u003e\u003c/script\u003e\n```\n\n\u003e :warning: This will pull the latest which can be breaking for your application. Always pin a specific version as follows:\n\n```html\n\u003cscript src=\"https://cdn.jsdelivr.net/npm/getstream@8.0.0/dist/js_min/getstream.js\"\u003e\u003c/script\u003e\n```\n\n### Install by downloading the JS file\n\n[JS](https://raw.githubusercontent.com/GetStream/stream-js/main/dist/js/getstream.js) /\n[Minified JS](https://raw.githubusercontent.com/GetStream/stream-js/main/dist/js_min/getstream.js)\n\n\u003e :warning: Beware about the version you're pulling. It's the latest by default which can break your app anytime.\n\n## 📚 Full documentation\n\nDocumentation for this JavaScript client are available at the [Stream website](https://getstream.io/docs/?language=js).\n\n#### Using with React Native\n\nThis package can be integrated into React Native applications. Remember to not expose the App Secret in browsers, \"native\" mobile apps, or other non-trusted environments.\n\n## ✨ Getting started\n\n### API client setup Node\n\n```js\nimport { connect } from 'getstream';\n// or if you are on commonjs\nconst { connect } = require('getstream');\n\n// Instantiate a new client (server side)\nconst client = connect('YOUR_API_KEY', 'API_KEY_SECRET');\n// Optionally supply the app identifier and an options object specifying the data center to use and timeout for requests (15s)\nconst client = connect('YOUR_API_KEY', 'API_KEY_SECRET', 'APP_ID', { location: 'us-east', timeout: 15000 });\n```\n\n### API client setup Node + Browser\n\nIf you want to use the API client directly on your web/mobile app you need to generate a user token server-side and pass it.\n\n#### Server-side token generation\n\n```js\nimport { connect } from 'getstream';\n// or if you are on commonjs\nconst { connect } = require('getstream');\n\n// Instantiate a new client (server side)\nconst client = connect('YOUR_API_KEY', 'API_KEY_SECRET');\n// Optionally supply the app identifier and an options object specifying the data center to use and timeout for requests (15s)\nconst client = connect('YOUR_API_KEY', 'API_KEY_SECRET', 'APP_ID', { location: 'us-east', timeout: 15000 });\n// Create a token for user with id \"the-user-id\"\nconst userToken = client.createUserToken('the-user-id');\n```\n\n\u003e :warning: Client checks if it's running in a browser environment with a secret and throws an error for a possible security issue of exposing your secret. If you are running backend code in Google Cloud or you know what you're doing, you can specify `browser: false` in `options` to skip this check.\n\n```js\nconst client = connect('YOUR_API_KEY', 'API_KEY_SECRET', 'APP_ID', { browser: false });\n```\n\n#### Client API init\n\n```js\nimport { connect } from 'getstream';\n// or if you are on commonjs\nconst { connect } = require('getstream');\n// Instantiate new client with a user token\nconst client = connect('apikey', userToken, 'appid');\n```\n\n#### Examples\n\n```js\n// Instantiate a feed object server side\nuser1 = client.feed('user', '1');\n\n// Get activities from 5 to 10 (slow pagination)\nuser1.get({ limit: 5, offset: 5 });\n// Filter on an id less than a given UUID\nuser1.get({ limit: 5, id_lt: 'e561de8f-00f1-11e4-b400-0cc47a024be0' });\n\n// All API calls are performed asynchronous and return a Promise object\nuser1\n  .get({ limit: 5, id_lt: 'e561de8f-00f1-11e4-b400-0cc47a024be0' })\n  .then(function (body) {\n    /* on success */\n  })\n  .catch(function (reason) {\n    /* on failure, reason.error contains an explanation */\n  });\n\n// Create a new activity\nactivity = { actor: 1, verb: 'tweet', object: 1, foreign_id: 'tweet:1' };\nuser1.addActivity(activity);\n// Create a bit more complex activity\nactivity = {\n  actor: 1,\n  verb: 'run',\n  object: 1,\n  foreign_id: 'run:1',\n  course: { name: 'Golden Gate park', distance: 10 },\n  participants: ['Thierry', 'Tommaso'],\n  started_at: new Date(),\n};\nuser1.addActivity(activity);\n\n// Remove an activity by its id\nuser1.removeActivity('e561de8f-00f1-11e4-b400-0cc47a024be0');\n// or remove by the foreign id\nuser1.removeActivity({ foreign_id: 'tweet:1' });\n\n// mark a notification feed as read\nnotification1 = client.feed('notification', '1');\nparams = { mark_read: true };\nnotification1.get(params);\n\n// mark a notification feed as seen\nparams = { mark_seen: true };\nnotification1.get(params);\n\n// Follow another feed\nuser1.follow('flat', '42');\n\n// Stop following another feed\nuser1.unfollow('flat', '42');\n\n// Stop following another feed while keeping previously published activities\n// from that feed\nuser1.unfollow('flat', '42', { keepHistory: true });\n\n// Follow another feed without copying the history\nuser1.follow('flat', '42', { limit: 0 });\n\n// List followers, following\nuser1.followers({ limit: '10', offset: '10' });\nuser1.following({ limit: '10', offset: '0' });\n\nuser1.follow('flat', '42');\n\n// adding multiple activities\nactivities = [\n  { actor: 1, verb: 'tweet', object: 1 },\n  { actor: 2, verb: 'tweet', object: 3 },\n];\nuser1.addActivities(activities);\n\n// specifying additional feeds to push the activity to using the to param\n// especially useful for notification style feeds\nto = ['user:2', 'user:3'];\nactivity = {\n  to: to,\n  actor: 1,\n  verb: 'tweet',\n  object: 1,\n  foreign_id: 'tweet:1',\n};\nuser1.addActivity(activity);\n\n// adding one activity to multiple feeds\nfeeds = ['flat:1', 'flat:2', 'flat:3', 'flat:4'];\nactivity = {\n  actor: 'User:2',\n  verb: 'pin',\n  object: 'Place:42',\n  target: 'Board:1',\n};\n\n// ⚠️ server-side only!\nclient.addToMany(activity, feeds);\n\n// Batch create follow relations (let flat:1 follow user:1, user:2 and user:3 feeds in one single request)\nfollows = [\n  { source: 'flat:1', target: 'user:1' },\n  { source: 'flat:1', target: 'user:2' },\n  { source: 'flat:1', target: 'user:3' },\n];\n\n// ⚠️ server-side only!\nclient.followMany(follows);\n\n// Updating parts of an activity\nset = {\n  'product.price': 19.99,\n  shares: {\n    facebook: '...',\n    twitter: '...',\n  },\n};\nunset = ['daily_likes', 'popularity'];\n// ...by ID\nclient.activityPartialUpdate({\n  id: '54a60c1e-4ee3-494b-a1e3-50c06acb5ed4',\n  set: set,\n  unset: unset,\n});\n// ...or by combination of foreign ID and time\nclient.activityPartialUpdate({\n  foreign_id: 'product:123',\n  time: '2016-11-10T13:20:00.000000',\n  set: set,\n  unset: unset,\n});\n\n// ⚠️ server-side only!\n// Create redirect urls\nimpression = {\n  content_list: ['tweet:1', 'tweet:2', 'tweet:3'],\n  user_data: 'tommaso',\n  location: 'email',\n  feed_id: 'user:global',\n};\nengagement = {\n  content: 'tweet:2',\n  label: 'click',\n  position: 1,\n  user_data: 'tommaso',\n  location: 'email',\n  feed_id: 'user:global',\n};\nevents = [impression, engagement];\nredirectUrl = client.createRedirectUrl('http://google.com', 'user_id', events);\n\n// update the 'to' fields on an existing activity\n// client.feed(\"user\", \"ken\").function (foreign_id, timestamp, new_targets, added_targets, removed_targets)\n// new_targets, added_targets, and removed_targets are all arrays of feed IDs\n// either provide only the `new_targets` parameter (will replace all targets on the activity),\n// OR provide the added_targets and removed_targets parameters\n// NOTE - the updateActivityToTargets method is not intended to be used in a browser environment.\nclient.feed('user', 'ken').updateActivityToTargets('foreign_id:1234', timestamp, ['feed:1234']);\nclient.feed('user', 'ken').updateActivityToTargets('foreign_id:1234', timestamp, null, ['feed:1234']);\nclient.feed('user', 'ken').updateActivityToTargets('foreign_id:1234', timestamp, null, null, ['feed:1234']);\n\n// Flag a user for moderation\nclient.flagUser('suspicious-user-123', { reason: 'spam' });\nclient.flagUser('bad-actor-456', { reason: 'inappropriate_content' });\n\n// Or using the user object method\nconst user = client.user('suspicious-user-123');\nuser.flag({ reason: 'spam' });\nuser.flag({ reason: 'inappropriate_content' });\n```\n\n### Typescript\n\n```ts\nimport { connect, UR, EnrichedActivity, NotificationActivity } from 'getstream';\n\ntype User1Type = { name: string; username: string; image?: string };\ntype User2Type = { name: string; avatar?: string };\ntype ActivityType = { attachments: string[]; text: string };\ntype Collection1Type = { cid: string; rating?: number };\ntype Collection2Type = { branch: number; location: string };\n\ntype ReactionType = { text: string };\ntype ChildReactionType = { text?: string };\n\ntype StreamType = {\n  userType: User1Type | User2Type,\n  activityType: ActivityType,\n  collectionType: Collection1Type | Collection2Type,\n  reactionType: ReactionType,\n  childReactionType: ChildReactionType,\n  personalizationType: UR,\n}\n\nconst client = connect\u003cStreamType\u003e('api_key', 'secret!', 'app_id');\n\n// if you have different union types like \"User1Type | User2Type\" you can use type guards as follow:\n// https://www.typescriptlang.org/docs/handbook/advanced-types.html#type-guards-and-differentiating-types\nfunction isUser1Type(user: User1Type | User2Type): user is User1Type {\n  return (user as User1Type).username !== undefined;\n}\n\nclient\n  .user('user_id')\n  .get()\n  .then((user) =\u003e {\n    const { data, id } = user;\n    if (isUser1Type(data)) return data.username;\n    return id;\n  });\n\n// notification: StreamFeed\u003cStreamType\u003e\nconst timeline = client.feed('timeline', 'feed_id');\ntimeline.get({ withOwnChildren: true, withOwnReactions: true }).then((response) =\u003e {\n  // response: FeedAPIResponse\u003cStreamType\u003e\n  if (response.next !== '') return response.next;\n\n  return (response.results as EnrichedActivity\u003cStreamType\u003e[]).map((activity) =\u003e {\n    return activity.id + activity.text + (activity.actor as User2Type).name;\n  });\n});\n\n// notification: StreamFeed\u003cStreamType\u003e\nconst notification = client.feed('notification', 'feed_id');\nnotification.get({ mark_read: true, mark_seen: true }).then((response) =\u003e {\n  // response: FeedAPIResponse\u003cStreamType\u003e\n  if (response.unread || response.unseen) return response.next;\n\n  return (response.results as NotificationActivity\u003cActivityType\u003e[]).map((activityGroup) =\u003e {\n    const { activities, id, verb, activity_count, actor_count } = activityGroup;\n    return activities[0].text + id + actor_count + activity_count + verb;\n  });\n});\n\nclient.collections.get('collection_1', 'taco').then((item: CollectionEntry\u003cStreamType\u003e) =\u003e {\n  if (item.data.rating) return { [item.data.cid]: item.data.rating };\n  return item.id;\n});\n```\n\n### Realtime (Faye)\n\nStream uses [Faye](http://faye.jcoglan.com/browser.html) for realtime notifications. Below is quick guide to subscribing to feed changes\n\n```js\nconst { connect } = require('getstream');\n\n// ⚠️ userToken is generated server-side (see previous section)\nconst client = connect('YOUR_API_KEY', userToken, 'APP_ID');\nconst user1 = client.feed('user', '1');\n\n// subscribe to the changes\nconst subscription = user1.subscribe(function (data) {\n  console.log(data);\n});\n// now whenever something changes to the feed user 1\n// the callback will be called\n\n// To cancel a subscription you can call cancel on the\n// object returned from a subscribe call.\n// This will remove the listener from this channel.\nsubscription.cancel();\n```\n\nDocs are available on [GetStream.io](http://getstream.io/docs/?language=js).\n\n## ⚠️ Node version requirements \u0026 Browser support\n\nThis API Client project requires Node.js v16 at a minimum.\n\nThe project is supported in line with the Node.js Foundation Release Working Group.\n\nSee the [github action configuration](.github/workflows/) for details of how it is built, tested and packaged.\n\n## ♻️ Contributing\n\nSee extensive at [test documentation](test/README.md) for your changes.\n\nYou can find generic API documentation enriched by code snippets from this package at http://getstream.io/docs/?language=js\n\n### Copyright and License Information\n\nProject is licensed under the [BSD 3-Clause](LICENSE).\n\nWe welcome code changes that improve this library or fix a problem, please make sure to follow all best practices and add tests if applicable before submitting a Pull Request on Github. We are very happy to merge your code in the official repository. Make sure to sign our [Contributor License Agreement (CLA)](https://docs.google.com/forms/d/e/1FAIpQLScFKsKkAJI7mhCr7K9rEIOpqIDThrWxuvxnwUq2XkHyG154vQ/viewform) first. See our [license file](./LICENSE) for more details.\n\n## 🧑‍💻 We are hiring!\n\nWe've recently closed a [$38 million Series B funding round](https://techcrunch.com/2021/03/04/stream-raises-38m-as-its-chat-and-activity-feed-apis-power-communications-for-1b-users/) and we keep actively growing.\nOur APIs are used by more than a billion end-users, and you'll have a chance to make a huge impact on the product within a team of the strongest engineers all over the world.\n\nCheck out our current openings and apply via [Stream's website](https://getstream.io/team/#jobs).\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgetstream%2Fstream-js","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgetstream%2Fstream-js","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgetstream%2Fstream-js/lists"}