Activity Feeds v3 is in beta — try it out!

Search for Activities

Scope

When called from client-side

queryActivities endpoint searches for activities in public and visible feeds. It also respects activity visibility:

  • private activities are only returned for the activity author
  • if an activity has tag visibilty, and user doesn’t have access to the full activity, only a preview is returned (for text based searches the search is performed across the whole activity text, not just the preview)

When called from server-side

queryActivities endpoint searches for activities in public and visible feeds. It also respects activity visibility:

  • private activities are not returned, unless include_private_activities is set to true see example below)
  • activities with tag visibility are returned with full content, not just a preview
  • user_id can be passed to turn a server-side request into a client-side request see example below

Examples

You can query & search activities. Here’s an example of how to query activities:

let query = ActivitiesQuery(
    filter: .equal(.type, "post"),
    sort: [Sort(field: .createdAt, direction: .reverse)],
    limit: 10
)
let activityList = client.activityList(for: query)
let activities = try await activityList.get()

When searching activities, the activity.current_feed field contains information about the feed the activity belongs to. However, if an activity is posted to multiple feeds, this field will be empty. In this case, you can use the activity.feeds array to read all feed IDs the activity was posted to and fetch feeds separately if needed.

Search filter syntax emulates a MongoDB style query syntax. (It emulates it, we don’t use MongoDB, but the query syntax is nice here).

Querying activities by text

// search for activities where the text includes the word 'popularity'.
let query = ActivitiesQuery(
    filter: .query(.text, "popularity")
)
let activityList = client.activityList(for: query)
let activities = try await activityList.get()

Querying activities by search data

Consider this example activity:

{
  "id": "activity-123",
  "type": "post",
  "text": "Check out our spring sale!",
  "search_data": {
    "campaign": {
      "id": "spring-sale-2025",
      "location": {
        "mall": "yorkdale",
        "city": "toronto",
        "country": "canada"
      }
    }
  }
  // ... other activity fields
}

You can search this activity using the search_data field in several ways:

// search for activities associated with the campaign ID 'spring-sale-2025'
let searchValue: [String: RawJSON] = ["campaign": .dictionary(["id": .string("spring-sale-2025")])]
let query = ActivitiesQuery(
    filter: .contains(.searchData, searchValue)
)
let activityList = client.activityList(for: query)
let activities = try await activityList.get()

// search for activities where the campaign took place in a mall
let query2 = ActivitiesQuery(
    filter: .pathExists(.searchData, "campaign.location.mall")
)
let activityList2 = client.activityList(for: query2)
let activities2 = try await activityList2.get()

Querying private activities

For server-side requests, you can set include_private_activities to true to include private activities in the results (the default is false).

const response = await client.feeds.queryActivities({
  include_private_activities: true,
  filter: {
    // your filter here
  },
});

user_id for server-side requests

For server-side requests, you can provide a user_id to perform the search as if it were made by that specific user. It turns the server-side request into a client-side request.

const response = await client.feeds.queryActivities({
  user_id: "john",
  filter: {
    // your filter here
  },
});

Activities Queryable Built-In Fields

nametypedescriptionsupported operationsexample
idstring or list of stringsThe ID of the activity$in, $eq{ id: { $in: [ 'abc', 'xyz' ] } }
activity_typestring or list of stringsThe type of the activity$in, $eq{ activity_type: { $in: [ 'abc', 'xyz' ] } }
user_idstring or list of stringsThe ID of the user who created the activity$in, $eq{ user_id: { $in: [ 'abc', 'xyz' ] } }
textstringThe text content of the activity$eq, $q, $autocomplete{ text: { $q: 'popularity' } }
search_dataobjectThe extra metadata for search indexing$contains, $path_exists{ search_data: { $contains: { 'category': 'sports', 'status': 'active' } } }
interest_tagslist of stringsTags for user interests$eq, $contains{ interest_tags: { $in: [ 'sports', 'music' ] } }
filter_tagslist of stringsTags for filtering$eq, $contains{ filter_tags: { $in: [ 'categoryA', 'categoryB' ] } }
created_atstring, must be formatted as an RFC3339 timestampThe time the activity was created$eq, $gt, $lt, $gte, $lte{ created_at: { $gte: '2023-12-04T09:30:20.45Z' } }
popularitynumberThe popularity score of the activity$eq, $ne, $gt, $lt, $gte, $lte{ popularity: { $gte: 70 } }
nearobjectIndicates the GEO point to search nearby activities$eq{ near: { $eq: { lat: 40.0, lng: -74.0, distance: 200 } } }
within_boundsobjectIndicates the 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 } } }
hiddenbooltrue if an activity was hidden by the user. Hidden activities are excluded unless specified with filter$eq{ hidden: { $eq: true }

The filter syntax also supports $or and $and:

// Get all the activities where filter tags contain both "green" and "orange"
let filter = .and([
  .in(.filterTags, ["green"]),
  .in(.filterTags, ["orange"])
])

Be sure to reach out to support if you need additional query activity capabilities.

Activities sort options

Fields:

  • created_at
  • popularity

Direction: 1 or -1

© Getstream.io, Inc. All Rights Reserved.