Delivered and Seen Receipts

Overview

This guide covers delivered and seen receipts within a conversation.

Before you begin, make sure you added the SDK to your app and you are able to create a conversation.

NOTE: A step-by-step tutorial to build a chat application is available here.

This guide will make use of the following concepts:

Conversation Events:

  • message:delivered events that fire on a Conversation, after you are a Member
  • message:seen events that fire on a Conversation, after you are a Member

Set Message Status to Delivered

There is a method that will set a Message status to delivered. The following code snippet will set a messages's status to delivered once a message event happens in the conversation.

conversation.on('message', (sender, event) => {
    // Can't set your own message status to delivered
    if (conversation.me.id !== event.from) {
        event.delivered().then(() => {
            console.log("message event status set to delivered");
        }).catch((error)=>{
            console.error("error setting message event status to delivered ", error);
        });
    };
});
override fun onMessageEvent(messageEvent: NexmoMessageEvent) {
    messageEvent.markAsDelivered(object: NexmoRequestListener<Void> {
        override fun onError(error: NexmoApiError) {}

        override fun onSuccess(result: Void?) {}
    })
}
public void onMessageEvent(@NonNull NexmoMessageEvent messageEvent) {
    messageEvent.markAsDelivered(new NexmoRequestListener() {
        @Override
        public void onError(@NonNull NexmoApiError error) { ... }

        @Override
        public void onSuccess(@Nullable Object result) { ... }
    });
}
if conversation.myMember?.memberUuid != event.fromMemberId {
    conversation.sendMarkDeliveredMessage(event.uuid, completionHandler: nil)
}
if (conversation.myMember.memberUuid != event.fromMemberId) {
    [conversation sendMarkDeliveredMessage:event.uuid completionHandler:nil];
}

Message Delivered Receipt

Given a conversation you are already a member of, message:delivered events will be received when Message events are set to delivered in the context of the current conversation:

conversation.on('message:delivered', (data, event) => {
    console.log(event);
});
private val messageListener = object : NexmoMessageEventListener {
    override fun onTypingEvent(typingEvent: NexmoTypingEvent) {}

    override fun onAttachmentEvent(attachmentEvent: NexmoAttachmentEvent) {}

    override fun onTextEvent(textEvent: NexmoTextEvent) {}

    override fun onSeenReceipt(seenEvent: NexmoSeenEvent) {}

    override fun onEventDeleted(deletedEvent: NexmoDeletedEvent) {}

    override fun onDeliveredReceipt(deliveredEvent: NexmoDeliveredEvent) {
        val userName = deliveredEvent.getEmbeddedInfo.user.name

        Log.d("TAG", "Event ${deliveredEvent.initialEventId()} delivered to User $userName")
    }
}

conversation.addMessageEventListener(messageListener)
private NexmoMessageEventListener messageListener = new NexmoMessageEventListener() {
    @Override
    public void onTextEvent(@NonNull NexmoTextEvent textEvent) {}

    @Override
    public void onAttachmentEvent(@NonNull NexmoAttachmentEvent attachmentEvent) {}

    @Override
    public void onEventDeleted(@NonNull NexmoDeletedEvent deletedEvent) {}

    @Override
    public void onSeenReceipt(@NonNull NexmoSeenEvent seenEvent) {}

    @Override
    public void onDeliveredReceipt(@NonNull NexmoDeliveredEvent deliveredEvent) {
        String userName = deliveredEvent.getEmbeddedInfo().getUser().getName();

        Log.d("TAG", "Event " + deliveredEvent.initialEventId() + "delivered to User " + userName);
    }

    @Override
    public void onTypingEvent(@NonNull NexmoTypingEvent typingEvent) {}
};

conversation.addMessageEventListener(messageListener);

Add NXMConversationDelegate as an extension to a ViewController or similar, and implement conversation(_ conversation: NXMConversation, didReceive event: NXMMessageStatusEvent):

Note: The first method below is required when implementing NXMConversationDelegate:

extension ViewController: NXMConversationDelegate {
    func conversation(_ conversation: NXMConversation, didReceive error: Error) {
        NSLog("Conversation error: \(error.localizedDescription)")
    }
    func conversation(_ conversation: NXMConversation, didReceive event: NXMMessageStatusEvent) {
        if event.status == .delivered {
            NSLog("Received delivered event: \(event.referenceEventUuid)")
        }
    }
}

Have a ViewController, or similar, conform to NXMConversationDelegate and implement conversation:didReceiveMessageStatusEvent::

Note: The first method below is required when implementing NXMConversationDelegate:

- (void)conversation:(NXMConversation *)conversation didReceive:(NSError *)error {
    NSLog(@"Conversation error: %@", error.localizedDescription);
}
- (void)conversation:(NXMConversation *)conversation didReceiveMessageStatusEvent:(NXMMessageStatusEvent *)event {
    if (event.status == NXMMessageStatusTypeDelivered) {
        NSLog(@"Received delivered event: %li", (long)event.referenceEventUuid);
    }
}

Set Message Status to Seen

There is a method that will set a Message status to seen. The following code snippet will set a messages's status to seen once a message event happens in the conversation.

conversation.on('message', (sender, event) => {
    // Can't set your own message status to seen
    if (conversation.me.id !== event.from) {
        event.seen().then(() => {
            console.log("message event status set to seen");
        }).catch((error)=>{
            console.error("error setting message event status to seen ", error);
        });
    };
});
override fun onMessageEvent(messageEvent: NexmoMessageEvent) {
    messageEvent.markAsSeen(object: NexmoRequestListener<Void> {
        override fun onError(error: NexmoApiError) {...}
        override fun onSuccess(result: Void?) {...}
    })
}
public void onMessageEvent(@NonNull NexmoMessageEvent messageEvent) {
    messageEvent.markAsSeen(new NexmoRequestListener() {
        @Override
        public void onError(@NonNull NexmoApiError error) { ... }

        @Override
        public void onSuccess(@Nullable Object result) { ... }
    });
}
if conversation.myMember?.memberUuid != event.fromMemberId {
    conversation.sendMarkSeenMessage(event.uuid, completionHandler: nil)
}
if (conversation.myMember.memberUuid != event.fromMemberId) {
    [conversation sendMarkSeenMessage:event.uuid completionHandler:nil];
}

Message Seen Receipt

Given a conversation you are already a member of, message:seen events will be received when Message events are set to seen in the context of the current conversation:

conversation.on('message:seen', (data, event) => {
    console.log(event);
});
private val messageListener = object : NexmoMessageEventListener {
    override fun onTypingEvent(typingEvent: NexmoTypingEvent) {}

    override fun onAttachmentEvent(attachmentEvent: NexmoAttachmentEvent) {}

    override fun onTextEvent(textEvent: NexmoTextEvent) {}

    override fun onSeenReceipt(seenEvent: NexmoSeenEvent) {
        val userName = seenEvent.getEmbeddedInfo.user.name

        Log.d("TAG", "Event ${seenEvent.initialEventId()} seen by User $userName")
    }

    override fun onEventDeleted(deletedEvent: NexmoDeletedEvent) {}

    override fun onDeliveredReceipt(deliveredEvent: NexmoDeliveredEvent) {}
}

conversation.addMessageEventListener(messageListener)
private NexmoMessageEventListener messageListener = new NexmoMessageEventListener() {
    @Override
    public void onTextEvent(@NonNull NexmoTextEvent textEvent) {}

    @Override
    public void onAttachmentEvent(@NonNull NexmoAttachmentEvent attachmentEvent) {}

    @Override
    public void onEventDeleted(@NonNull NexmoDeletedEvent deletedEvent) {}

    @Override
    public void onSeenReceipt(@NonNull NexmoSeenEvent seenEvent) {
        String userName = seenEvent.getEmbeddedInfo().getUser().getName();

        Log.d("TAG", "Event " + seenEvent.initialEventId() + "seen by User " + userName);
    }

    @Override
    public void onDeliveredReceipt(@NonNull NexmoDeliveredEvent deliveredEvent) {}

    @Override
    public void onTypingEvent(@NonNull NexmoTypingEvent typingEvent) {}
};

conversation.addMessageEventListener(messageListener);

Add NXMConversationDelegate as an extension to a ViewController or similar, and implement conversation(_ conversation: NXMConversation, didReceive event: NXMMessageStatusEvent):

Note: The first method below is required when implementing NXMConversationDelegate:

extension ViewController: NXMConversationDelegate {
    func conversation(_ conversation: NXMConversation, didReceive error: Error) {
        NSLog("Conversation error: \(error.localizedDescription)")
    }
    func conversation(_ conversation: NXMConversation, didReceive event: NXMMessageStatusEvent) {
        if event.status == .seen {
            NSLog("Received seen event: \(event.referenceEventUuid)")
        }
    }
}

Have a ViewController, or similar, conform to NXMConversationDelegate and implement conversation:didReceiveMessageStatusEvent::

Note: The first method below is required when implementing NXMConversationDelegate:

- (void)conversation:(NXMConversation *)conversation didReceive:(NSError *)error {
    NSLog(@"Conversation error: %@", error.localizedDescription);
}
- (void)conversation:(NXMConversation *)conversation didReceiveMessageStatusEvent:(NXMMessageStatusEvent *)event {
    if (event.status == NXMMessageStatusTypeSeen) {
        NSLog(@"Received seen event: %li", (long)event.referenceEventUuid);
    }
}

Reference