diff --git a/src/jamidht/account_manager.cpp b/src/jamidht/account_manager.cpp
index 60b5bb87d685cb65542eac8663993601c9363b87..bc65a284476e92ec9544b88e300fcc6633b41cab 100644
--- a/src/jamidht/account_manager.cpp
+++ b/src/jamidht/account_manager.cpp
@@ -345,19 +345,19 @@ AccountManager::startSync(const OnNewDeviceCb& cb, const OnDeviceAnnouncedCb& dc
                             return;
                         auto conversationId = v.conversationId;
                         // Check if there was an old active conversation.
-                        auto details = info_->contacts->getContactDetails(peer_account);
-                        auto oldConvIt = details.find(libjami::Account::TrustRequest::CONVERSATIONID);
-                        if (oldConvIt != details.end() && oldConvIt->second != "") {
-                            if (conversationId == oldConvIt->second) {
-                                // Here, it's possible that we already have accepted the conversation
-                                // but contact were offline and sync failed.
-                                // So, retrigger the callback so upper layer will clone conversation if needed
-                                // instead of getting stuck in sync.
-                                info_->contacts->acceptConversation(conversationId, v.owner->getLongId().toString());
-                                return;
+                        if (auto details = info_->contacts->getContactInfo(peer_account)) {
+                            if (!details->conversationId.empty()) {
+                                if (details->conversationId == conversationId) {
+                                    // Here, it's possible that we already have accepted the conversation
+                                    // but contact were offline and sync failed.
+                                    // So, retrigger the callback so upper layer will clone conversation if needed
+                                    // instead of getting stuck in sync.
+                                    info_->contacts->acceptConversation(conversationId, v.owner->getLongId().toString());
+                                    return;
+                                }
+                                conversationId = details->conversationId;
+                                JAMI_WARNING("Accept with old convId: {}", conversationId);
                             }
-                            conversationId = oldConvIt->second;
-                            JAMI_WARNING("Accept with old convId: {}", conversationId);
                         }
                         sendTrustRequestConfirm(peer_account, conversationId);
                     }
@@ -588,6 +588,21 @@ AccountManager::getContactDetails(const std::string& uri) const
     return info_->contacts->getContactDetails(h);
 }
 
+std::optional<Contact>
+AccountManager::getContactInfo(const std::string& uri) const
+{
+    if (!info_) {
+        JAMI_ERROR("[Account {}] getContactInfo(): account not loaded", accountId_);
+        return {};
+    }
+    dht::InfoHash h(uri);
+    if (not h) {
+        JAMI_ERROR("[Account {}] getContactInfo: invalid contact URI", accountId_);
+        return {};
+    }
+    return info_->contacts->getContactInfo(h);
+}
+
 bool
 AccountManager::findCertificate(
     const dht::InfoHash& h,
diff --git a/src/jamidht/account_manager.h b/src/jamidht/account_manager.h
index a3b12b4c3b674952482149de973181d8e51148fb..631e585ac1d24e82e63124c64e68a5a7f34880d2 100644
--- a/src/jamidht/account_manager.h
+++ b/src/jamidht/account_manager.h
@@ -248,6 +248,7 @@ public:
 
     /** Obtain details about one account contact in serializable form. */
     std::map<std::string, std::string> getContactDetails(const std::string& uri) const;
+    std::optional<Contact> getContactInfo(const std::string& uri) const;
 
     virtual bool findCertificate(
         const dht::InfoHash& h,
diff --git a/src/jamidht/contact_list.cpp b/src/jamidht/contact_list.cpp
index ac7916bf0c19fa7a213c77072b10fc62936e6a16..1bd16213d7517f642a9a6aeb8464ba6459d1664f 100644
--- a/src/jamidht/contact_list.cpp
+++ b/src/jamidht/contact_list.cpp
@@ -172,6 +172,17 @@ ContactList::getContactDetails(const dht::InfoHash& h) const
     return details;
 }
 
+std::optional<Contact>
+ContactList::getContactInfo(const dht::InfoHash& h) const
+{
+    const auto c = contacts_.find(h);
+    if (c == std::end(contacts_)) {
+        JAMI_WARNING("[Account {}] [Contacts] Contact '{}' not found", accountId_, h.to_view());
+        return {};
+    }
+    return c->second;
+}
+
 const std::map<dht::InfoHash, Contact>&
 ContactList::getContacts() const
 {
diff --git a/src/jamidht/contact_list.h b/src/jamidht/contact_list.h
index 3084bee687657b81caa023e4b89cb482616734fd..753f2651392a9902af6d5a1871829b038d28a873 100644
--- a/src/jamidht/contact_list.h
+++ b/src/jamidht/contact_list.h
@@ -66,6 +66,8 @@ public:
 
     /* Contacts */
     std::map<std::string, std::string> getContactDetails(const dht::InfoHash&) const;
+    std::optional<Contact> getContactInfo(const dht::InfoHash&) const;
+
     bool removeContact(const dht::InfoHash&, bool ban);
     bool removeContactConversation(const dht::InfoHash&);
     bool addContact(const dht::InfoHash&,
diff --git a/src/jamidht/conversation_module.cpp b/src/jamidht/conversation_module.cpp
index 7d1f4b26c8d88662448efa3e0f2c0bd063a2a55b..bab65b47d84ca264088379a661aa607c24d63111 100644
--- a/src/jamidht/conversation_module.cpp
+++ b/src/jamidht/conversation_module.cpp
@@ -900,22 +900,16 @@ ConversationModule::Impl::getRequest(const std::string& id) const
 std::string
 ConversationModule::Impl::getOneToOneConversation(const std::string& uri) const noexcept
 {
-    auto details = accountManager_->getContactDetails(uri);
-    auto itRemoved = details.find("removed");
-    // If contact is removed there is no conversation
-    if (itRemoved != details.end() && itRemoved->second != "0") {
-        auto itBanned = details.find("banned");
+    if (auto details = accountManager_->getContactInfo(uri)) {
+        // If contact is removed there is no conversation
         // If banned, conversation is still on disk
-        if (itBanned == details.end() || itBanned->second == "0") {
+        if (details->removed != 0 && details->banned == 0) {
             // Check if contact is removed
-            auto itAdded = details.find("added");
-            if (std::stoi(itRemoved->second) > std::stoi(itAdded->second))
+            if (details->removed > details->added)
                 return {};
         }
+        return details->conversationId;
     }
-    auto it = details.find(libjami::Account::TrustRequest::CONVERSATIONID);
-    if (it != details.end())
-        return it->second;
     return {};
 }
 
diff --git a/src/jamidht/jamiaccount.cpp b/src/jamidht/jamiaccount.cpp
index bb2c6f0527a9aaa39f1c9d004a9a323d80d1ac86..6c1798ce74318111826ade81077789200ee57c1b 100644
--- a/src/jamidht/jamiaccount.cpp
+++ b/src/jamidht/jamiaccount.cpp
@@ -1815,33 +1815,31 @@ JamiAccount::onTrackedBuddyOnline(const dht::InfoHash& contactId)
                                                                   "");
     }
 
-    auto details = getContactDetails(id);
-    auto it = details.find("confirmed");
-    if (it == details.end() or it->second == "false") {
-        auto convId = convModule()->getOneToOneConversation(id);
-        if (convId.empty())
-            return;
-        // In this case, the TrustRequest was sent but never confirmed (cause the contact was
-        // offline maybe) To avoid the contact to never receive the conv request, retry there
-        std::lock_guard lock(configurationMutex_);
-        if (accountManager_) {
-            // Retrieve cached payload for trust request.
-            auto requestPath = cachePath_ / "requests" / id;
-            std::vector<uint8_t> payload;
-            try {
-                payload = fileutils::loadFile(requestPath);
-            } catch (...) {
-            }
-
-            if (payload.size() >= 64000) {
-                JAMI_WARNING(
-                    "[Account {:s}] Trust request for contact {:s} is too big, reset payload",
-                    getAccountID(),
-                    id);
-                payload.clear();
+    if (auto details = getContactInfo(id)) {
+        if (!details->confirmed) {
+            auto convId = convModule()->getOneToOneConversation(id);
+            if (convId.empty())
+                return;
+            // In this case, the TrustRequest was sent but never confirmed (cause the contact was
+            // offline maybe) To avoid the contact to never receive the conv request, retry there
+            std::lock_guard lock(configurationMutex_);
+            if (accountManager_) {
+                // Retrieve cached payload for trust request.
+                auto requestPath = cachePath_ / "requests" / id;
+                std::vector<uint8_t> payload;
+                try {
+                    payload = fileutils::loadFile(requestPath);
+                } catch (...) {
+                }
+                if (payload.size() >= 64000) {
+                    JAMI_WARNING(
+                        "[Account {:s}] Trust request for contact {:s} is too big, reset payload",
+                        getAccountID(),
+                        id);
+                    payload.clear();
+                }
+                accountManager_->sendTrustRequest(id, convId, payload);
             }
-
-            accountManager_->sendTrustRequest(id, convId, payload);
         }
     }
 }
@@ -2914,6 +2912,13 @@ JamiAccount::getContactDetails(const std::string& uri) const
                            : std::map<std::string, std::string> {};
 }
 
+std::optional<Contact>
+JamiAccount::getContactInfo(const std::string& uri) const
+{
+    std::lock_guard lock(configurationMutex_);
+    return accountManager_ ? accountManager_->getContactInfo(uri) : std::nullopt;
+}
+
 std::vector<std::map<std::string, std::string>>
 JamiAccount::getContacts(bool includeRemoved) const
 {
diff --git a/src/jamidht/jamiaccount.h b/src/jamidht/jamiaccount.h
index d0049f6adde159b3de06f83ade93f4c440a33191..1e5fd5b9a4f8a8c784f1c3237091a0f1f5aacdcb 100644
--- a/src/jamidht/jamiaccount.h
+++ b/src/jamidht/jamiaccount.h
@@ -305,6 +305,7 @@ public:
     /// Obtain details about one account contact in serializable form.
     ///
     std::map<std::string, std::string> getContactDetails(const std::string& uri) const;
+    std::optional<Contact> getContactInfo(const std::string& uri) const;
 
     void sendTrustRequest(const std::string& to, const std::vector<uint8_t>& payload);
     void sendMessage(const std::string& to,