> ## Documentation Index
> Fetch the complete documentation index at: /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` |

> [!NOTE]
>
> Flutter developers can read `readCount` and `deliveredCount` from `AmityMessage`, but this SDK checkout does not expose public delivered-user or read-user query methods.

## 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.

```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) },
    )
```

## 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.

```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) },
    )
```

## Query Delivered Users

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

```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) },
    )
```

## 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

> **[Message Read Status](/social-plus-sdk/chat/engagement-features/unread-status/message-read-status.md)**
>
> Mark messages as read and inspect read count fields.

> **[Message Receipt Sync](/social-plus-sdk/chat/engagement-features/unread-status/message-receipt-sync.md)**
>
> Start receipt sync while a chat screen is active.

> **[Query Messages](/social-plus-sdk/chat/messaging-features/messages/query-and-filter-messages.md)**
>
> Load the message models used by receipt APIs.


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