# Feeds

## Creating a Feed

<Admonition type="info">

When using server-side SDKs, the `user_id` parameter is required in the `getOrCreate` request. It's needed in order to automatically create a user. Client-side SDKs do not require this parameter as the user is authenticated via token.

</Admonition>

<Tabs>

```js label="React"
// Feed with no extra fields, of feed group "user"
const feed = client.feed("user", "jack");
await feed.getOrCreate();
// Subscribe to WebSocket events for state updates
await feed.getOrCreate({ watch: true });

// More options
const feed = client.feed("user", "jack");
await feed.getOrCreate({
  data: {
    description: "My personal feed",
    name: "jack",
    visibility: "public",
    filter_tags: ["tech", "hiking", "cooking"],
  },
});
```

```js label="JavaScript"
// Feed with no extra fields, of feed group "user"
const feed = client.feed("user", "jack");
await feed.getOrCreate();
// Subscribe to WebSocket events for state updates
await feed.getOrCreate({ watch: true });

// More options
const feed = client.feed("user", "jack");
await feed.getOrCreate({
  data: {
    description: "My personal feed",
    name: "jack",
    visibility: "public",
    filter_tags: ["tech", "hiking", "cooking"],
  },
});
```

</Tabs>

## Built-in feed groups

| Group          | Description                                                                                                                    |
| -------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| `user`         | A feed setup for the content a user creates. Typically you add activities here when someone writes a post                      |
| `timeline`     | The timeline feed is used when you're following. So if user Charlie is following John, timeline:charlie would follow user:john |
| `foryou`       | A version of the timeline feed that adds popular content, and prioritizes popularity over recency                              |
| `notification` | A notification feed. Think of the bell icon you see in most apps                                                               |
| `story`        | A feed set up for users to post story activities (activities with expiration data)                                             |
| `stories`      | A timeline feed which can be used to follow other users' stories.                                                              |

## Reading a Feed

For high-traffic feeds many users read the same way, prefer server-side reads from your backend. If Stream has enabled [hot feed cache](https://getstream.io/activity-feeds/docs/node/hot-feed-cache/) for a feed, reads must be server-side for the cache to apply.

Here is a basic example of how to read a feed:

<Tabs>

```js label="React"
import { useCallback } from "react";

const feed = client.feed("user", "john");
await feed.getOrCreate({ watch: true });

const selector = useCallback((state: FeedState) => ({
  name: state.name,
  description: state.description,
  members: state.members,
}), []);

const { activities } = useFeedActivities(feed);
const { name, description, members } = useStateStore(feed.state, selector);
```

```js label="JavaScript"
const feed = client.feed("user", "john");
await feed.getOrCreate({ watch: true });
const currentState = feed.state.getLatestValue();

const visivility = currentState.visibility;
const name = currentState.name;
const description = currentState.description;
const activities = currentState.activities;
const members = currentState.members;

// Or subscribe to state changes
const unsubscribe = feed.state.subscribe((state) => {
  // Called everytime the state changes
  console.log(state);
});

// or if you care only part of the state
const unsubscribe2 = feed.state.subscribeWithSelector(
  (state) => ({
    activities: state.activities,
  }),
  (state, prevState) => {
    console.log(state.activities, prevState?.activities);
  },
);

// Unsubscribe when you no longer want to recieve updates
unsubscribe();
unsubscribe2();
```

</Tabs>

The response will contain the following data.

You have more options when reading a feed, let's go over a few:

<Tabs>

```js label="React"
const feed = client.feed("user", "jack");
const response = await feed.getOrCreate({
  limit: 10,
  filter: {
    filter_tags: ["green"], // filter activities with filter tag green
  },
  external_ranking: {
    user_score: 0.8, // additional data used for ranking
  },
  followers_pagination: {
    limit: 10,
  },
  following_pagination: {
    limit: 10,
  },
  member_pagination: {
    limit: 10,
  },
  view: "myview", // overwrite the default ranking or aggregation logic for this feed. good for split testing
});
```

```js label="JavaScript"
const feed = client.feed("user", "jack");
const response = await feed.getOrCreate({
  limit: 10,
  filter: {
    filter_tags: ["green"], // filter activities with filter tag green
  },
  external_ranking: {
    user_score: 0.8, // additional data used for ranking
  },
  followers_pagination: {
    limit: 10,
  },
  following_pagination: {
    limit: 10,
  },
  member_pagination: {
    limit: 10,
  },
  view: "myview", // overwrite the default ranking or aggregation logic for this feed. good for split testing
});
```

</Tabs>

## Enrichment Options

You can control how activities are enriched when reading a feed by providing `enrichment_options` to the `getOrCreate` request. This allows you to customize which fields and related data are included in the response.

<h3 id="EnrichmentOptions"><a href="#EnrichmentOptions">EnrichmentOptions</a></h3><table><thead><tr><th>Name</th><th>Type</th><th>Description</th><th>Constraints</th></tr></thead><tbody><tr><td><code>enrich_own_followings</code></td><td><code>boolean</code></td><td>Default: false. When true, includes fetching and enriching own_followings (follows where activity author&#39;s feeds follow current user&#39;s feeds).</td><td>-</td></tr><tr><td><code>include_score_vars</code></td><td><code>boolean</code></td><td>Default: false. When true, includes score_vars in activity responses containing variable values used at ranking time.</td><td>-</td></tr><tr><td><code>skip_activity</code></td><td><code>boolean</code></td><td>Default: false. When true, skips all activity enrichments.</td><td>-</td></tr><tr><td><code>skip_activity_collections</code></td><td><code>boolean</code></td><td>Default: false. When true, skips enriching collections on activities.</td><td>-</td></tr><tr><td><code>skip_activity_comments</code></td><td><code>boolean</code></td><td>Default: false. When true, skips enriching comments on activities.</td><td>-</td></tr><tr><td><code>skip_activity_current_feed</code></td><td><code>boolean</code></td><td>Default: false. When true, skips enriching current_feed on activities. Note: CurrentFeed is still computed for permission checks, but enrichment is skipped.</td><td>-</td></tr><tr><td><code>skip_activity_mentioned_users</code></td><td><code>boolean</code></td><td>Default: false. When true, skips enriching mentioned users on activities.</td><td>-</td></tr><tr><td><code>skip_activity_own_bookmarks</code></td><td><code>boolean</code></td><td>Default: false. When true, skips enriching own bookmarks on activities.</td><td>-</td></tr><tr><td><code>skip_activity_parents</code></td><td><code>boolean</code></td><td>Default: false. When true, skips enriching parent activities.</td><td>-</td></tr><tr><td><code>skip_activity_poll</code></td><td><code>boolean</code></td><td>Default: false. When true, skips enriching poll data on activities.</td><td>-</td></tr><tr><td><code>skip_activity_reactions</code></td><td><code>boolean</code></td><td>Default: false. When true, skips fetching and enriching latest and own reactions on activities. Note: If reactions are already denormalized in the database, they will still be included.</td><td>-</td></tr><tr><td><code>skip_activity_refresh_image_urls</code></td><td><code>boolean</code></td><td>Default: false. When true, skips refreshing image URLs on activities.</td><td>-</td></tr><tr><td><code>skip_all</code></td><td><code>boolean</code></td><td>Default: false. When true, skips all enrichments.</td><td>-</td></tr><tr><td><code>skip_feed_member_user</code></td><td><code>boolean</code></td><td>Default: false. When true, skips enriching user data on feed members.</td><td>-</td></tr><tr><td><code>skip_followers</code></td><td><code>boolean</code></td><td>Default: false. When true, skips fetching and enriching followers. Note: If followers_pagination is explicitly provided, followers will be fetched regardless of this setting.</td><td>-</td></tr><tr><td><code>skip_following</code></td><td><code>boolean</code></td><td>Default: false. When true, skips fetching and enriching following. Note: If following_pagination is explicitly provided, following will be fetched regardless of this setting.</td><td>-</td></tr><tr><td><code>skip_own_capabilities</code></td><td><code>boolean</code></td><td>Default: false. When true, skips computing and including capabilities for feeds.</td><td>-</td></tr><tr><td><code>skip_own_follows</code></td><td><code>boolean</code></td><td>Default: false. When true, skips fetching and enriching own_follows (follows where user&#39;s feeds follow target feeds).</td><td>-</td></tr><tr><td><code>skip_pins</code></td><td><code>boolean</code></td><td>Default: false. When true, skips enriching pinned activities.</td><td>-</td></tr></tbody></table>

<Admonition type="info">

**Performance Optimization**: Enrichment options allow you to skip specific enrichments to improve performance.

**Important Notes**:

- **Reactions**: If `skip_activity_reactions` is set to `true`, the expensive enrichment step is skipped. However, if reactions are already denormalized in the database, they will still be included in the response. This option only skips the expensive enrichment step but does not remove already-loaded data for performance reasons.

- **Followers/Following**: If `skip_followers` or `skip_following` is set to `true`, fetching and enriching followers or following is skipped. However, if `followers_pagination` or `following_pagination` is explicitly provided in the request, followers or following will be fetched regardless of this setting. This ensures that explicit pagination requests are always honored.

</Admonition>

### Example

<Tabs>

```js label="React"
const feed = client.feed("user", "jack");
const response = await feed.getOrCreate({
  enrichment_options: {
    // Configure enrichment options here
  },
});
```

```js label="JavaScript"
const feed = client.feed("user", "jack");
const response = await feed.getOrCreate({
  enrichment_options: {
    // Configure enrichment options here
  },
});
```

</Tabs>

## Feed Pagination

Here is how you can read the next page on the feed:

<Tabs>

```js label="React"
const feed = client.feed("user", "jack");

// First page
await feed.getOrCreate({
  limit: 10,
});

const { activities, loadNextPage, is_loading, has_next_page } =
  useFeedActivities(feed) ?? {};
// Only if feed group has aggregation turned on
const { aggregated_activities, is_loading, has_next_page } =
  useAggregatedActivities(feed) ?? {};
```

```js label="JavaScript"
const feed = client.feed("user", "jack");

// First page
await feed.getOrCreate({
  limit: 10,
});

// Second page
await feed.getNextPage();

console.log(feed.state.getLatestValue().is_loading_activities);
// Truthy if feed has next page
console.log(feed.state.getLatestValue().next);
console.log(feed.state.getLatestValue().activities);
// Only if feed group has aggregation turned on
console.log(feed.state.getLatestValue().aggregated_activities);
```

</Tabs>

When using `external_ranking` with [hot feed cache](https://getstream.io/activity-feeds/docs/node/hot-feed-cache/), pass the same `external_ranking` values on every page. Changing or dropping them mid-pagination discards the cached snapshot for that page. See [Pagination](https://getstream.io/activity-feeds/docs/node/hot-feed-cache/#pagination) and [External ranking](https://getstream.io/activity-feeds/docs/node/hot-feed-cache/#external-ranking).

## Filters

`filter` provides a performant way to read a feed, and only select activities that match a given filter.

<Admonition type="info">

Please note that filtering is typically used for fields with fixed value sets (for example `filter_tags`), for text based search, you should check out [query activities endpoint](https://getstream.io/activity-feeds/docs/react/query-activities/)

</Admonition>

### Examples

<Tabs>

```js label="React"
const feed = client.feed("user", "123");

// Add a few activities
client.upsertActivities({
  activities: [
    {
      feeds: [feed.feed],
      type: "post",
      text: "first",
      filter_tags: ["green", "blue"],
    },
    {
      feeds: [feed.feed],
      type: "post",
      text: "second",
      filter_tags: ["yellow", "blue"],
    },
    {
      feeds: [feed.feed],
      type: "post",
      text: "third",
      filter_tags: ["orange"],
    },
  ],
});

const response = await feed.getOrCreate({
  watch: true,
  filter: {
    filter_tags: ["blue"],
  },
});
```

```js label="JavaScript"
const feed = client.feed("user", "123");

// Add a few activities
client.upsertActivities({
  activities: [
    {
      feeds: [feed.feed],
      type: "post",
      text: "first",
      filter_tags: ["green", "blue"],
    },
    {
      feeds: [feed.feed],
      type: "post",
      text: "second",
      filter_tags: ["yellow", "blue"],
    },
    {
      feeds: [feed.feed],
      type: "post",
      text: "third",
      filter_tags: ["orange"],
    },
  ],
});

const response = await feed.getOrCreate({
  watch: true,
  filter: {
    filter_tags: ["blue"],
  },
});
```

</Tabs>

The filter syntax also supports `$or` and `$and`, so here's an example that's a little more complicated:

<Tabs>

```js label="React"
// Get all the activities where filter tags contain both "green" and "orange"
const response = await feed.getOrCreate({
  filter: {
    $and: [{ filter_tags: ["green"] }, { filter_tags: ["orange"] }],
  },
});
```

```js label="JavaScript"
// Get all the activities where filter tags contain both "green" and "orange"
const response = await feed.getOrCreate({
  filter: {
    $and: [{ filter_tags: ["green"] }, { filter_tags: ["orange"] }],
  },
});
```

</Tabs>

### Supported filters

What filters you can use when reading a feed depends on the feed group (or view, if provided) configuration.

The [activity selectors page](https://getstream.io/activity-feeds/docs/react/activity-selectors/) explains this in detail, but some quick examples: the `user` group uses `current` selector, and the `timeline` group the `following` selector by default.

The following `filter` options are available for the `following` selector:

| name          | type                      | description            | supported operations      | example                                                  |
| ------------- | ------------------------- | ---------------------- | ------------------------- | -------------------------------------------------------- |
| `id`          | string or list of strings | The ID of the activity | `$in`, `$eq`              | `{ id: { $in: [ 'abc', 'xyz' ] } }`                      |
| `filter_tags` | list of strings           | Tags for filtering     | `$eq`, `$contains`, `$in` | `{ filter_tags: { $in: [ 'categoryA', 'categoryB' ] } }` |

The following `filter` options are available for the `current`, `popular`, `interest`, `proximity` and `query` selectors:

| name            | type                                              | description                                                      | supported operations                       | example                                                                                      |
| --------------- | ------------------------------------------------- | ---------------------------------------------------------------- | ------------------------------------------ | -------------------------------------------------------------------------------------------- |
| `id`            | string or list of strings                         | The ID of the activity                                           | `$in`, `$eq`                               | `{ id: { $in: [ 'abc', 'xyz' ] } }`                                                          |
| `activity_type` | string or list of strings                         | The type of the activity                                         | `$in`, `$eq`                               | `{ activity_type: { $in: [ 'abc', 'xyz' ] } }`                                               |
| `user_id`       | string or list of strings                         | The ID of the user who created the activity                      | `$in`, `$eq`                               | `{ user_id: { $in: [ 'abc', 'xyz' ] } }`                                                     |
| `text`          | string                                            | The text content of the activity                                 | `$eq`, `$q`, `$autocomplete`               | `{ text: { $q: 'popularity' } }`                                                             |
| `search_data`   | object                                            | The extra metadata for search indexing                           | `$contains`, `$path_exists`                | `{ search_data: { $contains: { 'category': 'sports', 'status': 'active' } } }`               |
| `interest_tags` | list of strings                                   | Tags for user interests                                          | `$eq`, `$contains`                         | `{ interest_tags: { $in: [ 'sports', 'music' ] } }`                                          |
| `filter_tags`   | list of strings                                   | Tags for filtering                                               | `$eq`, `$contains`, `$in`                  | `{ filter_tags: { $in: [ 'categoryA', 'categoryB' ] } }`                                     |
| `created_at`    | string, must be formatted as an RFC3339 timestamp | The time the activity was created                                | `$eq`, `$gt`, `$lt`, `$gte`, `$lte`        | `{ created_at: { $gte: '2023-12-04T09:30:20.45Z' } }`                                        |
| `popularity`    | number                                            | The popularity score of the activity                             | `$eq`, `$ne`, `$gt`, `$lt`, `$gte`, `$lte` | `{ popularity: { $gte: 70 } }`                                                               |
| `near`          | object                                            | GEO point and a distance (in km) to search for activities within | `$eq`                                      | `{ near: { $eq: { lat: 40.0, lng: -74.0, distance: 200 } } }`                                |
| `within_bounds` | object                                            | GEO bounds to search for activities within                       | `$eq`                                      | `{ within_bounds: { $eq: { ne_lat: 40.0, ne_lng: -115.0, sw_lat: 32.0, sw_lng: -125.0 } } }` |

When filtering by `filter_tags`, a plain array (or `$eq`) uses **AND-logic**: the activity must contain **all** of the specified tags. Use `$in` if you want **OR-logic**, where the activity must contain **any** of the specified tags.

The filter syntax also supports `$or` and `$and`:

<Tabs>

```js label="React"
// Get all the activities where filter tags contain both "green" and "orange"
const filter = {
  $and: [{ filter_tags: ["green"] }, { filter_tags: ["orange"] }],
};
```

```js label="JavaScript"
// Get all the activities where filter tags contain both "green" and "orange"
const filter = {
  $and: [{ filter_tags: ["green"] }, { filter_tags: ["orange"] }],
};
```

</Tabs>

When providing `filter` to read a feed, activity selector filters on group/view level are ignored.

## Overview of built-in fields

<h3 id="GetOrCreateFeedResponse"><a href="#GetOrCreateFeedResponse">GetOrCreateFeedResponse</a></h3><table><thead><tr><th>Name</th><th>Type</th><th>Description</th><th>Constraints</th></tr></thead><tbody><tr><td><code>activities</code></td><td><code>ActivityResponse[]</code></td><td>-</td><td>Required</td></tr><tr><td><code>aggregated_activities</code></td><td><code>AggregatedActivityResponse[]</code></td><td>-</td><td>Required</td></tr><tr><td><code>created</code></td><td><code>boolean</code></td><td>-</td><td>Required</td></tr><tr><td><code>duration</code></td><td><code>string</code></td><td>Duration of the request in milliseconds</td><td>Required</td></tr><tr><td><code>feed</code></td><td><code>FeedResponse</code></td><td>-</td><td>Required</td></tr><tr><td><code>followers</code></td><td><code>FollowResponse[]</code></td><td>-</td><td>Required</td></tr><tr><td><code>followers_pagination</code></td><td><code>PagerResponse</code></td><td>-</td><td>-</td></tr><tr><td><code>following</code></td><td><code>FollowResponse[]</code></td><td>-</td><td>Required</td></tr><tr><td><code>following_pagination</code></td><td><code>PagerResponse</code></td><td>-</td><td>-</td></tr><tr><td><code>member_pagination</code></td><td><code>PagerResponse</code></td><td>-</td><td>-</td></tr><tr><td><code>members</code></td><td><code>FeedMemberResponse[]</code></td><td>-</td><td>Required</td></tr><tr><td><code>next</code></td><td><code>string</code></td><td>-</td><td>-</td></tr><tr><td><code>notification_status</code></td><td><code>NotificationStatusResponse</code></td><td>-</td><td>-</td></tr><tr><td><code>pinned_activities</code></td><td><code>ActivityPinResponse[]</code></td><td>-</td><td>Required</td></tr><tr><td><code>prev</code></td><td><code>string</code></td><td>-</td><td>-</td></tr></tbody></table>

<h3 id="FeedResponse"><a href="#FeedResponse">FeedResponse</a></h3><table><thead><tr><th>Name</th><th>Type</th><th>Description</th><th>Constraints</th></tr></thead><tbody><tr><td><code>activity_count</code></td><td><code>integer</code></td><td>-</td><td>Required</td></tr><tr><td><code>created_at</code></td><td><code>number</code></td><td>When the feed was created</td><td>Required</td></tr><tr><td><code>created_by</code></td><td><code>UserResponse</code></td><td>User who created the feed</td><td>Required</td></tr><tr><td><code>custom</code></td><td><code>object</code></td><td>Custom data for the feed</td><td>-</td></tr><tr><td><code>deleted_at</code></td><td><code>number</code></td><td>When the feed was deleted</td><td>-</td></tr><tr><td><code>description</code></td><td><code>string</code></td><td>Description of the feed</td><td>Required</td></tr><tr><td><code>feed</code></td><td><code>string</code></td><td>Fully qualified feed ID (group_id:id)</td><td>Required</td></tr><tr><td><code>filter_tags</code></td><td><code>string[]</code></td><td>Tags used for filtering feeds</td><td>-</td></tr><tr><td><code>follower_count</code></td><td><code>integer</code></td><td>Number of followers of this feed</td><td>Required</td></tr><tr><td><code>following_count</code></td><td><code>integer</code></td><td>Number of feeds this feed follows</td><td>Required</td></tr><tr><td><code>group_id</code></td><td><code>string</code></td><td>Group this feed belongs to</td><td>Required</td></tr><tr><td><code>id</code></td><td><code>string</code></td><td>Unique identifier for the feed</td><td>Required</td></tr><tr><td><code>member_count</code></td><td><code>integer</code></td><td>Number of members in this feed</td><td>Required</td></tr><tr><td><code>name</code></td><td><code>string</code></td><td>Name of the feed</td><td>Required</td></tr><tr><td><code>own_capabilities</code></td><td><code>FeedOwnCapability[]</code></td><td>Capabilities the current user has for this feed</td><td>-</td></tr><tr><td><code>own_followings</code></td><td><code>FollowResponse[]</code></td><td>Follow relationships where the feed owner’s feeds are following the current user&#39;s feeds</td><td>-</td></tr><tr><td><code>own_follows</code></td><td><code>FollowResponse[]</code></td><td>Follow relationships where the current user&#39;s feeds are following this feed</td><td>-</td></tr><tr><td><code>own_membership</code></td><td><code>FeedMemberResponse</code></td><td>Membership information for the current user in this feed</td><td>-</td></tr><tr><td><code>pin_count</code></td><td><code>integer</code></td><td>Number of pinned activities in this feed</td><td>Required</td></tr><tr><td><code>updated_at</code></td><td><code>number</code></td><td>When the feed was last updated</td><td>Required</td></tr><tr><td><code>visibility</code></td><td><code>string (public, visible, followers, members, private)</code></td><td>Visibility setting for the feed</td><td>-</td></tr></tbody></table>

## Updating a Feed

The `updateFeed` endpoint performs a partial update: only the fields you include in the request are changed, and each of those fields is completely overwritten.

<Tabs>

```js label="React"
await feed.update({
  name: "Updated feed name",
  filter_tags: ["tech", "hiking", "cooking"],
  custom: {
    color: "blue",
  },
});
```

```js label="JavaScript"
await feed.update({
  name: "Updated feed name",
  filter_tags: ["tech", "hiking", "cooking"],
  custom: {
    color: "blue",
  },
});
```

</Tabs>

### Clearing a feed's location

Since `updateFeed` is a partial update, omitting `location` from the request leaves it unchanged. To explicitly remove a feed's location, set `clear_location` to `true`:

```js label="JavaScript"
await feed.update({
  clear_location: true,
});
```

<Admonition type="warning">

`clear_location` and `location` cannot be used together in the same request. The API will return an error if both are provided.

</Admonition>

### Changing visibility

Changing visibility has dedicated behavior and SDK examples, including how `pending_follows_action` works when loosening from `followers`.

See [Changing Feed Visibility](https://getstream.io/activity-feeds/docs/node/changing-feed-visibility/) for details.

## Deleting a Feed

<Admonition type="danger">

Deleting a feed is an irreversible operation. This goes for **both soft and hard deletes**.

</Admonition>

Deleting a feed will cascade delete the following entities:

- Follows - any follow relationship this feed is part of will be deleted
- Feed members
- Pinned activities
- Activity marks (read/seen)
- Activities - the following will be deleted for each activity
  - Reactions
  - Bookmarks
  - Comments - the following will be deleted for each comment
    - Reactions

The deletion of a feed will be done asynchronously. If the endpoint is called server side a `task_id` is returned and you
can use this task ID to [track the deletion process](https://getstream.io/docs/platform/async-operations/).

The difference between a hard and soft delete is that soft deleting will soft delete the entities that supports this.
These are `feeds`, `activities` and `comments`. Soft deleted `activities` will retain their `reactions` and `bookmarks` until hard deleted. Soft deleted `comments` will retain their `reactions` until hard deleted.
This means that this data can still be exported with the [export endpoint](https://getstream.io/docs/platform/gdpr/#exporting-feeds-data).

<Tabs>

```js label="React"
// Soft delete a feed
await feed.delete({ hard_delete: false });

// Hard delete a feed
await feed.delete({ hard_delete: true });
```

```js label="JavaScript"
// Soft delete a feed
await feed.delete({ hard_delete: false });

// Hard delete a feed
await feed.delete({ hard_delete: true });
```

</Tabs>

## Batch create and delete

You can create and delete multiple feeds in a single request using server-side SDKs. Both batch endpoints support a maximum of 100 feeds per request.

```js label="Node.js"
const feeds = new Array(100).fill(0).map((_, index) => ({
  feed_id: `feed_${index}`,
  feed_group_id: "user",
  name: `Feed ${index}`,
  visibility: "public",
}));
const response = await serverClient.feeds.createFeedsBatch({
  feeds,
});
await serverClient.feeds.deleteFeedsBatch({
  feeds: response.feeds.map((feed) => feed.feed),
  hard_delete: true,
});
```


---

This page was last updated at 2026-09-08T17:13:39.523Z.

For the most recent version of this documentation, visit [https://getstream.io/activity-feeds/docs/react/feeds/](https://getstream.io/activity-feeds/docs/react/feeds/).