> ## Documentation Index
> Fetch the complete documentation index at: https://social-b97141fb-feat-user-history-moderation-detail.mintlify.site/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>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.