> ## Documentation Index
> Fetch the complete documentation index at: https://cometchat-22654f5b-docs-angular-v5-docs-update.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Delivery & Read Receipts

> Mark messages as delivered, read, or unread and receive real-time receipt events using the CometChat iOS SDK.

<Accordion title="AI Integration Quick Reference">
  | Method                                                          | Description                              |
  | --------------------------------------------------------------- | ---------------------------------------- |
  | `markAsDelivered(baseMessage:)`                                 | Mark a message as delivered              |
  | `markAsRead(baseMessage:)`                                      | Mark a message as read                   |
  | `markConversationAsDelivered(conversationWithId:receiverType:)` | Mark entire conversation as delivered    |
  | `markConversationAsRead(conversationWithId:receiverType:)`      | Mark entire conversation as read         |
  | `markMessageAsUnread(baseMessage:receiverType:)`                | Mark a message as unread                 |
  | `getMessageReceipts(_:)`                                        | Get delivery/read receipts for a message |

  ```swift theme={null}
  // Mark as delivered/read (pass message object)
  CometChat.markAsDelivered(baseMessage: baseMessage)
  CometChat.markAsRead(baseMessage: baseMessage)

  // Mark entire conversation
  CometChat.markConversationAsRead(conversationWithId: uid, receiverType: .user) { _ in } onError: { _ in }

  // Listen for receipt events (CometChatMessageDelegate)
  func onMessagesDelivered(receipt: MessageReceipt) { }
  func onMessagesRead(receipt: MessageReceipt) { }
  func onMessagesDeliveredToAll(receipt: MessageReceipt) { }  // Groups only
  func onMessagesReadByAll(receipt: MessageReceipt) { }        // Groups only
  ```
</Accordion>

Delivery and read receipts track whether messages have been delivered to and read by recipients.

## Mark as Delivered

Use `markAsDelivered()` to mark messages as delivered. You can pass either a message object or individual parameters.

### Using Message Object

<Tabs>
  <Tab title="Swift">
    ```swift theme={null}
    CometChat.markAsDelivered(baseMessage: baseMessage, onSuccess: {
        print("markAsDelivered Success")
    }, onError: { error in
        print("markAsDelivered error: \(error?.errorDescription ?? "")")
    })
    ```
  </Tab>

  <Tab title="Objective-C">
    ```objc theme={null}
    [CometChat markAsDeliveredWithBaseMessage:baseMessage onSuccess:^{
        NSLog(@"markAsDelivered Success");
    } onError:^(CometChatException *error){
        NSLog(@"markAsDelivered error: %@", [error errorDescription]);
    }];
    ```
  </Tab>
</Tabs>

### Using Parameters

| Parameter       | Description                                          |
| --------------- | ---------------------------------------------------- |
| `messageId`     | ID of the message to mark as delivered               |
| `receiverId`    | For user chats: sender's UID. For groups: group GUID |
| `receiverType`  | `.user` or `.group`                                  |
| `messageSender` | UID of the message sender                            |

<Tabs>
  <Tab title="Swift (User)">
    ```swift theme={null}
    var messageId = 123
    var receiverId = "cometchat-uid-2"
    var senderId = "cometchat-uid-1"

    CometChat.markAsDelivered(messageId: messageId, receiverId: receiverId, receiverType: .user, messageSender: senderId, onSuccess: {
        print("markAsDelivered Success")
    }, onError: { error in
        print("markAsDelivered error: \(error?.errorDescription ?? "")")
    })
    ```
  </Tab>

  <Tab title="Swift (Group)">
    ```swift theme={null}
    var messageId = 123
    var receiverId = "cometchat-uid-2"
    var senderId = "cometchat-uid-1"

    CometChat.markAsDelivered(messageId: messageId, receiverId: receiverId, receiverType: .group, messageSender: senderId, onSuccess: {
        print("markAsDelivered Success")
    }, onError: { error in
        print("markAsDelivered error: \(error?.errorDescription ?? "")")
    })
    ```
  </Tab>

  <Tab title="Objective-C (User)">
    ```objc theme={null}
    int messageId = 123;
    NSString *receiverId = @"cometchat-uid-2";
    NSString *senderId = @"cometchat-uid-1";

    [CometChat markAsDeliveredWithMessageId:messageId receiverId:receiverId receiverType:ReceiverTypeUser messageSender:senderId onSuccess:^{
        NSLog(@"markAsDelivered Success");
    } onError:^(CometChatException *error){
        NSLog(@"markAsDelivered error: %@", [error errorDescription]);
    }];
    ```
  </Tab>

  <Tab title="Objective-C (Group)">
    ```objc theme={null}
    int messageId = 123;
    NSString *receiverId = @"cometchat-uid-2";
    NSString *senderId = @"cometchat-uid-1";

    [CometChat markAsDeliveredWithMessageId:messageId receiverId:receiverId receiverType:ReceiverTypeGroup messageSender:senderId onSuccess:^{
        NSLog(@"markAsDelivered Success");
    } onError:^(CometChatException *error){
        NSLog(@"markAsDelivered error: %@", [error errorDescription]);
    }];
    ```
  </Tab>
</Tabs>

This method marks all messages before the specified `messageId` for the conversation with `receiverId` and `receiverType` as delivered.

<Note>
  Starting v3, messages are not marked delivered internally by the SDK. You must use `markAsDelivered()` explicitly.
</Note>

## Mark Conversation as Delivered

Use `markConversationAsDelivered()` to mark all messages in a conversation as delivered.

<Tabs>
  <Tab title="Swift (User)">
    ```swift theme={null}
    CometChat.markConversationAsDelivered(conversationWithId: (conversation.conversationWith as? User)?.uid, receiverType: .user) { message in
        print(message)
    } onError: { error in
        print(error.errorDescription)
    }
    ```
  </Tab>

  <Tab title="Swift (Group)">
    ```swift theme={null}
    CometChat.markConversationAsDelivered(conversationWithId: (conversation.conversationWith as? Group)?.guid, receiverType: .group) { message in
        print(message)
    } onError: { error in
        print(error.errorDescription)
    }
    ```
  </Tab>
</Tabs>

## Mark as Read

Use `markAsRead()` to mark messages as read. You can pass either a message object or individual parameters.

### Using Message Object

<Tabs>
  <Tab title="Swift">
    ```swift theme={null}
    CometChat.markAsRead(baseMessage: baseMessage, onSuccess: {
        print("markAsRead Success")
    }, onError: { error in
        print("markAsRead error: \(error?.errorDescription ?? "")")
    })
    ```
  </Tab>

  <Tab title="Objective-C">
    ```objc theme={null}
    [CometChat markAsReadWithBaseMessage:baseMessage onSuccess:^{
        NSLog(@"markAsRead Success");
    } onError:^(CometChatException *error){
        NSLog(@"markAsRead error: %@", [error errorDescription]);
    }];
    ```
  </Tab>
</Tabs>

### Using Parameters

<Tabs>
  <Tab title="Swift (User)">
    ```swift theme={null}
    var messageId = 123
    var receiverId = "cometchat-uid-2"
    var senderId = "cometchat-uid-1"

    CometChat.markAsRead(messageId: messageId, receiverId: receiverId, receiverType: .user, messageSender: senderId, onSuccess: {
        print("markAsRead Success")
    }, onError: { error in
        print("markAsRead error: \(error?.errorDescription ?? "")")
    })
    ```
  </Tab>

  <Tab title="Swift (Group)">
    ```swift theme={null}
    var messageId = 123
    var receiverId = "cometchat-uid-2"
    var senderId = "cometchat-uid-1"

    CometChat.markAsRead(messageId: messageId, receiverId: receiverId, receiverType: .group, messageSender: senderId, onSuccess: {
        print("markAsRead Success")
    }, onError: { error in
        print("markAsRead error: \(error?.errorDescription ?? "")")
    })
    ```
  </Tab>

  <Tab title="Objective-C (User)">
    ```objc theme={null}
    int messageId = 123;
    NSString *receiverId = @"abc";

    [CometChat markAsReadWithMessageId:messageId receiverId:receiverId receiverType:ReceiverTypeUser onSuccess:^{
        NSLog(@"markAsRead Success");
    } onError:^(CometChatException *error){
        NSLog(@"markAsRead error: %@", [error errorDescription]);
    }];
    ```
  </Tab>

  <Tab title="Objective-C (Group)">
    ```objc theme={null}
    int messageId = 123;
    NSString *receiverId = @"abc";

    [CometChat markAsReadWithMessageId:messageId receiverId:receiverId receiverType:ReceiverTypeGroup onSuccess:^{
        NSLog(@"markAsRead Success");
    } onError:^(CometChatException *error){
        NSLog(@"markAsRead error: %@", [error errorDescription]);
    }];
    ```
  </Tab>
</Tabs>

## Mark Conversation as Read

Use `markConversationAsRead()` to mark all messages in a conversation as read.

<Tabs>
  <Tab title="Swift (User)">
    ```swift theme={null}
    CometChat.markConversationAsRead(conversationWithId: (conversation.conversationWith as? User)?.uid, receiverType: .user) { message in
        print(message)
    } onError: { error in
        print(error.errorDescription)
    }
    ```
  </Tab>

  <Tab title="Swift (Group)">
    ```swift theme={null}
    CometChat.markConversationAsRead(conversationWithId: (conversation.conversationWith as? Group)?.guid, receiverType: .group) { message in
        print(message)
    } onError: { error in
        print(error.errorDescription)
    }
    ```
  </Tab>
</Tabs>

## Real-Time Receipt Events

Implement `CometChatMessageDelegate` to receive delivery and read receipt events.

| Callback                   | Description                            |
| -------------------------- | -------------------------------------- |
| `onMessagesDelivered`      | Message delivered to a user            |
| `onMessagesRead`           | Message read by a user                 |
| `onMessagesDeliveredToAll` | Group message delivered to all members |
| `onMessagesReadByAll`      | Group message read by all members      |

<Tabs>
  <Tab title="Swift">
    ```swift theme={null}
    func onMessagesRead(receipt: MessageReceipt) {
        print("onMessagesRead \(receipt.stringValue())")
    }

    func onMessagesDelivered(receipt: MessageReceipt) {
        print("onMessagesDelivered \(receipt.stringValue())")
    }

    func onMessagesDeliveredToAll(receipt: MessageReceipt) {
        print("onMessagesDeliveredToAll \(receipt.stringValue())")
    }

    func onMessagesReadByAll(receipt: MessageReceipt) {
        print("onMessagesReadByAll \(receipt.stringValue())")
    }
    ```
  </Tab>

  <Tab title="Objective-C">
    ```objc theme={null}
    -(void)onMessagesDeliveredWithReceipt:(MessageReceipt *)receipt {
        NSLog(@"onMessagesDeliveredWithReceipt %@", receipt.stringValue);
    }

    -(void)onMessagesReadWithReceipt:(MessageReceipt *)receipt {
        NSLog(@"onMessagesReadWithReceipt %@", receipt.stringValue);
    }

    -(void)onMessagesDeliveredToAll:(MessageReceipt *)receipt {
        NSLog(@"onMessagesDeliveredToAll %@", receipt.stringValue);
    }

    -(void)onMessagesReadByAll:(MessageReceipt *)receipt {
        NSLog(@"onMessagesReadByAll %@", receipt.stringValue);
    }
    ```
  </Tab>
</Tabs>

You will receive events in the form of [`MessageReceipt`](/sdk/reference/auxiliary#messagereceipt) objects:

| Parameter      | Information                                                                                                                           |
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| `messageId`    | The Id of the message prior to which all messages for that conversation have been marked as read.                                     |
| `sender`       | User object containing the details of the user who marked the message as read. System User for `deliveredToAll` & `readByAll` events. |
| `receiverId`   | Id of the receiver whose conversation has been marked as read.                                                                        |
| `receiverType` | Type of the receiver (user/group)                                                                                                     |
| `receiptType`  | Type of the receipt (read/delivered)                                                                                                  |
| `deliveredAt`  | Timestamp when the message was delivered. Only present if receiptType is delivered.                                                   |
| `readAt`       | Timestamp when the message was read. Only present when receiptType is read.                                                           |

<Info>
  The following features require **Enhanced Messaging Status** to be enabled for your app:

  * `onMessagesDeliveredToAll` event
  * `onMessagesReadByAll` event
  * `deliveredAt` field in group messages
  * `readAt` field in group messages
  * `markMessageAsUnread` method
</Info>

## Get Receipt History

Use `getMessageReceipts()` to fetch delivery and read receipts for a specific message. Useful for group messages to see which members have received/read the message.

<Tabs>
  <Tab title="Swift">
    ```swift theme={null}
    var messageId = 10101

    CometChat.getMessageReceipts(messageId, onSuccess: { receipt in
        print("getMessageReceipt \(receipt)")
    }) { error in
        print(error?.errorDescription ?? "")
    }
    ```
  </Tab>

  <Tab title="Objective-C">
    ```objc theme={null}
    int messageId = 10101;

    [CometChat getMessageReceipts:messageId onSuccess:^(NSArray<MessageReceipt *> * _Nonnull receipt) {
        NSLog(@"getMessageReceipts %@", receipt);
    } onError:^(CometChatException * _Nullable error) {
        NSLog(@"CometChatException %@", error.errorDescription);
    }];
    ```
  </Tab>
</Tabs>

Returns an array of [`MessageReceipt`](/sdk/reference/auxiliary#messagereceipt) objects.

## Missed Receipts

When fetching messages, each message object includes `deliveredAt` and `readAt` timestamps indicating when the message was delivered and read.

For group messages, use `getMessageReceipts()` to fetch individual member delivery and read status.

## Mark as Unread

Use `markMessageAsUnread()` to mark a message as unread. This is useful for "mark as unread" functionality in conversation lists.

<Tabs>
  <Tab title="Swift (User)">
    ```swift theme={null}
    CometChat.markMessageAsUnread(baseMessage: message, receiverType: .user) { conversation in
        print(conversation)
        print(conversation.unreadMessageCount)
    } onError: { error in
        print(error?.errorDescription ?? "")
    }
    ```
  </Tab>

  <Tab title="Swift (Group)">
    ```swift theme={null}
    CometChat.markMessageAsUnread(baseMessage: message, receiverType: .group) { conversation in
        print(conversation)
        print(conversation.unreadMessageCount)
    } onError: { error in
        print(error?.errorDescription ?? "")
    }
    ```
  </Tab>
</Tabs>

<Note>
  You cannot mark your own messages as unread. This method only works for messages received from other users.
</Note>

***

## Next Steps

<CardGroup cols={2}>
  <Card title="Typing Indicators" icon="keyboard" href="/sdk/ios/typing-indicators">
    Show real-time typing status in conversations
  </Card>

  <Card title="Receive Messages" icon="envelope-open" href="/sdk/ios/receive-message">
    Listen for incoming messages in real time
  </Card>

  <Card title="Retrieve Conversations" icon="comments" href="/sdk/ios/retrieve-conversations">
    Fetch conversation list with unread counts
  </Card>

  <Card title="All Real-Time Listeners" icon="tower-broadcast" href="/sdk/ios/all-real-time-delegates-listeners">
    Complete reference for all SDK event listeners
  </Card>
</CardGroup>
