On this page

Manage the user-channel membership relationship

Requires App Context

Enable App Context for your keyset in the Admin Portal.

A Membership entity is created when a user joins or is invited to a channel, and ends when the user leaves.

Get members

Get all members of a channel with getMembers().

Method signature

This method takes the following parameters:

1channel.getMembers(
2 limit: Int?,
3 page: PNPage?,
4 filter: String?,
5 sort: Collection<PNSortKey<PNMemberKey>> = listOf(),
6): PNFuture<MembersResponse>

Input

* required
ParameterDescription
limit
Type: Int
Default:
100
Number of objects to return in response. The default (and maximum) value is 100.
page
Type: PNPage
Default:
n/a
Object used for pagination to define which previous or next result page you want to fetch.
filter
Type: String
Default:
n/a
Expression used to filter the results. Returns only these members whose properties satisfy the given expression. The filter language is defined here.
sort
Type: Collection<PNSortKey<PNMemberKey>>
Default:
listOf()
A collection to specify the sort order. Available options are id, name, and updated. Use asc or desc to specify the sorting direction, or specify null to take the default sorting direction (ascending). For example: {name: "asc"}. Unless specified otherwise, the items are sorted by the last updated date. Defaults to an empty list.

Output

TypeDescription
PNFuture<MembersResponse>
PNFuture containing a set of channel members with membership status, total number of members, and next and prev pages.

Sample code

List all members of the support channel on the premium support plan.

1// reference the "channel" object
2chat.getChannel("support").async { result ->
3 result.onSuccess { channel ->
4 // get the list of all members with the premium support plan
5 channel.getMembers(
6 filter = "custom.support_plan == 'premium'"
7 ).async { membersResult ->
8 membersResult.onSuccess { membersResponse ->
9 val membersList = membersResponse.members
10 // handle success: membersList contains the list of members
11 }.onFailure { error ->
12 // handle failure
13 }
14 }
15 }.onFailure { error ->
show all 18 lines

Get membership

Get all channel memberships for a user with getMemberships().

To list all channels, use getChannels() instead.

Method signature

This method takes the following parameters:

1user.getMemberships(
2 limit: Int?,
3 page: PNPage?,
4 filter: String?,
5 sort: Collection<PNSortKey<PNMembershipKey>> = listOf(),
6): PNFuture<MembershipsResponse>

Input

* required
ParameterDescription
limit
Type: Int
Default:
100
Number of objects to return in response. The default (and maximum) value is 100.
page
Type: PNPage
Default:
n/a
Object used for pagination to define which previous or next result page you want to fetch.
filter
Type: String
Default:
n/a
Expression used to filter the results. Returns only these members whose properties satisfy the given expression. The filter language is defined here.
sort
Type: Collection<PNSortKey<PNMembershipKey>>
Default:
listOf()
A collection to specify the sort order. Available options are id, name, and updated. Use asc or desc to specify the sorting direction, or specify null to take the default sorting direction (ascending). For example: {name: "asc"}. Unless specified otherwise, the items are sorted by the last updated date. Defaults to an empty list.

Output

TypeDescription
PNFuture<MembershipsResponse>
PNFuture containing a set of memberships, their status and total number, and next and prev pages.

Sample code

Find out which channels the support_agent_15 user is a member of.

1// reference the "support_agent_15" user
2chat.getUser("support_agent_15").async { result ->
3 result.onSuccess { user ->
4 // get the list of all user memberships
5 user.getMemberships().async { membershipsResult ->
6 membershipsResult.onSuccess { membershipsResponse ->
7 val membershipsList = membershipsResponse.memberships
8 // handle success: membershipsList contains the list of memberships
9 }.onFailure { error ->
10 // handle failure
11 }
12 }
13 }.onFailure { error ->
14 // handle failure to fetch user
15 }
show all 16 lines

Check membership

Check if a user is a member of a channel, or retrieve a specific membership.

Check from channel

Use hasMember() to check if a user is a member, or getMember() to retrieve the membership.

Method signature

1channel.hasMember(userId: String): PNFuture<Boolean>
2
3channel.getMember(userId: String): PNFuture<Membership?>

Input

* required
ParameterDescription
userId *
Type: String
Default:
n/a
The ID of the user to check.

Output

MethodDescription
hasMember()
Type: PNFuture<Boolean>
true if the user is a member of the channel.
getMember()
Type: PNFuture<Membership?>
The Membership object if found, or null.

Sample code

1// check if a user is a member
2channel.hasMember("support_agent_15").async { result ->
3 result.onSuccess { isMember ->
4 println("Is member: $isMember")
5 }.onFailure { error ->
6 // handle failure
7 }
8}
9
10// get the membership details
11channel.getMember("support_agent_15").async { result ->
12 result.onSuccess { membership ->
13 if (membership != null) {
14 println("Membership found: ${membership.user.id} on ${membership.channel.id}")
15 } else {
show all 21 lines

Check from user

Use isMemberOf() to check if a user belongs to a channel, or getMembership() to retrieve the membership.

Method signature

1user.isMemberOf(channelId: String): PNFuture<Boolean>
2
3user.getMembership(channelId: String): PNFuture<Membership?>

Input

* required
ParameterDescription
channelId *
Type: String
Default:
n/a
The ID of the channel to check.

Output

MethodDescription
isMemberOf()
Type: PNFuture<Boolean>
true if the user is a member of the channel.
getMembership()
Type: PNFuture<Membership?>
The Membership object if found, or null.

Sample code

1// check if the user belongs to a channel
2user.isMemberOf("support").async { result ->
3 result.onSuccess { isMember ->
4 println("Is member of support: $isMember")
5 }.onFailure { error ->
6 // handle failure
7 }
8}

Get updates

Receive updates when Membership objects are edited:

  • streamUpdates() - monitors a single membership
  • streamUpdatesOn() - monitors multiple memberships

Receive real-time notifications when membership metadata changes or a membership is deleted:

  • onUpdated() - fires when membership metadata is modified
  • onDeleted() - fires when the membership is removed

Method signature (entity-first)

  • onUpdated()

    1membership.onUpdated(callback: (membership: Membership) -> Unit): AutoCloseable
  • onDeleted()

    1membership.onDeleted(callback: () -> Unit): AutoCloseable

Input

* required
ParameterDescription
callback (in onUpdated) *
Type: (membership: Membership) -> Unit
Default:
n/a
Function that receives the updated Membership object.
callback (in onDeleted) *
Type: () -> Unit
Default:
n/a
Function invoked when the membership is deleted.

Output

TypeDescription
AutoCloseable
Interface that lets you stop receiving membership-related updates by invoking the close() method.

Sample code (entity-first)

1// get a membership and listen for updates
2chat.currentUser.getMemberships().async { result ->
3 result.onSuccess { membershipsResponse ->
4 val firstMembership = membershipsResponse.memberships.firstOrNull()
5 firstMembership?.let {
6 val subscription = it.onUpdated { updatedMembership ->
7 println("Updated membership: $updatedMembership")
8 }
9 }
10 }.onFailure { exception ->
11 println("Failed to fetch memberships: $exception")
12 }
13}

Deprecated methods

Deprecated methods

streamUpdates() is deprecated. Use onUpdated() and onDeleted() instead. streamUpdatesOn() remains supported.

Membership changes

These methods notify about field changes (metadata, status) for existing memberships, not additions or removals.

Both methods accept a callback invoked when membership data changes. They subscribe to a channel and add an objects event listener for membership events, returning an unsubscribe function.

Stream update behavior
  • streamUpdates() returns the updated Membership object on each change (null if deleted)
  • streamUpdatesOn() returns the complete list of monitored memberships on any change

Method signature

These methods take the following parameters:

  • streamUpdates()

    1membership.streamUpdates(callback: (membership: Membership?) -> Unit): AutoCloseable
  • streamUpdatesOn()

    1class Membership {
    2 companion object {
    3 fun streamUpdatesOn(
    4 memberships: Collection<Membership>,
    5 callback: (memberships: Collection<Membership>) -> Unit
    6 ): AutoCloseable
    7 }
    8}

Input

ParameterRequired in streamUpdates()Required in streamUpdatesOn()Description
memberships
Type: Collection<Membership>
Default:
n/a
No
Yes
A collection of Membership objects for which you want to get updates.
callback
Type: (membership: Membership?) -> Unit
Default:
n/a
Yes
No
Function that takes a single Membership object. It defines the custom behavior to be executed when detecting membership changes.
callback
Type: (memberships: Collection<Membership>) -> Unit
Default:
n/a
No
Yes
Function that takes a set of Membership objects. It defines the custom behavior to be executed when detecting membership changes.

Output

TypeDescription
AutoCloseable
Interface that lets you stop receiving membership-related updates (objects events) by invoking the close() method.

Sample code

Get updates on the first user membership.

  • streamUpdates()

    1chat.currentUser.getMemberships().async { result ->
    2 result.onSuccess { membershipsResponse ->
    3 // handle success
    4 val firstMembership = membershipsResponse.memberships.firstOrNull()
    5 firstMembership?.let {
    6 val autoCloseable = it.streamUpdates { updatedMembership ->
    7 // The callback receives the entire updated Membership object each time a change occurs.
    8 if (updatedMembership != null) {
    9 println("Updated membership: $updatedMembership")
    10 } else {
    11 println("Membership was deleted")
    12 }
    13 }
    14 } ?: run {
    15 println("No memberships found.")
    show all 21 lines

Get updates on the first page of user memberships.

  • streamUpdatesOn()

    1chat.currentUser.getMemberships().async { result ->
    2 result.onSuccess { membershipsResponse ->
    3 // handle success
    4 val firstPageMemberships = membershipsResponse.memberships.take(10) // assuming one page has 10 memberships
    5
    6 val autoCloseable = Membership.streamUpdatesOn(memberships = firstPageMemberships) { updatedMemberships ->
    7 // The callback receives the complete list of all memberships you're monitoring
    8 // each time any change occurs.
    9 if (updatedMemberships.isNotEmpty()) {
    10 updatedMemberships.forEach { updatedMembership ->
    11 println("Updated membership: $updatedMembership")
    12 }
    13 } else {
    14 println("No membership updates available.")
    15 }
    show all 21 lines

Other examples

Stop listening to updates on the first user membership.

  • streamUpdates()

    1chat.currentUser.getMemberships().async { result ->
    2 result.onSuccess { membershipsResponse ->
    3 // handle success
    4 val firstMembership = membershipsResponse.memberships.firstOrNull()
    5 firstMembership?.let {
    6 val autoCloseable = it.streamUpdates { updatedMembership ->
    7 // The callback receives the entire updated Membership object each time a change occurs.
    8 if (updatedMembership != null) {
    9 println("Updated membership: $updatedMembership")
    10 } else {
    11 println("Membership was deleted")
    12 }
    13 }
    14
    15 // logic to stop listening to updates can be placed here
    show all 27 lines

Stop listening to updates on the first page of user memberships.

  • streamUpdatesOn()

    1chat.currentUser.getMemberships().async { result ->
    2 result.onSuccess { membershipsResponse ->
    3 // handle success
    4 val firstPageMemberships = membershipsResponse.memberships.take(10) // assuming one page has 10 memberships
    5
    6 val autoCloseable = Membership.streamUpdatesOn(memberships = firstPageMemberships) { updatedMemberships ->
    7 // The callback receives the complete list of all memberships you're monitoring
    8 // each time any change occurs.
    9 if (updatedMemberships.isNotEmpty()) {
    10 updatedMemberships.forEach { updatedMembership ->
    11 println("Updated membership: $updatedMembership")
    12 }
    13 } else {
    14 println("No membership updates available.")
    15 }
    show all 27 lines

Delete membership

Delete a membership with delete().

Method signature

1membership.delete(): PNFuture<Unit>

Input

This method doesn't take any parameters.

Output

TypeDescription
PNFuture<Unit>
Returns when the membership is successfully removed.

Sample code

1val channel: Channel
2// ...
3
4channel.join().async { joinResult ->
5 joinResult.onSuccess { membership ->
6 membership.delete().async { deleteResult ->
7 deleteResult.onSuccess {
8 // handle success
9 println("Membership deleted successfully")
10 }.onFailure {
11 // handle failure
12 println("Failed to delete membership: ${it.message}")
13 }
14 }
15 }.onFailure {
show all 18 lines

Update

Update a user's channel membership information with update().

Method signature

This method takes the following parameters:

1membership.update(
2 status: String? = null,
3 type: String? = null,
4 custom: CustomObject? = null
5): PNFuture<Membership>

Input

* required
ParameterDescription
status
Type: String
Default:
null
Current status of the membership, like active or inactive.
type
Type: String
Default:
null
Type of the membership, used to categorize the user-channel relationship.
custom
Type: CustomObject
Default:
null
Any custom properties or metadata associated with the channel-user membership in the form of a JSON. Values must be scalar only; arrays or objects are not supported. App Context filtering language doesn’t support filtering by custom properties.

Output

TypeDescription
PNFuture<Membership>
Returned (modified) object containing the membership data.

Sample code

Assign the premium-support role to support_agent_15 on the high-priority-incidents channel.

1// get the list of all user memberships and filter out the right channel
2user.getMemberships(filter = "channel.id == 'high-priority-incidents'").async {
3 it.onSuccess { membershipsResponse ->
4 membershipsResponse
5 .memberships
6 .firstOrNull()
7 // add custom metadata to the user membership
8 ?.update(mapOf("role" to "premium-support"))?.async { membership ->
9 // ...
10 }
11 }.onFailure {
12 // handle failure
13 }
14}