> ## Documentation Index
> Fetch the complete documentation index at: https://learn.social.plus/llms.txt
> Use this file to discover all available pages before exploring further.

# Message Delivery Status

> Mark chat messages as delivered and query read or delivered users where the SDK supports it.

Use message delivery status when your app needs delivered receipts, read-user lists, or delivered-user lists for a message. TypeScript, iOS, and Android expose explicit delivery and receipt-user APIs. Flutter currently exposes message count fields, but not public APIs for marking a message delivered or querying receipt users.

## Platform Surface

| Surface             | TypeScript                                                   | iOS                                           | Android                                                 | Flutter                                       |
| ------------------- | ------------------------------------------------------------ | --------------------------------------------- | ------------------------------------------------------- | --------------------------------------------- |
| Mark delivered      | `MessageRepository.markAsDelivered(subChannelId, messageId)` | `message.markAsDelivered()`                   | `message.markAsDelivered()`                             | Not exposed                                   |
| Get read users      | `MessageRepository.getReadUsers(query)`                      | `message.getReadUsers(memberships:)`          | `message.getReadUsers(memberships)`                     | Not exposed                                   |
| Get delivered users | `MessageRepository.getDeliveredUsers(query)`                 | `message.getDeliveredUsers(memberships:)`     | `message.getDeliveredUsers(memberships)`                | Not exposed                                   |
| Count fields        | `message.readCount`, `message.deliveredCount`                | `message.readCount`, `message.deliveredCount` | `message.getReadCount()`, `message.getDeliveredCount()` | `message.readCount`, `message.deliveredCount` |

<Info>
  Flutter developers can read `readCount` and `deliveredCount` from `AmityMessage`, but this SDK checkout does not expose public delivered-user or read-user query methods.
</Info>

## Parameters

| Parameter           | Required                              | Description                                                                                                     |
| ------------------- | ------------------------------------- | --------------------------------------------------------------------------------------------------------------- |
| `subChannelId`      | Yes for TypeScript delivery marking   | Subchannel ID that owns the message being marked as delivered.                                                  |
| `messageId`         | Yes                                   | Message ID to mark delivered or use for receipt-user queries.                                                   |
| `message`           | Yes for iOS and Android model methods | Message model returned by the SDK.                                                                              |
| `memberships`       | No                                    | Filters receipt users by membership state. Supported values are member, banned, muted, non-member, and deleted. |
| Pagination controls | No                                    | TypeScript returns a paged response; Android returns `PagingData`; iOS returns an `AmityCollection`.            |

## Mark Message Delivered

Call the delivered API when a received message has reached the recipient device and your app needs to sync that delivery state.

<CodeGroup>
  ```typescript TypeScript theme={null}
  import { MessageRepository } from '@amityco/ts-sdk';

  const didMarkDelivered = await MessageRepository.markAsDelivered(
    subChannelId,
    messageId,
  );

  if (didMarkDelivered) {
    showSuccessMessage(messageId);
  }
  ```

  ```swift iOS theme={null}
  let liveMessage = messageRepository.getMessage("message-id")

  token = liveMessage.observe { liveObject, _ in
      guard let currentMessage = liveObject.snapshot else { return }

      Task {
          do {
              try await currentMessage.markAsDelivered()
              showSuccessMessage(currentMessage.messageId)
          } catch {
              handleError(error)
          }
      }
  }
  ```

  ```kotlin Android theme={null}
  val currentMessage = message ?: return

  val disposable = currentMessage
      .markAsDelivered()
      .subscribe(
          { showSuccessMessage(currentMessage.getMessageId()) },
          { error -> handleGeneralError(error) },
      )
  ```
</CodeGroup>

## Query Read Users

Use read-user queries when you need to show who has read a message. Apply membership filters when your product only wants active members or needs to include muted, banned, non-member, or deleted users.

<CodeGroup>
  ```typescript TypeScript theme={null}
  import { MessageRepository } from '@amityco/ts-sdk';

  const { data: users, nextPage } = await MessageRepository.getReadUsers({
    messageId,
    memberships: ['member', 'muted', 'non-member'],
  });

  renderResults({
    users,
    nextPage,
  });
  ```

  ```swift iOS theme={null}
  let liveMessage = messageRepository.getMessage("message-id")

  token = liveMessage.observe { liveObject, _ in
      guard let currentMessage = liveObject.snapshot else { return }

      let memberships: Set<MessageReadMembershipFilter> = [
          .member,
          .muted,
          .nonMember
      ]
      let readUsers = currentMessage.getReadUsers(memberships: memberships)

      showSuccessMessage(readUsers)
  }
  ```

  ```kotlin Android theme={null}
  import com.amity.socialcloud.sdk.model.chat.message.MessageReadMembershipFilter

  val currentMessage = message ?: return

  val disposable = currentMessage
      .getReadUsers(
          memberships = listOf(
              MessageReadMembershipFilter.MEMBER,
              MessageReadMembershipFilter.MUTED,
              MessageReadMembershipFilter.NOT_MEMBER,
          ),
      )
      .subscribe(
          { pagingData -> getPagingData(pagingData) },
          { error -> handleGeneralError(error) },
      )
  ```
</CodeGroup>

## Query Delivered Users

Use delivered-user queries when your sender UI or moderation tooling needs to know which recipients have received a message.

<CodeGroup>
  ```typescript TypeScript theme={null}
  import { MessageRepository } from '@amityco/ts-sdk';

  const { data: users, nextPage } = await MessageRepository.getDeliveredUsers({
    messageId,
    memberships: ['member', 'banned', 'deleted'],
  });

  renderResults({
    users,
    nextPage,
  });
  ```

  ```swift iOS theme={null}
  let liveMessage = messageRepository.getMessage("message-id")

  token = liveMessage.observe { liveObject, _ in
      guard let currentMessage = liveObject.snapshot else { return }

      let memberships: Set<MessageDeliveredMembershipFilter> = [
          .member,
          .banned,
          .deleted
      ]
      let deliveredUsers = currentMessage.getDeliveredUsers(memberships: memberships)

      showSuccessMessage(deliveredUsers)
  }
  ```

  ```kotlin Android theme={null}
  import com.amity.socialcloud.sdk.model.chat.message.MessageDeliveredMembershipFilter

  val currentMessage = message ?: return

  val disposable = currentMessage
      .getDeliveredUsers(
          memberships = listOf(
              MessageDeliveredMembershipFilter.MEMBER,
              MessageDeliveredMembershipFilter.BANNED,
              MessageDeliveredMembershipFilter.DELETED,
          ),
      )
      .subscribe(
          { pagingData -> getPagingData(pagingData) },
          { error -> handleGeneralError(error) },
      )
  ```
</CodeGroup>

## Receipt User Filters

| Logical value | TypeScript     | iOS          | Android      |
| ------------- | -------------- | ------------ | ------------ |
| Member        | `'member'`     | `.member`    | `MEMBER`     |
| Banned        | `'banned'`     | `.banned`    | `BANNED`     |
| Muted         | `'muted'`      | `.muted`     | `MUTED`      |
| Non-member    | `'non-member'` | `.nonMember` | `NOT_MEMBER` |
| Deleted       | `'deleted'`    | `.deleted`   | `DELETED`    |

## Related Topics

<CardGroup cols={3}>
  <Card title="Message Read Status" href="./message-read-status" icon="eye">
    Mark messages as read and inspect read count fields.
  </Card>

  <Card title="Message Receipt Sync" href="./message-receipt-sync" icon="rotate">
    Start receipt sync while a chat screen is active.
  </Card>

  <Card title="Query Messages" href="/social-plus-sdk/chat/messaging-features/messages/query-and-filter-messages" icon="list">
    Load the message models used by receipt APIs.
  </Card>
</CardGroup>
