# Reactions

## Adding Reactions

Reactions are a special kind of data that can be used to capture user interaction with specific activities. Common examples of reactions are **likes** , **comments** , and **upvotes** . Reactions are automatically returned to feeds' activities at read time when the reactions parameters are used.

Reactions are always related to activities; in order to add a reaction to an activity you need to provide its ID.

### Parameters

| name                    | type   | description                                                                       | default | optional |
| ----------------------- | ------ | --------------------------------------------------------------------------------- | ------- | -------- |
| kind                    | string | The type of reaction (eg. like, comment, ...)                                     | -       |          |
| activity_id             | string | The ID of the activity the reaction refers to                                     | -       |          |
| data                    | object | Additional data to attach to the reaction                                         | -       | ✓        |
| target_feeds            | array  | The feeds that should receive a notification activity                             | -       | ✓        |
| target_feeds_extra_data | object | Additional data to attach to the notification activities                          | -       | ✓        |
| user_id                 | string | Id of the user adding the reaction if not own user. **Required for server side.** | -       | ✓        |

<Tabs>

```csharp label="C#"
// add a like reaction to the activity with id activityId
var like = await client.Reactions.AddAsync("like", activityId);

// adds a comment reaction to the activity with id activityId
var comment = await client.Reactions.AddAsync("comment", activityId, "bob");
```

```js label="JavaScript"
// add a like reaction to the activity with id activityId
const like = await client.reactions.add("like", activityId, {});

// adds a comment reaction to the activity with id activityId
const comment = await client.reactions.add("comment", activityId, {
  text: "awesome post!",
});

// for server side auth, userId is required
const comment = await client.reactions.add(
  "comment",
  activityId,
  { text: "awesome post!" },
  { userId },
);
```

```python label="Python"
# add a like reaction to the activity with id activity_id
client.reactions.add("like", activity_id, user_id="mike")

# adds a comment reaction to the activity with id activityId
client.reactions.add(
  "comment", activity_id, user_id="mike", data={"text": "awesome post!"}
)
```

```ruby label="Ruby"
# add a like reaction to the activity with id activity_id
client.reactions.add("like", activity_id, user_id="mike")

# adds a comment reaction to the activity with id activity_id
client.reactions.add(
  "comment", activity_id, user_id="mike", data: {text: "awesome post!"}
)
```

```php label="PHP"
// add a like reaction to the activity with id activity_id
$client->reactions()->add("like", $activity_id, "mike");

// adds a comment reaction to the activity with id activity_id
$client->reactions()->add("comment", $activity_id, "mike", ["text"=>"awesome post!"]);
```

```java label="Java"
Reaction like = new Reaction.Builder()
    .kind("like")
    .activityID(activity.getID())
    .build();

// add a like reaction to the activity with id activityId
like = client.reactions().add("john-doe", like).get();

Reaction comment = new Reaction.Builder()
    .kind("comment")
    .activityID(activity.getID())
    .extraField("text", "awesome post!")
    .build();

// adds a comment reaction to the activity with id activityId
comment = client.reactions().add("john-doe", comment).get();
```

```go label="Go"
// add a like reaction to the activity with id activityID
	r := stream.AddReactionRequestObject{
		Kind:    "like",
		ActivityID: activityID,
	}
	like, err := client.Reactions().Add(context.TODO(), r)
	if err != nil {
		panic(err)
	}

	// adds a comment reaction to the activity with id activityId
	r = stream.AddReactionRequestObject{
		Kind:    "comment",
		ActivityID: activityID,
		UserID:   "bob",
	}
	comment, err := client.Reactions().Add(context.TODO(), r)
	if err != nil {
		panic(err)
	}
```

</Tabs>

Here's a complete example:

<Tabs>

```csharp label="C#"
// first let's read current user's timeline feed and pick one activity
var response = await client.Feed("timeline", "bob").GetActivitiesAsync();
var activity = response.FirstOrDefault();

// then let's add a like reaction to that activity
await client.Reactions.AddAsync("like", activity.Id, "bob");
```

```js label="JavaScript"
// first let's read current user's timeline feed and pick one activity
const response = await client.feed("timeline", "mike").get();
const activity = response.activities[0];

// then let's add a like reaction to that activity
await client.reactions.add("like", activity.id);
```

```python label="Python"
# first let's read current user's timeline feed and pick one activity
response = client.feed("timeline", "mike").get()
activity = response["results"][0]

# then let's add a like reaction to that activity
client.reactions.add("like", activity["id"], user_id="bob")
```

```ruby label="Ruby"
# first let's read current user's timeline feed and pick one activity
response = client.feed("timeline", "mike").get()
activity = response["results"][0]

# then let's add a like reaction to that activity
client.reactions.add("like", activity["id"], "bob")
```

```php label="PHP"
// first let's read current user's timeline feed and pick one activity
$activity = $client->feed('timeline', 'mike')->getActivities(0,1)["results"][0];

// then let's add a like reaction to that activity
$client->reactions()->add("like", $activity["id"], "bob");
```

```java label="Java"
// first let's read current user's timeline feed and pick one activity
List<activity> response = client.flatFeed("timeline", "mike").getActivities().get();
Activity activity = response.get(0);

// then let's add a like reaction to that activity
client.reactions().add("john-doe", Reaction.builder()
    .kind("like")
    .activityID(activity.getID())
    .build()).join();</activity>
```

```go label="Go"
// first let's read current user's timeline feed and pick one activity
	feed, err := client.FlatFeed("timeline", "bob")
	if err != nil {
		panic(err)
	}

	resp, err := feed.GetActivities(context.TODO())
	if err != nil {
		panic(err)
	}
	activity := resp.Results[0]

	// then let's add a like reaction to that activity
	r := stream.AddReactionRequestObject{
		Kind:    "like",
		ActivityID: activity.ID,
		UserID:   "bob",
	}
	_, err := client.Reactions().Add(context.TODO(), r)
	if err != nil {
		panic(err)
	}
```

</Tabs>

<admonition type="info">

The size of a reaction can not exceed 10kB

</admonition>

## Retrieving Reactions

You can read reactions and filter them based on their `user_id` or `activity_id` values.
Further filtering can be done with the `kind` parameter (e.g. retrieve all likes by one user, retrieve all comments for one activity, etc.).

Reactions are returned in descending order (newest to oldest) by default and when using `id_lt[e]` , and in ascending order (oldest to newest) when using `id_gt[e]` .

### Parameters

| name               | type    | description                                                                          | default | optional |
| ------------------ | ------- | ------------------------------------------------------------------------------------ | ------- | -------- |
| activity_id        | string  | Retrieve reactions by activity_id                                                    | -       |          |
| user_id            | string  | Retrieve reactions by user_id                                                        | -       |          |
| reaction_id        | string  | Retrieve children reaction by reaction_id                                            | -       | ✓        |
| kind               | string  | If provided it will only retrieve reactions of a certain kind (e.g. "like")          | -       | ✓        |
| limit              | integer | The number of reactions to retrieve (Max. 25)                                        | 10      | ✓        |
| id_gte             | string  | Retrieve reactions created after the one with ID equal to the parameter (inclusive)  | -       | ✓        |
| id_gt              | string  | Retrieve reactions created after the one with ID equal to the parameter.             | -       | ✓        |
| id_lte             | string  | Retrieve reactions created before the one with ID equal to the parameter (inclusive) | -       | ✓        |
| id_lt              | string  | Retrieve reactions before the one with ID equal to the parameter                     | -       | ✓        |
| with_activity_data | boolean | Returns activity data when paginating using activity_id                              | -       | ✓        |
| with_own_children  | boolean | Enable returning the children reactions when filtering reactions by parent ID        | -       | ✓        |

<admonition type="info">

If you want to filter reactions by `activity_id` or `reaction_id` <strong>and</strong> `user_id` you need to use the parameter `filter_user_id` instead of the `user_id` parameter described above.

</admonition>

<Tabs>

```csharp label="C#"
// retrieve all kind of reactions for an activity
var reactions = await client.Reactions.FilterAsync(ReactionFiltering.Default, ReactionPagination.By.ActivityID("ed2837a6-0a3b-4679-adc1-778a1704852d"));

// retrieve first 10 likes for an activity
var response = await client.Reactions.FilterAsync(ReactionFiltering.Default.WithLimit(10), ReactionPagination.By.ActivityID("ed2837a6-0a3b-4679-adc1-778a1704852d").Kind("like"));

// retrieve the next 10 likes using the id_lt param
var filter = ReactionFiltering.Default.WithFilter(FeedFilter.Where().IdLessThan("e561de8f-00f1-11e4-b400-0cc47a024be0"));
var pagination = ReactionPagination.By.ActivityID("ed2837a6-0a3b-4679-adc1-778a1704852d").Kind("like");
var response2 = await client.Reactions.FilterAsync(filter, pagination);
```

```js label="JavaScript"
// retrieve all kind of reactions for an activity
const reactions = await client.reactions.filter({
  activity_id: "ed2837a6-0a3b-4679-adc1-778a1704852d",
});

// retrieve first 10 likes for an activity
const response = await client.reactions.filter({
  activity_id: "ed2837a6-0a3b-4679-adc1-778a1704852d",
  kind: "like",
  limit: 10,
});

// retrieve the next 10 likes using the id_lt param
const response = await client.reactions.filter({
  activity_id: "ed2837a6-0a3b-4679-adc1-778a1704852d",
  kind: "like",
  id_lt: "e561de8f-00f1-11e4-b400-0cc47a024be0",
});
```

```python label="Python"
# retrieve all kind of reactions for an activity
reactions = client.reactions.filter(
  activity_id="ed2837a6-0a3b-4679-adc1-778a1704852d"
)

# retrieve first 10 likes for an activity
response = client.reactions.filter(
  activity_id="ed2837a6-0a3b-4679-adc1-778a1704852d", kind="like", limit=10
)

# retrieve the next 10 likes using the id_lt param
response = client.reactions.filter(
  activity_id="ed2837a6-0a3b-4679-adc1-778a1704852d",
  kind="like",
  id_lt="e561de8f-00f1-11e4-b400-0cc47a024be0",
)
```

```ruby label="Ruby"
# retrieve all kind of reactions for an activity
reactions = client.reactions.filter(
  activity_id: "ed2837a6-0a3b-4679-adc1-778a1704852d"
)

# retrieve first 10 likes for an activity
response = client.reactions.filter(
  activity_id: "ed2837a6-0a3b-4679-adc1-778a1704852d", kind: "like", limit: 10
)

# retrieve the next 10 likes using the id_lt param
response = client.reactions.filter(
  activity_id: "ed2837a6-0a3b-4679-adc1-778a1704852d",
  kind: "like",
  id_lt: "e561de8f-00f1-11e4-b400-0cc47a024be0",
)
```

```php label="PHP"
// retrieve all kind of reactions for an activity
$client->reactions()->filter("activity_id", "827509c1-2872-11e9-8ec6-0a544dd61b80", "comment");

// retrieve first 10 likes for an activity
$client->reactions()->filter(
  "activity_id",
  "827509c1-2872-11e9-8ec6-0a544dd61b80",
  "like",
  ["limit" => 10],
);

// retrieve the next 10 likes using the id_lt param
$client->reactions()->filter(
  "activity_id",
  "827509c1-2872-11e9-8ec6-0a544dd61b80",
  "like",
  ["limit" => 10
   "id_lt" => "e561de8f-00f1-11e4-b400-0cc47a024be0"],
);
```

```java label="Java"
// retrieve all kind of reactions for an activity
List<reaction> reactions = client.reactions().filter(LookupKind.ACTIVITY, "ed2837a6-0a3b-4679-adc1-778a1704852d").get();

// retrieve first 10 likes for an activity
reactions = client.reactions()
    .filter(LookupKind.ACTIVITY,
        "ed2837a6-0a3b-4679-adc1-778a1704852d",
        new Filter().limit(10),
        "like").join();

// retrieve the next 10 likes using the id_lt param
reactions = client.reactions()
    .filter(LookupKind.ACTIVITY,
        "ed2837a6-0a3b-4679-adc1-778a1704852d",
        new Filter().idLessThan("e561de8f-00f1-11e4-b400-0cc47a024be0"),
        "like").join();</reaction>
```

```go label="Go"
// retrieve all kind of reactions for an activity
	resp, err := client.Reactions().Filter(context.TODO(), stream.ByActivityID("ed2837a6-0a3b-4679-adc1-778a1704852d"))
	if err != nil {
		panic(err)
	}

	// retrieve first 10 likes for an activity
	resp, err := client.Reactions().Filter(
		context.TODO(),
		stream.ByActivityID("ed2837a6-0a3b-4679-adc1-778a1704852d").ByKind("like"),
		stream.WithLimit(10),
	)
	if err != nil {
		panic(err)
	}

	// retrieve the next 10 likes using the id_lt param
	filterAttribute := stream.ByActivityID("ed2837a6-0a3b-4679-adc1-778a1704852d").ByKind("like")
	pagination := stream.WithIDLT("e561de8f-00f1-11e4-b400-0cc47a024be0")
	resp, err := client.Reactions().Filter(context.TODO(), filterAttribute, pagination)
	if err != nil {
		panic(err)
	}
```

</Tabs>

## Retrieving Reactions by ID

<Tabs>

```js label="JavaScript"
await client.reactions.get(reactionId);
```

```ruby label="Ruby"
client.reactions.get(reaction_id)
```

```go label="Go"
resp, err := client.Reactions().Get(context.TODO(), id)
if err != nil {
  panic(err)
}
```

</Tabs>

## Updating Reactions

Reactions can be updated by providing reaction ID parameter. Changes to reactions are propagated to all notified feeds; if the `target_feeds` list is updated, notifications will be added and removed accordingly.

### Parameters

| name         | type   | description                                                   | default | optional |
| ------------ | ------ | ------------------------------------------------------------- | ------- | -------- |
| reaction_id  | string | The ID of the reaction                                        | -       |          |
| data         | object | Reaction data                                                 | -       | ✓        |
| target_feeds | string | The list of feeds that should receive a copy of the reaction. | -       | ✓        |

<Tabs>

```csharp label="C#"
var reactionData = new Dictionary<string, object="">()
{
  { "text", "love it!"}
};
await client.Reactions.UpdateAsync(reactionId, reactionData);
```

```js label="JavaScript"
client.reactions.update(reactionId, { text: "love it!" });
```

```python label="Python"
client.reactions.update(reaction_id, {"text": "love it!"});
```

```ruby label="Ruby"
client.reactions.update(reaction_id, data: {text: "I love it"})
```

```php label="PHP"
$client->reactions()->update($reaction_id, ["text"=> "I love it"]);
```

```java label="Java"
client.reactions().update(Reaction.builder()
    .id(reaction.getId())
    .extraField("text", "love it!")
    .build());
```

```go label="Go"
resp, err := client.Reactions().Update(context.TODO(), reactionID, map[string]any{"text": "love it!"}, nil)
	if err != nil {
		panic(err)
	}
```

</Tabs>

## Removing Reactions

Reactions are easy to remove. Simply pass in their ID, like so:

<Tabs>

```csharp label="C#"
await client.Reactions.DeleteAsync(reactionId)
```

```js label="JavaScript"
client.reactions.delete(reactionId);
```

```python label="Python"
client.reactions.delete(reaction_id)
```

```ruby label="Ruby"
client.reactions.delete(reaction_id)
```

```java label="Java"
client.reactions().delete(reaction.getId()).join();
```

```go label="Go"
_, err := client.Reactions().Delete(context.TODO(), reactionID)
	if err != nil {
		panic(err)
	}
```

</Tabs>

## Soft delete and restore

<admonition type="info">

This feature is currently supported only selected SDKs. If you need support for other SDKs, please contact support.

</admonition>

Reactions can be soft deleted and restored by ID:

<Tabs>

```csharp label="C#"
await client.Reactions.DeleteAsync(reactionId, soft: true);
await client.Reactions.RestoreSoftDeletedAsync(reactionId);
```

```python label="Python"
client.reactions.delete(reaction_id, soft=True)
client.reactions.restore(reaction_id)
```

```java label="Java"
client.reactions().softDelete(reaction.getId()).join();
client.reactions().restore(reaction.getId()).join();
```

```js label="JavaScript"
client.reactions.delete(reactionId, true);
client.reactions.restore(reactionId);
```

</Tabs>


---

This page was last updated at 2026-05-22T16:31:48.592Z.

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