Reactions

Overview

You can react to both activities and comments. It's possible to configure any reaction types that best fit your app.

When adding reactions and the enforce_unique flag is set to true, the existing reaction of a user will be overridden with the new reaction. Use this flag if you want to ensure users have a single reaction per each comment/activity. The default value is false, in which case users can have multiple reactions. The response tells you whether the reaction was new or replaced an existing one — see Reaction write outcome.

AddReactionRequest reactionRequest =
    AddReactionRequest.builder().type("like").userID(testUserId).build();

AddReactionResponse response =
    feeds.addReaction(activityId, reactionRequest).execute().getData();

Overview of the reaction model

FeedsReactionResponse

NameTypeDescriptionConstraints
activity_idstring-Required
comment_idstring--
created_atnumber-Required
customobject--
typestring-Required
updated_atnumber-Required
userUserResponse-Required

By default creating a reaction doesn't create an activity. Pass create_notification_activity: true to add a notification to the reacted-to user's notification feed — see Reaction notification creation timing (added June 23, 2026). The response includes notification_accepted and notification_task_id; notification_created is deprecated and mirrors notification_accepted.

Reaction write outcome

Adding a reaction returns what the write actually did, so you can keep your own reaction counters from a single request instead of reading state first or deleting before adding.

field type description
outcome string One of created, replaced, unchanged. What the write did to this user's reaction on the target.
previous_reaction_type string or null The reaction type that was replaced. Non-null exactly when outcome is replaced.
counter_delta number The change to the number of reactions this user holds on the target: 1 or 0.
outcome when previous_reaction_type counter_delta
created A new reaction was written and nothing was replaced. null 1
replaced enforce_unique removed one or more of the user's other reaction types. the removed type 0
unchanged The user already held this reaction type. Its custom data may have been updated. null 0

replaced only happens with enforce_unique: true — without it nothing is ever removed.

To maintain a per-user reaction counter:

  • Adding: increment when outcome is created, otherwise leave it alone. This is what counter_delta already gives you.
  • Deleting: a successful delete always removed a row, so decrement on 2xx. A 404 means there was nothing to remove. These endpoints never return counter_delta: -1.

Without enforce_unique a user can hold several reaction types on the same target, so created there means this reaction type was newly added, not the user's first reaction on this target. The two only coincide when enforce_unique: true is set, which is the mode to use if you are counting one reaction per user per target.

Re-sending the same reaction type with enforce_unique: true updates the existing reaction in place and preserves its original created_at.

When you read a feed the reactions are included. Here's an example:

Map<String, Object> filter = new HashMap<>();
filter.put("reaction_type", "like");

QueryActivityReactionsRequest queryRequest =
    QueryActivityReactionsRequest.builder().limit(10).filter(filter).build();

QueryActivityReactionsResponse response =
    feeds.queryActivityReactions(activityId, queryRequest).execute().getData();

Querying Reactions

You can query reactions to both activities and comments. Here are some examples:

JavaScript
await client.queryActivityReactions({
  activity_id: activity.id,
  // Provide optional filters
  filter: {
    reaction_type: "like",
  },
});

await client.queryCommentReactions({
  id: comment.id,
  // Provide optional filters

  filter: {
    reaction_type: "like",
  },
});

Batch query activity reactions

batchQueryActivityReactions fetches a single user's reactions across a whole page of activities in one call, so you can merge own_reactions back onto a cached page without calling query reactions once per activity. Pass up to 100 activity IDs per request. The response contains reaction rows only (no activity payloads) and supports the same filter, sort, and pagination options as the single-activity query.

On a client-side connection the returned reactions are always the connected user's. Server-side, pass user_id to choose whose reactions to fetch.

JavaScript
// Fetch the connected user's reactions across a page of activities in one request.
const response = await client.batchQueryActivityReactions({
  activity_ids: activities.map((activity) => activity.id),
  // Optional: filter by reaction type, sort, or paginate with next/prev
  filter: { reaction_type: "like" },
});

// Merge response.reactions back onto the activities as own_reactions
console.log(response.reactions);

Reaction queryable built-in fields

Both batchQueryActivityReactions and batchQueryCommentReactions accept these filter fields.

name type description supported operations example
reaction_type string or list of strings The type of reaction $in, $eq { reaction_type: { $in: [ 'like', 'heart', 'thumbs_up' ] } }
user_id string or list of strings The ID of the user who created the reaction $in, $eq { user_id: { $eq: 'user_123' } }
created_at string, must be formatted as an RFC3339 timestamp The time the reaction was created $eq, $gt, $gte, $lt, $lte { created_at: { $gte: '2023-12-04T09:30:20.45Z' } }

Batch query comment reactions

batchQueryCommentReactions is the comment counterpart of batch query activity reactions. It fetches a single user's reactions across up to 100 comments in one call, returning reaction rows only (no comment payloads). Use it to hydrate own_reactions for a whole comment thread without a request per comment. It accepts the same filter fields, sort, and pagination options.

As with activities, a client-side connection returns the connected user's reactions; server-side, pass user_id.

JavaScript
const response = await client.batchQueryCommentReactions({
  comment_ids: comments.map((comment) => comment.id),
  filter: { reaction_type: "like" },
});

console.log(response.reactions);
Add Chat to my app: getstream.io/SKILL.md

The fastest way to build with Stream. Start a new project or improve an existing one. Full CLI and documentation integration out of the box.


Ask your agent:

/stream Build me a Social App with Feeds and Moderation.
/stream Any livestream calls running?
/stream Feeds Java v3: <Your Question>