diff --git a/src/account.h b/src/account.h
index 99c960e49e1d74e843e18a080a11623c87e71f88..40cbf6507e612783096e70b77f4fc217aa501c0e 100644
--- a/src/account.h
+++ b/src/account.h
@@ -324,7 +324,9 @@ public:
                                 const std::string& /*commitId*/) {};
 
     // Invites
-    virtual void onConversationRequest(const std::string& /* from */, const Json::Value&) {};
+    virtual void onConversationRequest(const std::string& /*from*/, const Json::Value&) {};
+    virtual void onNeedConversationRequest(const std::string& /*from*/,
+                                           const std::string& /*conversationId*/) {};
 
     /**
      * Helper function used to load the default codec order from the codec factory
diff --git a/src/jamidht/account_manager.h b/src/jamidht/account_manager.h
index b6b90deb4df634a71331dd4681a48edd8c0f2bb6..945f916f428b242ee2145214008d2eed26240d20 100644
--- a/src/jamidht/account_manager.h
+++ b/src/jamidht/account_manager.h
@@ -21,6 +21,7 @@
 #include "config.h"
 #endif
 
+#include "jamidht/conversation.h"
 #include "contact_list.h"
 #include "logger.h"
 #if HAVE_RINGNS
@@ -45,6 +46,8 @@ struct AccountInfo
 {
     dht::crypto::Identity identity;
     std::unique_ptr<ContactList> contacts;
+    std::vector<ConvInfo> conversations;
+    std::map<std::string, ConversationRequest> conversationsRequests;
     std::string accountId;
     std::string deviceId;
     std::shared_ptr<dht::Value> announce;
@@ -211,6 +214,20 @@ public:
     void removeContact(const std::string& uri, bool banned = true);
     std::vector<std::map<std::string, std::string>> getContacts() const;
 
+    // Conversations
+    void setConversations(const std::vector<ConvInfo>& newConv)
+    {
+        if (info_) {
+            info_->conversations = newConv;
+        }
+    }
+    void setConversationsRequests(const std::map<std::string, ConversationRequest>& newConvReq)
+    {
+        if (info_) {
+            info_->conversationsRequests = newConvReq;
+        }
+    }
+
     /** Obtain details about one account contact in serializable form. */
     std::map<std::string, std::string> getContactDetails(const std::string& uri) const;
 
diff --git a/src/jamidht/accountarchive.cpp b/src/jamidht/accountarchive.cpp
index c7b6bc0ab00e3018066ef403cab649a26fff37f1..4c54fe611bb4ed613c8400a864a0a96ab818b656 100644
--- a/src/jamidht/accountarchive.cpp
+++ b/src/jamidht/accountarchive.cpp
@@ -73,6 +73,15 @@ AccountArchive::deserialize(const std::vector<uint8_t>& dat)
                         if (h != dht::InfoHash {})
                             contacts.emplace(h, Contact {*citr});
                     }
+                } else if (key.compare(Conf::CONVERSATIONS_KEY) == 0) {
+                    for (Json::ValueIterator citr = itr->begin(); citr != itr->end(); citr++) {
+                        conversations.emplace_back(ConvInfo(*citr));
+                    }
+                } else if (key.compare(Conf::CONVERSATIONS_REQUESTS_KEY) == 0) {
+                    for (Json::ValueIterator citr = itr->begin(); citr != itr->end(); citr++) {
+                        conversationsRequests.emplace(citr.key().asString(),
+                                                      ConversationRequest(*citr));
+                    }
                 } else if (key.compare(Conf::ETH_KEY) == 0) {
                     eth_key = base64::decode(itr->asString());
                 } else if (key.compare(Conf::RING_ACCOUNT_CRL) == 0) {
@@ -120,6 +129,20 @@ AccountArchive::serialize() const
             jsonContacts[c.first.toString()] = c.second.toJson();
     }
 
+    if (not conversations.empty()) {
+        Json::Value& jsonConversations = root[Conf::CONVERSATIONS_KEY];
+        for (const auto& c : conversations) {
+            jsonConversations.append(c.toJson());
+        }
+    }
+
+    if (not conversationsRequests.empty()) {
+        Json::Value& jsonConversationsReqs = root[Conf::CONVERSATIONS_REQUESTS_KEY];
+        for (const auto& [key, value] : conversationsRequests) {
+            jsonConversationsReqs[key] = value.toJson();
+        }
+    }
+
     Json::StreamWriterBuilder wbuilder;
     wbuilder["commentStyle"] = "None";
     wbuilder["indentation"] = "";
diff --git a/src/jamidht/accountarchive.h b/src/jamidht/accountarchive.h
index f1b442059165b3162589d1a72f01f71cd6b35078..e03bd3c6b3956fda1f3ac8a6f27c1a5796717e34 100644
--- a/src/jamidht/accountarchive.h
+++ b/src/jamidht/accountarchive.h
@@ -18,6 +18,7 @@
 #pragma once
 
 #include "jami_contact.h"
+#include "jamidht/jamiaccount.h"
 #include "fileutils.h"
 
 #include <opendht/crypto.h>
@@ -49,6 +50,10 @@ struct AccountArchive
     /** Contacts */
     std::map<dht::InfoHash, Contact> contacts;
 
+    // Conversations
+    std::vector<ConvInfo> conversations;
+    std::map<std::string, ConversationRequest> conversationsRequests;
+
     /** Account configuration */
     std::map<std::string, std::string> config;
 
diff --git a/src/jamidht/archive_account_manager.cpp b/src/jamidht/archive_account_manager.cpp
index 96326528c6108328cd654c36352007659c97ef2f..9e35d3157180be1218e839ef7f5cc722d61ed503 100644
--- a/src/jamidht/archive_account_manager.cpp
+++ b/src/jamidht/archive_account_manager.cpp
@@ -348,6 +348,8 @@ ArchiveAccountManager::onArchiveLoaded(AuthContext& ctx, AccountArchive&& a)
     info->contacts = std::make_unique<ContactList>(a.id.second, path_, onChange_);
     info->contacts->setContacts(a.contacts);
     info->contacts->foundAccountDevice(deviceCertificate, ctx.deviceName, clock::now());
+    info->conversations = a.conversations;
+    info->conversationsRequests = a.conversationsRequests;
     info->ethAccount = ethAccount;
     info->announce = std::move(receipt.second);
     info_ = std::move(info);
@@ -559,6 +561,8 @@ ArchiveAccountManager::updateArchive(AccountArchive& archive) const
             archive.config[it.first] = it.second;
     }
     archive.contacts = info_->contacts->getContacts();
+    archive.conversations = info_->conversations;
+    archive.conversationsRequests = info_->conversationsRequests;
 }
 
 void
diff --git a/src/jamidht/configkeys.h b/src/jamidht/configkeys.h
index c9a4d9da5d66687e8776f4950fdf52cf140c91d7..5d0889a2c3a7e60984ad3c4053f9780836a33bce 100644
--- a/src/jamidht/configkeys.h
+++ b/src/jamidht/configkeys.h
@@ -38,6 +38,8 @@ constexpr const char* const RING_ACCOUNT_RECEIPT = "ringAccountReceipt";
 constexpr const char* const RING_ACCOUNT_RECEIPT_SIG = "ringAccountReceiptSignature";
 constexpr const char* const RING_ACCOUNT_CRL = "ringAccountCRL";
 constexpr const char* const RING_ACCOUNT_CONTACTS = "ringAccountContacts";
+constexpr const char* const CONVERSATIONS_KEY = "conversations";
+constexpr const char* const CONVERSATIONS_REQUESTS_KEY = "conversationsRequests";
 constexpr const char* const PROXY_ENABLED_KEY = "proxyEnabled";
 constexpr const char* const PROXY_SERVER_KEY = "proxyServer";
 constexpr const char* const PROXY_PUSH_TOKEN_KEY = "proxyPushToken";
diff --git a/src/jamidht/contact_list.cpp b/src/jamidht/contact_list.cpp
index bcf8338432beb5c1bd9ff16c500faa9820b399f0..e238b94c61cb2d090a74f23eac48937dbd4e913c 100644
--- a/src/jamidht/contact_list.cpp
+++ b/src/jamidht/contact_list.cpp
@@ -275,17 +275,14 @@ ContactList::onTrustRequest(const dht::InfoHash& peer_account,
             // Add trust request
             req = trustRequests_
                       .emplace(peer_account,
-                               TrustRequest {peer_device,
-                                             conversationId,
-                                             received,
-                                             std::move(payload)})
+                               TrustRequest {peer_device, conversationId, received, payload})
                       .first;
         } else {
             // Update trust request
             if (received < req->second.received) {
                 req->second.device = peer_device;
                 req->second.received = received;
-                req->second.payload = std::move(payload);
+                req->second.payload = payload;
             } else {
                 JAMI_DBG("[Contacts] Ignoring outdated trust request from %s",
                          peer_account.toString().c_str());
@@ -294,7 +291,7 @@ ContactList::onTrustRequest(const dht::InfoHash& peer_account,
         saveTrustRequests();
     }
     // Note: call JamiAccount's callback to build ConversationRequest anyway
-    callbacks_.trustRequest(peer_account.toString(), conversationId, payload, received);
+    callbacks_.trustRequest(peer_account.toString(), conversationId, std::move(payload), received);
     return accept;
 }
 
diff --git a/src/jamidht/conversation.cpp b/src/jamidht/conversation.cpp
index 6d4a6cc53b374c9578b4f7a64dd93fe64a72cda1..8a2120b044e7718fb9e56653e6fc9a61a9acf836 100644
--- a/src/jamidht/conversation.cpp
+++ b/src/jamidht/conversation.cpp
@@ -31,6 +31,75 @@
 
 namespace jami {
 
+ConvInfo::ConvInfo(const Json::Value& json)
+{
+    id = json["id"].asString();
+    created = json["created"].asLargestUInt();
+    removed = json["removed"].asLargestUInt();
+    erased = json["erased"].asLargestUInt();
+    for (const auto& v : json["members"]) {
+        members.emplace_back(v["uri"].asString());
+    }
+}
+
+Json::Value
+ConvInfo::toJson() const
+{
+    Json::Value json;
+    json["id"] = id;
+    json["created"] = Json::Int64(created);
+    if (removed) {
+        json["removed"] = Json::Int64(removed);
+    }
+    if (erased) {
+        json["erased"] = Json::Int64(erased);
+    }
+    for (const auto& m : members) {
+        Json::Value member;
+        member["uri"] = m;
+        json["members"].append(member);
+    }
+    return json;
+}
+
+// ConversationRequest
+ConversationRequest::ConversationRequest(const Json::Value& json)
+{
+    received = json["received"].asLargestUInt();
+    declined = json["declined"].asLargestUInt();
+    from = json["from"].asString();
+    conversationId = json["conversationId"].asString();
+    auto& md = json["metadatas"];
+    for (const auto& member : md.getMemberNames()) {
+        metadatas.emplace(member, md[member].asString());
+    }
+}
+
+Json::Value
+ConversationRequest::toJson() const
+{
+    Json::Value json;
+    json["conversationId"] = conversationId;
+    json["from"] = from;
+    json["received"] = static_cast<uint32_t>(received);
+    if (declined)
+        json["declined"] = static_cast<uint32_t>(declined);
+    for (const auto& [key, value] : metadatas) {
+        json["metadatas"][key] = value;
+    }
+    return json;
+}
+
+std::map<std::string, std::string>
+ConversationRequest::toMap() const
+{
+    auto result = metadatas;
+    result["id"] = conversationId;
+    result["from"] = from;
+    result["received"] = std::to_string(received);
+    return result;
+}
+
 class Conversation::Impl
 {
 public:
@@ -128,7 +197,9 @@ Conversation::Impl::convCommitToMap(const std::vector<ConversationCommit>& commi
                 repository_->pinCertificates();
             // Get certificate from repo
             try {
-                auto certPath = fileutils::getFullPath(repoPath(), std::string("devices") + DIR_SEPARATOR_STR + authorDevice + ".crt");
+                auto certPath = fileutils::getFullPath(repoPath(),
+                                                       std::string("devices") + DIR_SEPARATOR_STR
+                                                           + authorDevice + ".crt");
                 auto deviceCert = fileutils::loadTextFile(certPath);
                 cert = std::make_shared<crypto::Certificate>(deviceCert);
                 if (!cert) {
@@ -429,15 +500,18 @@ Conversation::mergeHistory(const std::string& uri)
 
     std::unique_lock<std::mutex> lk(pimpl_->writeMtx_);
     // Validate commit
-    auto newCommits = pimpl_->repository_->validFetch(uri);
+    auto [newCommits, err] = pimpl_->repository_->validFetch(uri);
     if (newCommits.empty()) {
-        JAMI_ERR("Could not validate history with %s", uri.c_str());
+        if (err)
+            JAMI_ERR("Could not validate history with %s", uri.c_str());
+        pimpl_->repository_->removeBranchWith(uri);
         return {};
     }
 
     // If validated, merge
     if (!pimpl_->repository_->merge(remoteHead)) {
         JAMI_ERR("Could not merge history with %s", uri.c_str());
+        pimpl_->repository_->removeBranchWith(uri);
         return {};
     }
     lk.unlock();
diff --git a/src/jamidht/conversation.h b/src/jamidht/conversation.h
index 52bd889e21f981dd347271fa9af55fe49a0bf4c6..f8f3e4c684d00d6f55893a2d55a8f09640f0a6bd 100644
--- a/src/jamidht/conversation.h
+++ b/src/jamidht/conversation.h
@@ -25,9 +25,50 @@
 #include <map>
 #include <memory>
 #include <json/json.h>
+#include <msgpack.hpp>
 
 namespace jami {
 
+/**
+ * A ConversationRequest is a request which corresponds to a trust request, but for conversations
+ * It's signed by the sender and contains the members list, the conversationId, and the metadatas
+ * such as the conversation's vcard, etc. (TODO determine)
+ * Transmitted via the UDP DHT
+ */
+struct ConversationRequest
+{
+    std::string conversationId;
+    std::string from;
+    std::map<std::string, std::string> metadatas;
+
+    time_t received {0};
+    time_t declined {0};
+
+    ConversationRequest() = default;
+    ConversationRequest(const Json::Value& json);
+
+    Json::Value toJson() const;
+    std::map<std::string, std::string> toMap() const;
+
+    MSGPACK_DEFINE_MAP(from, conversationId, metadatas, received, declined)
+};
+
+struct ConvInfo
+{
+    std::string id {};
+    time_t created {0};
+    time_t removed {0};
+    time_t erased {0};
+    std::vector<std::string> members;
+
+    ConvInfo() = default;
+    ConvInfo(const Json::Value& json);
+
+    Json::Value toJson() const;
+
+    MSGPACK_DEFINE_MAP(id, created, removed, erased, members)
+};
+
 class JamiAccount;
 class ConversationRepository;
 enum class ConversationMode;
diff --git a/src/jamidht/conversationrepository.cpp b/src/jamidht/conversationrepository.cpp
index 69844babf043732f1db1c57bd24c42a77c04b9e7..e86e549d45e335c58ba4e31b71db89dff7c45a41 100644
--- a/src/jamidht/conversationrepository.cpp
+++ b/src/jamidht/conversationrepository.cpp
@@ -2714,18 +2714,18 @@ ConversationRepository::resolveVote(const std::string& uri, bool isDevice)
     return {};
 }
 
-std::vector<ConversationCommit>
+std::pair<std::vector<ConversationCommit>, bool>
 ConversationRepository::validFetch(const std::string& remoteDevice) const
 {
     auto newCommit = remoteHead(remoteDevice);
     if (not pimpl_ or newCommit.empty())
-        return {};
+        return {{}, false};
     auto commitsToValidate = pimpl_->behind(newCommit);
     std::reverse(std::begin(commitsToValidate), std::end(commitsToValidate));
     auto isValid = pimpl_->validCommits(commitsToValidate);
     if (isValid)
-        return commitsToValidate;
-    return {};
+        return {commitsToValidate, false};
+    return {{}, true};
 }
 
 bool
@@ -2734,6 +2734,20 @@ ConversationRepository::validClone() const
     return pimpl_->validCommits(logN("", 0));
 }
 
+void
+ConversationRepository::removeBranchWith(const std::string& remoteDevice)
+{
+    git_remote* remote_ptr = nullptr;
+    auto repo = pimpl_->repository();
+    if (git_remote_lookup(&remote_ptr, repo.get(), remoteDevice.c_str()) < 0) {
+        JAMI_WARN("No remote found with id: %s", remoteDevice.c_str());
+        return;
+    }
+    GitRemote remote {remote_ptr, git_remote_free};
+
+    git_remote_prune(remote.get(), nullptr);
+}
+
 std::vector<std::string>
 ConversationRepository::getInitialMembers() const
 {
diff --git a/src/jamidht/conversationrepository.h b/src/jamidht/conversationrepository.h
index 1e8449a2d7b46dea12d3817d82fa7e2d9c36efa8..71457148a6417e153ccfe77b530ba393c6383b21 100644
--- a/src/jamidht/conversationrepository.h
+++ b/src/jamidht/conversationrepository.h
@@ -240,9 +240,21 @@ public:
     std::string voteKick(const std::string& uri, bool isDevice);
     std::string resolveVote(const std::string& uri, bool isDevice);
 
-    std::vector<ConversationCommit> validFetch(const std::string& remoteDevice) const;
+    /**
+     * Validate a fetch with remote device
+     * @param remotedevice
+     * @return the validated commits and if an error occurs
+     */
+    std::pair<std::vector<ConversationCommit>, bool> validFetch(
+        const std::string& remoteDevice) const;
     bool validClone() const;
 
+    /**
+     * Delete branch with remote
+     * @param remoteDevice
+     */
+    void removeBranchWith(const std::string& remoteDevice);
+
     /**
      * One to one util, get initial members
      * @return initial members
@@ -260,7 +272,6 @@ public:
      */
     void refreshMembers() const;
 
-
     /**
      * Because conversations can contains non contacts certificates, this methods
      * loads certificates in conversations into the cert store
diff --git a/src/jamidht/jamiaccount.cpp b/src/jamidht/jamiaccount.cpp
index 5d5c850e28b6ac5886d8723964a54a67553ba4c1..b3a553290b9591395e9697f4fa93015654008a84 100644
--- a/src/jamidht/jamiaccount.cpp
+++ b/src/jamidht/jamiaccount.cpp
@@ -136,77 +136,6 @@ struct VCardMessageCtx
     std::string path;
 };
 
-struct ConvInfo
-{
-    std::string id {};
-    time_t created {0};
-    time_t removed {0};
-    time_t erased {0};
-
-    ConvInfo() = default;
-    ConvInfo(const Json::Value& json)
-    {
-        id = json["id"].asString();
-        created = json["created"].asLargestUInt();
-        removed = json["removed"].asLargestUInt();
-        erased = json["erased"].asLargestUInt();
-    }
-
-    Json::Value toJson() const
-    {
-        Json::Value json;
-        json["id"] = id;
-        json["created"] = Json::Int64(created);
-        if (removed) {
-            json["removed"] = Json::Int64(removed);
-        }
-        if (erased) {
-            json["erased"] = Json::Int64(erased);
-        }
-        return json;
-    }
-
-    MSGPACK_DEFINE_MAP(id, created, removed, erased)
-};
-
-// ConversationRequest
-ConversationRequest::ConversationRequest(const Json::Value& json)
-{
-    received = json["received"].asLargestUInt();
-    declined = json["declined"].asLargestUInt();
-    from = json["from"].asString();
-    conversationId = json["conversationId"].asString();
-    auto& md = json["metadatas"];
-    for (const auto& member : md.getMemberNames()) {
-        metadatas.emplace(member, md[member].asString());
-    }
-}
-
-Json::Value
-ConversationRequest::toJson() const
-{
-    Json::Value json;
-    json["conversationId"] = conversationId;
-    json["from"] = from;
-    json["received"] = static_cast<uint32_t>(received);
-    if (declined)
-        json["declined"] = static_cast<uint32_t>(declined);
-    for (const auto& [key, value] : metadatas) {
-        json["metadatas"][key] = value;
-    }
-    return json;
-}
-
-std::map<std::string, std::string>
-ConversationRequest::toMap() const
-{
-    auto result = metadatas;
-    result["id"] = conversationId;
-    result["from"] = from;
-    result["received"] = std::to_string(received);
-    return result;
-}
-
 namespace Migration {
 
 enum class State { // Contains all the Migration states
@@ -1144,6 +1073,7 @@ JamiAccount::addDevice(const std::string& password)
 bool
 JamiAccount::exportArchive(const std::string& destinationPath, const std::string& password)
 {
+    saveConvInfos(); // Refresh members known
     if (auto manager = dynamic_cast<ArchiveAccountManager*>(accountManager_.get())) {
         return manager->exportArchive(destinationPath, password);
     }
@@ -1238,6 +1168,7 @@ JamiAccount::loadAccount(const std::string& archive_password,
                             req.metadatas = ConversationRepository::infosFromVCard(details);
                             acc->conversationsRequests_[conversationId] = std::move(req);
                         }
+                        acc->saveConvRequests();
                         emitSignal<DRing::ConfigurationSignal::IncomingTrustRequest>(
                             acc->getAccountID(), uri, payload, received);
                     }
@@ -1389,6 +1320,17 @@ JamiAccount::loadAccount(const std::string& archive_password,
                         details[key] = value;
                     setAccountDetails(details);
 
+                    {
+                        std::lock_guard<std::mutex> lkConv(conversationsMtx_);
+                        convInfos_ = info.conversations;
+                    }
+                    {
+                        std::lock_guard<std::mutex> lkReq(conversationsRequestsMtx_);
+                        conversationsRequests_ = info.conversationsRequests;
+                    }
+                    saveConvInfos();
+                    saveConvRequests();
+
                     if (not info.photo.empty() or not displayName_.empty())
                         emitSignal<DRing::ConfigurationSignal::AccountProfileReceived>(getAccountID(),
                                                                                        displayName_,
@@ -2697,6 +2639,33 @@ JamiAccount::doRegister_()
                         });
                 }
             }
+
+            for (const auto& c : convInfos_) {
+                if (!c.removed) {
+                    auto it = conversations_.find(c.id);
+                    if (it == conversations_.end()) {
+                        std::shared_ptr<std::atomic_bool> willClone
+                            = std::make_shared<std::atomic_bool>(false);
+                        for (const auto& member : c.members) {
+                            if (member != getUsername()) {
+                                // Try to clone from first other members device found
+                                accountManager_
+                                    ->forEachDevice(dht::InfoHash(member),
+                                                    [w = weak(), convId = c.id, willClone](
+                                                        const dht::InfoHash& dev) {
+                                                        if (willClone->exchange(true))
+                                                            return;
+                                                        auto shared = w.lock();
+                                                        if (!shared)
+                                                            return;
+                                                        shared->cloneConversation(dev.toString(),
+                                                                                  convId);
+                                                    });
+                            }
+                        }
+                    }
+                }
+            }
         }
     } catch (const std::exception& e) {
         JAMI_ERR("Error registering DHT account: %s", e.what());
@@ -3393,6 +3362,16 @@ JamiAccount::acceptTrustRequest(const std::string& from)
 bool
 JamiAccount::discardTrustRequest(const std::string& from)
 {
+    // Remove 1:1 generated conv requests
+    auto requests = getTrustRequests();
+    for (const auto& req : requests) {
+        if (req.at(DRing::Account::TrustRequest::FROM) == from) {
+            declineConversationRequest(req.at(DRing::Account::TrustRequest::CONVERSATIONID));
+        }
+    }
+    saveConvRequests();
+
+    // Remove trust request
     std::lock_guard<std::mutex> lock(configurationMutex_);
     if (accountManager_)
         return accountManager_->discardTrustRequest(from);
@@ -3909,7 +3888,9 @@ JamiAccount::acceptConversationRequest(const std::string& conversationId)
     std::unique_lock<std::mutex> lk(conversationsRequestsMtx_);
     auto request = conversationsRequests_.find(conversationId);
     if (request == conversationsRequests_.end()) {
-        JAMI_WARN("Request not found for conversation %s", conversationId.c_str());
+        JAMI_WARN("[Account %s] Request not found for conversation %s",
+                  getAccountID().c_str(),
+                  conversationId.c_str());
         return;
     }
     {
@@ -3918,7 +3899,7 @@ JamiAccount::acceptConversationRequest(const std::string& conversationId)
     }
     auto memberHash = dht::InfoHash(request->second.from);
     if (!memberHash) {
-        JAMI_WARN("Invalid member detected");
+        JAMI_WARN("Invalid member detected: %s", request->second.from.c_str());
         return;
     }
     forEachDevice(memberHash, [this, request = request->second](const dht::InfoHash& dev) {
@@ -3976,45 +3957,66 @@ JamiAccount::handlePendingConversations()
     std::lock_guard<std::mutex> lk(pendingConversationsFetchMtx_);
     for (auto it = pendingConversationsFetch_.begin(); it != pendingConversationsFetch_.end();) {
         if (it->second.ready) {
-            // Clone and store conversation
-            auto conversationId = it->first;
-            try {
-                auto conversation = std::make_shared<Conversation>(weak(),
-                                                                   it->second.deviceId,
-                                                                   conversationId);
-                if (conversation) {
-                    auto commitId = conversation->join();
-                    ConvInfo info;
-                    info.id = conversationId;
-                    info.created = std::time(nullptr);
-                    convInfos_.emplace_back(info);
-                    {
-                        std::lock_guard<std::mutex> lk(conversationsMtx_);
-                        conversations_.emplace(conversationId, std::move(conversation));
+            dht::ThreadPool::io().run([w = weak(),
+                                       conversationId = it->first,
+                                       deviceId = it->second.deviceId]() {
+                auto shared = w.lock();
+                if (!shared)
+                    return;
+                // Clone and store conversation
+                try {
+                    auto conversation = std::make_shared<Conversation>(w, deviceId, conversationId);
+                    if (!conversation->isMember(shared->getUsername(), true)) {
+                        JAMI_ERR("Conversation cloned but doesn't seems to be a valid member");
+                        conversation->erase();
+                        return;
                     }
-                    if (!commitId.empty()) {
-                        runOnMainThread([w = weak(), conversationId, commitId]() {
-                            if (auto shared = w.lock()) {
-                                std::lock_guard<std::mutex> lk(shared->conversationsMtx_);
-                                auto it = shared->conversations_.find(conversationId);
-                                // Do not sync as it's synched by convInfos
-                                if (it != shared->conversations_.end())
-                                    shared->sendMessageNotification(*it->second, commitId, false);
+                    if (conversation) {
+                        auto commitId = conversation->join();
+                        // TODO change convInfos to map<id, ConvInfo>
+                        auto found = false;
+                        for (const auto& ci : shared->convInfos_) {
+                            if (ci.id == conversationId) {
+                                found = true;
+                                break;
                             }
-                        });
+                        }
+                        if (!found) {
+                            ConvInfo info;
+                            info.id = conversationId;
+                            info.created = std::time(nullptr);
+                            shared->convInfos_.emplace_back(info);
+                        }
+                        {
+                            std::lock_guard<std::mutex> lk(shared->conversationsMtx_);
+                            shared->conversations_.emplace(conversationId, std::move(conversation));
+                        }
+                        if (!commitId.empty()) {
+                            runOnMainThread([w, conversationId, commitId]() {
+                                if (auto shared = w.lock()) {
+                                    std::lock_guard<std::mutex> lk(shared->conversationsMtx_);
+                                    auto it = shared->conversations_.find(conversationId);
+                                    // Do not sync as it's synched by convInfos
+                                    if (it != shared->conversations_.end())
+                                        shared->sendMessageNotification(*it->second,
+                                                                        commitId,
+                                                                        false);
+                                }
+                            });
+                        }
+                        shared->saveConvInfos();
+                        // Inform user that the conversation is ready
+                        emitSignal<DRing::ConversationSignal::ConversationReady>(shared->accountID_,
+                                                                                 conversationId);
                     }
-                    saveConvInfos();
-                    // Inform user that the conversation is ready
-                    emitSignal<DRing::ConversationSignal::ConversationReady>(accountID_,
-                                                                             conversationId);
+                } catch (const std::exception& e) {
+                    emitSignal<DRing::ConversationSignal::OnConversationError>(shared->accountID_,
+                                                                               conversationId,
+                                                                               EFETCH,
+                                                                               e.what());
+                    JAMI_WARN("Something went wrong when cloning conversation: %s", e.what());
                 }
-            } catch (const std::exception& e) {
-                emitSignal<DRing::ConversationSignal::OnConversationError>(getAccountID(),
-                                                                           conversationId,
-                                                                           EFETCH,
-                                                                           e.what());
-                JAMI_WARN("Something went wrong when cloning conversation: %s", e.what());
-            }
+            });
             it = pendingConversationsFetch_.erase(it);
         } else {
             ++it;
@@ -4052,19 +4054,18 @@ JamiAccount::removeConversation(const std::string& conversationId)
     for (auto& info : convInfos_) {
         if (info.id == conversationId) {
             info.removed = std::time(nullptr);
-            saveConvInfos();
-            if (hasMembers) {
-                // Sync now, because it can take some time to really removes the datas
-                runOnMainThread([w = weak()]() {
-                    // Invite connected devices for the same user
-                    auto shared = w.lock();
-                    if (!shared or !shared->accountManager_)
-                        return;
+            // Sync now, because it can take some time to really removes the datas
+            runOnMainThread([w = weak(), hasMembers]() {
+                // Invite connected devices for the same user
+                auto shared = w.lock();
+                if (!shared or !shared->accountManager_)
+                    return;
 
-                    // Send to connected devices
+                shared->saveConvInfos();
+                // Send to connected devices
+                if (hasMembers)
                     shared->syncWithConnected();
-                });
-            }
+            });
             break;
         }
     }
@@ -4194,7 +4195,7 @@ JamiAccount::addConversationMember(const std::string& conversationId,
                                    const std::string& contactUri,
                                    bool sendRequest)
 {
-    std::lock_guard<std::mutex> lk(conversationsMtx_);
+    std::unique_lock<std::mutex> lk(conversationsMtx_);
     // Add a new member in the conversation
     auto it = conversations_.find(conversationId);
     if (it == conversations_.end()) {
@@ -4208,7 +4209,9 @@ JamiAccount::addConversationMember(const std::string& conversationId,
                  conversationId.c_str());
         // Note: This should not be necessary, but if for whatever reason the other side didn't join
         // we should not forbid new invites
-        sendTextMessage(contactUri, it->second->generateInvitation());
+        auto invite = it->second->generateInvitation();
+        lk.unlock();
+        sendTextMessage(contactUri, invite);
         return true;
     }
 
@@ -4222,7 +4225,7 @@ JamiAccount::addConversationMember(const std::string& conversationId,
             auto shared = w.lock();
             if (not shared or messages.empty())
                 return; // should not happen
-            std::lock_guard<std::mutex> lk(shared->conversationsMtx_);
+            std::unique_lock<std::mutex> lk(shared->conversationsMtx_);
             // Add a new member in the conversation
             auto it = shared->conversations_.find(conversationId);
             if (it == shared->conversations_.end()) {
@@ -4234,9 +4237,12 @@ JamiAccount::addConversationMember(const std::string& conversationId,
             emitSignal<DRing::ConversationSignal::MessageReceived>(shared->getAccountID(),
                                                                    conversationId,
                                                                    message);
-            if (sendRequest)
-                shared->sendTextMessage(contactUri, it->second->generateInvitation());
             shared->sendMessageNotification(*it->second, commitId, true);
+            if (sendRequest) {
+                auto invite = it->second->generateInvitation();
+                lk.unlock();
+                shared->sendTextMessage(contactUri, invite);
+            }
         },
         commitId,
         1);
@@ -4284,7 +4290,7 @@ JamiAccount::removeConversationMember(const std::string& conversationId,
 }
 
 std::vector<std::map<std::string, std::string>>
-JamiAccount::getConversationMembers(const std::string& conversationId)
+JamiAccount::getConversationMembers(const std::string& conversationId) const
 {
     std::lock_guard<std::mutex> lk(conversationsMtx_);
     auto conversation = conversations_.find(conversationId);
@@ -4541,9 +4547,16 @@ JamiAccount::fetchNewCommits(const std::string& peer,
             if (pendingConversationsFetch_.find(conversationId) != pendingConversationsFetch_.end())
                 return;
         }
-        JAMI_WARN("[Account %s] Could not find conversation %s",
+        for (const auto& ci : convInfos_) {
+            if (ci.id == conversationId) {
+                cloneConversation(deviceId, conversationId);
+                return;
+            }
+        }
+        JAMI_WARN("[Account %s] Could not find conversation %s, ask for an invite",
                   getAccountID().c_str(),
                   conversationId.c_str());
+        sendTextMessage(peer, {{"application/invite", conversationId}});
     }
 }
 
@@ -4551,9 +4564,10 @@ void
 JamiAccount::onConversationRequest(const std::string& from, const Json::Value& value)
 {
     ConversationRequest req(value);
-    JAMI_INFO("[Account %s] Receive a new conversation request for conversation %s",
+    JAMI_INFO("[Account %s] Receive a new conversation request for conversation %s from %s",
               getAccountID().c_str(),
-              req.conversationId.c_str());
+              req.conversationId.c_str(),
+              from.c_str());
     auto convId = req.conversationId;
     req.from = from;
 
@@ -4578,6 +4592,29 @@ JamiAccount::onConversationRequest(const std::string& from, const Json::Value& v
                                                                        req.toMap());
 }
 
+void
+JamiAccount::onNeedConversationRequest(const std::string& from, const std::string& conversationId)
+{
+    // Check if conversation exists
+    std::unique_lock<std::mutex> lk(conversationsMtx_);
+    auto itConv = conversations_.find(conversationId);
+    if (itConv != conversations_.end() && !itConv->second->isRemoving()) {
+        // Check if isMember
+        if (!itConv->second->isMember(from, true)) {
+            JAMI_WARN("%s is asking a new invite for %s, but not a member",
+                      from.c_str(),
+                      conversationId.c_str());
+            return;
+        }
+
+        // Send new invite
+        auto invite = itConv->second->generateInvitation();
+        lk.unlock();
+        JAMI_DBG("%s is asking a new invite for %s", from.c_str(), conversationId.c_str());
+        sendTextMessage(from, invite);
+    }
+}
+
 void
 JamiAccount::cacheTurnServers()
 {
@@ -5007,49 +5044,7 @@ JamiAccount::cacheSyncConnection(std::shared_ptr<ChannelSocket>&& socket,
                     conversationsRequests_.erase(convId);
                 }
                 if (not removed) {
-                    if (!isConversation(convId)) {
-                        {
-                            std::lock_guard<std::mutex> lk(pendingConversationsFetchMtx_);
-                            auto it = pendingConversationsFetch_.find(convId);
-                            if (it != pendingConversationsFetch_.end()) // Already pending
-                                return len;
-                            pendingConversationsFetch_[convId] = PendingConversationFetch {};
-                        }
-                        std::lock_guard<std::mutex> lkCM(connManagerMtx_);
-                        if (!connectionManager_)
-                            return len;
-                        connectionManager_->connectDevice(
-                            DeviceId(deviceId),
-                            std::string("git://").append(deviceId).append("/").append(convId),
-                            [this, convId](std::shared_ptr<ChannelSocket> socket,
-                                           const DeviceId& deviceId) {
-                                if (socket) {
-                                    std::unique_lock<std::mutex> lk(pendingConversationsFetchMtx_);
-                                    auto& pending = pendingConversationsFetch_[convId];
-                                    if (!pending.ready) {
-                                        pending.ready = true;
-                                        pending.deviceId = deviceId.toString();
-                                        lk.unlock();
-                                        // Save the git socket
-                                        addGitSocket(deviceId.toString(), convId, socket);
-                                        checkConversationsEvents();
-                                    } else {
-                                        lk.unlock();
-                                        socket->shutdown();
-                                    }
-                                }
-                            });
-
-                        JAMI_INFO(
-                            "[Account %s] New conversation detected: %s. Ask device %s to clone it",
-                            getAccountID().c_str(),
-                            convId.c_str(),
-                            deviceId.c_str());
-                    } else {
-                        JAMI_INFO("[Account %s] Already have conversation %s",
-                                  getAccountID().c_str(),
-                                  convId.c_str());
-                    }
+                    cloneConversation(deviceId, convId);
                 } else {
                     {
                         std::lock_guard<std::mutex> lk(conversationsMtx_);
@@ -5179,14 +5174,13 @@ JamiAccount::loadConvInfos()
         auto file = fileutils::loadFile("convInfo", idPath_);
         // load values
         msgpack::object_handle oh = msgpack::unpack((const char*) file.data(), file.size());
-        oh.get().convert(convInfo);
+        oh.get().convert(convInfos_);
     } catch (const std::exception& e) {
         JAMI_WARN("[convInfo] error loading convInfo: %s", e.what());
         return;
     }
 
     for (auto& info : convInfo) {
-        convInfos_.emplace_back(info);
         std::lock_guard<std::mutex> lk(conversationsMtx_);
         auto itConv = conversations_.find(info.id);
         if (itConv != conversations_.end() && info.removed) {
@@ -5200,6 +5194,20 @@ JamiAccount::saveConvInfos() const
 {
     std::ofstream file(idPath_ + DIR_SEPARATOR_STR "convInfo", std::ios::trunc | std::ios::binary);
     msgpack::pack(file, convInfos_);
+
+    // Update infos
+    // TODO avoid to do this for all conversations, just last updated if possible
+    for (auto& c : convInfos_) {
+        c.members.clear();
+        auto members = getConversationMembers(c.id);
+        for (const auto& member : members) {
+            auto uri = member.find("uri");
+            if (uri != member.end()) {
+                c.members.emplace_back(uri->second);
+            }
+        }
+    }
+    accountManager_->setConversations(convInfos_);
 }
 
 void
@@ -5224,6 +5232,9 @@ JamiAccount::saveConvRequests()
     std::ofstream file(idPath_ + DIR_SEPARATOR_STR "convRequests",
                        std::ios::trunc | std::ios::binary);
     msgpack::pack(file, conversationsRequests_);
+
+    // Update infos
+    accountManager_->setConversationsRequests(conversationsRequests_);
 }
 
 void
@@ -5242,11 +5253,12 @@ JamiAccount::removeRepository(const std::string& conversationId, bool sync, bool
         for (auto& info : convInfos_) {
             if (info.id == conversationId) {
                 info.erased = std::time(nullptr);
-                saveConvInfos();
                 runOnMainThread([w = weak()]() {
                     // Send to connected devices
-                    if (auto shared = w.lock())
+                    if (auto shared = w.lock()) {
+                        shared->saveConvInfos(); // will lock conversationsMtx_
                         shared->syncWithConnected();
+                    }
                 });
                 break;
             }
@@ -5345,4 +5357,51 @@ JamiAccount::monitor() const
         connectionManager_->monitor();
 }
 
+void
+JamiAccount::cloneConversation(const std::string& deviceId, const std::string& convId)
+{
+    if (!isConversation(convId)) {
+        {
+            std::lock_guard<std::mutex> lk(pendingConversationsFetchMtx_);
+            auto it = pendingConversationsFetch_.find(convId);
+            if (it != pendingConversationsFetch_.end()) // Already pending
+                return;
+            pendingConversationsFetch_[convId] = PendingConversationFetch {};
+        }
+        std::lock_guard<std::mutex> lkCM(connManagerMtx_);
+        if (!connectionManager_)
+            return;
+        connectionManager_
+            ->connectDevice(DeviceId(deviceId),
+                            "git://" + deviceId + "/" + convId,
+                            [this, convId](std::shared_ptr<ChannelSocket> socket,
+                                           const DeviceId& deviceId) {
+                                if (socket) {
+                                    std::unique_lock<std::mutex> lk(pendingConversationsFetchMtx_);
+                                    auto& pending = pendingConversationsFetch_[convId];
+                                    if (!pending.ready) {
+                                        pending.ready = true;
+                                        pending.deviceId = deviceId.toString();
+                                        lk.unlock();
+                                        // Save the git socket
+                                        addGitSocket(deviceId.toString(), convId, socket);
+                                        checkConversationsEvents();
+                                    } else {
+                                        lk.unlock();
+                                        socket->shutdown();
+                                    }
+                                }
+                            });
+
+        JAMI_INFO("[Account %s] New conversation detected: %s. Ask device %s to clone it",
+                  getAccountID().c_str(),
+                  convId.c_str(),
+                  deviceId.c_str());
+    } else {
+        JAMI_INFO("[Account %s] Already have conversation %s",
+                  getAccountID().c_str(),
+                  convId.c_str());
+    }
+}
+
 } // namespace jami
diff --git a/src/jamidht/jamiaccount.h b/src/jamidht/jamiaccount.h
index 6a801e8d2c3b730b4eeb902c4d524202cd047a23..98e7fffb325fa8ef322352cbee475d271241133c 100644
--- a/src/jamidht/jamiaccount.h
+++ b/src/jamidht/jamiaccount.h
@@ -31,6 +31,7 @@
 #include "security/diffie-hellman.h"
 #include "sip/sipaccountbase.h"
 #include "dring/datatransfer_interface.h"
+#include "jamidht/conversation.h"
 #include "multiplexed_socket.h"
 
 #include "noncopyable.h"
@@ -84,32 +85,6 @@ class AccountManager;
 struct AccountInfo;
 class SipTransport;
 class ChanneledOutgoingTransfer;
-class Conversation;
-struct ConvInfo;
-
-/**
- * A ConversationRequest is a request which corresponds to a trust request, but for conversations
- * It's signed by the sender and contains the members list, the conversationId, and the metadatas
- * such as the conversation's vcard, etc. (TODO determine)
- * Transmitted via the UDP DHT
- */
-struct ConversationRequest
-{
-    std::string conversationId;
-    std::string from;
-    std::map<std::string, std::string> metadatas;
-
-    time_t received {0};
-    time_t declined {0};
-
-    ConversationRequest() = default;
-    ConversationRequest(const Json::Value& json);
-
-    Json::Value toJson() const;
-    std::map<std::string, std::string> toMap() const;
-
-    MSGPACK_DEFINE_MAP(conversationId, metadatas, received, declined)
-};
 
 using SipConnectionKey = std::pair<std::string /* accountId */, DeviceId>;
 using GitSocketList = std::map<std::string,                            /* device Id */
@@ -527,7 +502,7 @@ public:
                                   const std::string& contactUri,
                                   bool isDevice = false);
     std::vector<std::map<std::string, std::string>> getConversationMembers(
-        const std::string& conversationId);
+        const std::string& conversationId) const;
 
     // Message send/load
     void sendMessage(const std::string& conversationId,
@@ -568,9 +543,18 @@ public:
 
     // Invites
     void onConversationRequest(const std::string& from, const Json::Value&) override;
+    void onNeedConversationRequest(const std::string& from,
+                                   const std::string& conversationId) override;
 
     void monitor() const;
 
+    /**
+     * Clone a conversation (initial) from device
+     * @param deviceId
+     * @param convId
+     */
+    void cloneConversation(const std::string& deviceId, const std::string& convId);
+
 private:
     NON_COPYABLE(JamiAccount);
 
@@ -773,7 +757,7 @@ private:
         std::lock_guard<std::mutex> lk(conversationsMtx_);
         return conversations_.find(convId) != conversations_.end();
     }
-    std::vector<ConvInfo> convInfos_;
+    mutable std::vector<ConvInfo> convInfos_;
 
     mutable std::mutex dhtValuesMtx_;
     bool dhtPublicInCalls_ {true};
diff --git a/src/sip/sipaccountbase.cpp b/src/sip/sipaccountbase.cpp
index f575615fadf8f4ab8a54edd9398c494bc7e112c5..93930760329291e8b7a17a51b9aec7f4af5164f9 100644
--- a/src/sip/sipaccountbase.cpp
+++ b/src/sip/sipaccountbase.cpp
@@ -62,6 +62,7 @@ namespace jami {
 static constexpr const char MIME_TYPE_IMDN[] {"message/imdn+xml"};
 static constexpr const char MIME_TYPE_GIT[] {"application/im-gitmessage-id"};
 static constexpr const char MIME_TYPE_INVITE_JSON[] {"application/invite+json"};
+static constexpr const char MIME_TYPE_INVITE[] {"application/invite"};
 static constexpr const char MIME_TYPE_IM_COMPOSING[] {"application/im-iscomposing+xml"};
 static constexpr std::chrono::steady_clock::duration COMPOSING_TIMEOUT {std::chrono::seconds(12)};
 
@@ -589,6 +590,8 @@ SIPAccountBase::onTextMessage(const std::string& id,
                 return;
             }
             onConversationRequest(from, json);
+        } else if (m.first == MIME_TYPE_INVITE) {
+            onNeedConversationRequest(from, m.second);
         }
     }
 
diff --git a/test/unitTest/conversation/conversation.cpp b/test/unitTest/conversation/conversation.cpp
index ddc452576a6cff20493eb777754531833328a150..5bc91e99c2cb0119fa1eac3b36fc00c56895e9e2 100644
--- a/test/unitTest/conversation/conversation.cpp
+++ b/test/unitTest/conversation/conversation.cpp
@@ -675,8 +675,7 @@ ConversationTest::testAddOfflineMemberThenConnects()
 
     CPPUNIT_ASSERT(aliceAccount->addConversationMember(convId, carlaUri));
     Manager::instance().sendRegister(carlaId, true);
-    cv.wait_for(lk, std::chrono::seconds(60));
-    CPPUNIT_ASSERT(requestReceived);
+    CPPUNIT_ASSERT(cv.wait_for(lk, std::chrono::seconds(60), [&] { return requestReceived; }));
 
     carlaAccount->acceptConversationRequest(convId);
     cv.wait_for(lk, std::chrono::seconds(30), [&]() { return conversationReady; });
@@ -995,19 +994,21 @@ ConversationTest::testSendMessageToMultipleParticipants()
     std::mutex mtx;
     std::unique_lock<std::mutex> lk {mtx};
     std::condition_variable cv;
+    bool carlaConnected = false;
     confHandlers.insert(
         DRing::exportable_callback<DRing::ConfigurationSignal::VolatileDetailsChanged>(
             [&](const std::string&, const std::map<std::string, std::string>&) {
                 auto details = carlaAccount->getVolatileAccountDetails();
                 auto daemonStatus = details[DRing::Account::ConfProperties::Registration::STATUS];
                 if (daemonStatus == "REGISTERED") {
+                    carlaConnected = true;
                     cv.notify_one();
                 }
             }));
     DRing::registerSignalHandlers(confHandlers);
 
     Manager::instance().sendRegister(carlaId, true);
-    cv.wait_for(lk, std::chrono::seconds(30));
+    CPPUNIT_ASSERT(cv.wait_for(lk, std::chrono::seconds(60), [&] { return carlaConnected; }));
     confHandlers.clear();
     DRing::unregisterSignalHandlers();
 
@@ -1225,14 +1226,14 @@ ConversationTest::testMemberBanNoBadFile()
     auto carlaAccount = Manager::instance().getAccount<JamiAccount>(carlaId);
     auto carlaUri = carlaAccount->getUsername();
     aliceAccount->trackBuddyPresence(carlaUri, true);
-    Manager::instance().sendRegister(carlaId, true);
 
     std::mutex mtx;
     std::unique_lock<std::mutex> lk {mtx};
     std::condition_variable cv;
     std::map<std::string, std::shared_ptr<DRing::CallbackWrapperBase>> confHandlers;
     bool conversationReady = false, requestReceived = false, memberMessageGenerated = false,
-         voteMessageGenerated = false, messageBobReceived = false, errorDetected = false;
+         voteMessageGenerated = false, messageBobReceived = false, errorDetected = false,
+         carlaConnected = false;
     confHandlers.insert(
         DRing::exportable_callback<DRing::ConversationSignal::ConversationRequestReceived>(
             [&](const std::string& /*accountId*/,
@@ -1241,6 +1242,16 @@ ConversationTest::testMemberBanNoBadFile()
                 requestReceived = true;
                 cv.notify_one();
             }));
+    confHandlers.insert(
+        DRing::exportable_callback<DRing::ConfigurationSignal::VolatileDetailsChanged>(
+            [&](const std::string&, const std::map<std::string, std::string>&) {
+                auto details = carlaAccount->getVolatileAccountDetails();
+                auto daemonStatus = details[DRing::Account::ConfProperties::Registration::STATUS];
+                if (daemonStatus == "REGISTERED") {
+                    carlaConnected = true;
+                    cv.notify_one();
+                }
+            }));
     confHandlers.insert(DRing::exportable_callback<DRing::ConversationSignal::ConversationReady>(
         [&](const std::string& accountId, const std::string& conversationId) {
             if (accountId == bobId && conversationId == convId) {
@@ -1272,6 +1283,8 @@ ConversationTest::testMemberBanNoBadFile()
             cv.notify_one();
         }));
     DRing::registerSignalHandlers(confHandlers);
+    Manager::instance().sendRegister(carlaId, true);
+    CPPUNIT_ASSERT(cv.wait_for(lk, std::chrono::seconds(60), [&] { return carlaConnected; }));
     CPPUNIT_ASSERT(aliceAccount->addConversationMember(convId, bobUri));
     CPPUNIT_ASSERT(cv.wait_for(lk, std::chrono::seconds(30), [&]() {
         return requestReceived && memberMessageGenerated;
@@ -2051,22 +2064,32 @@ ConversationTest::testMemberCannotBanOther()
     auto carlaAccount = Manager::instance().getAccount<JamiAccount>(carlaId);
     auto carlaUri = carlaAccount->getUsername();
     aliceAccount->trackBuddyPresence(carlaUri, true);
-    Manager::instance().sendRegister(carlaId, true);
 
     std::mutex mtx;
     std::unique_lock<std::mutex> lk {mtx};
     std::condition_variable cv;
     std::map<std::string, std::shared_ptr<DRing::CallbackWrapperBase>> confHandlers;
     bool conversationReady = false, requestReceived = false, memberMessageGenerated = false,
-         voteMessageGenerated = false, messageBobReceived = false, errorDetected = false;
+         voteMessageGenerated = false, messageBobReceived = false, errorDetected = false,
+         carlaConnected = false;
     confHandlers.insert(
         DRing::exportable_callback<DRing::ConversationSignal::ConversationRequestReceived>(
-            [&](const std::string& /*accountId*/,
+            [&](const std::string& accountId,
                 const std::string& /* conversationId */,
                 std::map<std::string, std::string> /*metadatas*/) {
                 requestReceived = true;
                 cv.notify_one();
             }));
+    confHandlers.insert(
+        DRing::exportable_callback<DRing::ConfigurationSignal::VolatileDetailsChanged>(
+            [&](const std::string&, const std::map<std::string, std::string>&) {
+                auto details = carlaAccount->getVolatileAccountDetails();
+                auto daemonStatus = details[DRing::Account::ConfProperties::Registration::STATUS];
+                if (daemonStatus == "REGISTERED") {
+                    carlaConnected = true;
+                    cv.notify_one();
+                }
+            }));
     confHandlers.insert(DRing::exportable_callback<DRing::ConversationSignal::ConversationReady>(
         [&](const std::string& accountId, const std::string& conversationId) {
             if (accountId == bobId && conversationId == convId) {
@@ -2098,6 +2121,8 @@ ConversationTest::testMemberCannotBanOther()
             cv.notify_one();
         }));
     DRing::registerSignalHandlers(confHandlers);
+    Manager::instance().sendRegister(carlaId, true);
+    CPPUNIT_ASSERT(cv.wait_for(lk, std::chrono::seconds(60), [&] { return carlaConnected; }));
     CPPUNIT_ASSERT(aliceAccount->addConversationMember(convId, bobUri));
     CPPUNIT_ASSERT(cv.wait_for(lk, std::chrono::seconds(30), [&]() {
         return requestReceived && memberMessageGenerated;
@@ -2107,6 +2132,7 @@ ConversationTest::testMemberCannotBanOther()
     CPPUNIT_ASSERT(
         cv.wait_for(lk, std::chrono::seconds(30), [&]() { return memberMessageGenerated; }));
     requestReceived = false;
+    memberMessageGenerated = false;
     CPPUNIT_ASSERT(aliceAccount->addConversationMember(convId, carlaUri));
     CPPUNIT_ASSERT(cv.wait_for(lk, std::chrono::seconds(30), [&]() {
         return requestReceived && memberMessageGenerated;
@@ -2140,14 +2166,14 @@ ConversationTest::testCheckAdminFakeAVoteIsDetected()
     auto carlaAccount = Manager::instance().getAccount<JamiAccount>(carlaId);
     auto carlaUri = carlaAccount->getUsername();
     aliceAccount->trackBuddyPresence(carlaUri, true);
-    Manager::instance().sendRegister(carlaId, true);
 
     std::mutex mtx;
     std::unique_lock<std::mutex> lk {mtx};
     std::condition_variable cv;
     std::map<std::string, std::shared_ptr<DRing::CallbackWrapperBase>> confHandlers;
     bool conversationReady = false, requestReceived = false, memberMessageGenerated = false,
-         voteMessageGenerated = false, messageBobReceived = false, errorDetected = false;
+         voteMessageGenerated = false, messageBobReceived = false, errorDetected = false,
+         carlaConnected = false;
     confHandlers.insert(
         DRing::exportable_callback<DRing::ConversationSignal::ConversationRequestReceived>(
             [&](const std::string& /*accountId*/,
@@ -2177,6 +2203,16 @@ ConversationTest::testCheckAdminFakeAVoteIsDetected()
             }
             cv.notify_one();
         }));
+    confHandlers.insert(
+        DRing::exportable_callback<DRing::ConfigurationSignal::VolatileDetailsChanged>(
+            [&](const std::string&, const std::map<std::string, std::string>&) {
+                auto details = carlaAccount->getVolatileAccountDetails();
+                auto daemonStatus = details[DRing::Account::ConfProperties::Registration::STATUS];
+                if (daemonStatus == "REGISTERED") {
+                    carlaConnected = true;
+                    cv.notify_one();
+                }
+            }));
     confHandlers.insert(DRing::exportable_callback<DRing::ConversationSignal::OnConversationError>(
         [&](const std::string& /* accountId */,
             const std::string& /* conversationId */,
@@ -2187,6 +2223,8 @@ ConversationTest::testCheckAdminFakeAVoteIsDetected()
             cv.notify_one();
         }));
     DRing::registerSignalHandlers(confHandlers);
+    Manager::instance().sendRegister(carlaId, true);
+    CPPUNIT_ASSERT(cv.wait_for(lk, std::chrono::seconds(60), [&] { return carlaConnected; }));
     CPPUNIT_ASSERT(aliceAccount->addConversationMember(convId, bobUri));
     CPPUNIT_ASSERT(cv.wait_for(lk, std::chrono::seconds(30), [&]() {
         return requestReceived && memberMessageGenerated;
@@ -2224,14 +2262,14 @@ ConversationTest::testVoteNonEmpty()
     auto carlaAccount = Manager::instance().getAccount<JamiAccount>(carlaId);
     auto carlaUri = carlaAccount->getUsername();
     aliceAccount->trackBuddyPresence(carlaUri, true);
-    Manager::instance().sendRegister(carlaId, true);
 
     std::mutex mtx;
     std::unique_lock<std::mutex> lk {mtx};
     std::condition_variable cv;
     std::map<std::string, std::shared_ptr<DRing::CallbackWrapperBase>> confHandlers;
     bool conversationReady = false, requestReceived = false, memberMessageGenerated = false,
-         voteMessageGenerated = false, messageBobReceived = false, errorDetected = false;
+         voteMessageGenerated = false, messageBobReceived = false, errorDetected = false,
+         carlaConnected = false;
     confHandlers.insert(
         DRing::exportable_callback<DRing::ConversationSignal::ConversationRequestReceived>(
             [&](const std::string& /*accountId*/,
@@ -2247,6 +2285,16 @@ ConversationTest::testVoteNonEmpty()
                 cv.notify_one();
             }
         }));
+    confHandlers.insert(
+        DRing::exportable_callback<DRing::ConfigurationSignal::VolatileDetailsChanged>(
+            [&](const std::string&, const std::map<std::string, std::string>&) {
+                auto details = carlaAccount->getVolatileAccountDetails();
+                auto daemonStatus = details[DRing::Account::ConfProperties::Registration::STATUS];
+                if (daemonStatus == "REGISTERED") {
+                    carlaConnected = true;
+                    cv.notify_one();
+                }
+            }));
     confHandlers.insert(DRing::exportable_callback<DRing::ConversationSignal::MessageReceived>(
         [&](const std::string& accountId,
             const std::string& conversationId,
@@ -2271,6 +2319,8 @@ ConversationTest::testVoteNonEmpty()
             cv.notify_one();
         }));
     DRing::registerSignalHandlers(confHandlers);
+    Manager::instance().sendRegister(carlaId, true);
+    CPPUNIT_ASSERT(cv.wait_for(lk, std::chrono::seconds(60), [&] { return carlaConnected; }));
     CPPUNIT_ASSERT(aliceAccount->addConversationMember(convId, bobUri));
     CPPUNIT_ASSERT(cv.wait_for(lk, std::chrono::seconds(30), [&]() {
         return requestReceived && memberMessageGenerated;
@@ -2493,7 +2543,6 @@ ConversationTest::testNoBadFileInInitialCommit()
 
     Manager::instance().sendRegister(carlaId, true);
     CPPUNIT_ASSERT(cv.wait_for(lk, std::chrono::seconds(30), [&] { return carlaConnected; }));
-    JAMI_ERR("@@@@@@@@@@@22");
     CPPUNIT_ASSERT(carlaAccount->addConversationMember(convId, aliceUri));
     CPPUNIT_ASSERT(cv.wait_for(lk, std::chrono::seconds(30), [&]() { return requestReceived; }));
 
@@ -2590,14 +2639,15 @@ ConversationTest::testVoteNoBadFile()
     auto carlaAccount = Manager::instance().getAccount<JamiAccount>(carlaId);
     auto carlaUri = carlaAccount->getUsername();
     aliceAccount->trackBuddyPresence(carlaUri, true);
-    Manager::instance().sendRegister(carlaId, true);
 
     std::mutex mtx;
     std::unique_lock<std::mutex> lk {mtx};
     std::condition_variable cv;
     std::map<std::string, std::shared_ptr<DRing::CallbackWrapperBase>> confHandlers;
     bool conversationReady = false, requestReceived = false, memberMessageGenerated = false,
-         voteMessageGenerated = false, messageBobReceived = false, messageCarlaReceived = false;
+         voteMessageGenerated = false, messageBobReceived = false, messageCarlaReceived = false,
+         carlaConnected = true;
+    ;
     confHandlers.insert(
         DRing::exportable_callback<DRing::ConversationSignal::ConversationRequestReceived>(
             [&](const std::string& /*accountId*/,
@@ -2613,6 +2663,16 @@ ConversationTest::testVoteNoBadFile()
                 cv.notify_one();
             }
         }));
+    confHandlers.insert(
+        DRing::exportable_callback<DRing::ConfigurationSignal::VolatileDetailsChanged>(
+            [&](const std::string&, const std::map<std::string, std::string>&) {
+                auto details = carlaAccount->getVolatileAccountDetails();
+                auto daemonStatus = details[DRing::Account::ConfProperties::Registration::STATUS];
+                if (daemonStatus == "REGISTERED") {
+                    carlaConnected = true;
+                    cv.notify_one();
+                }
+            }));
     confHandlers.insert(DRing::exportable_callback<DRing::ConversationSignal::MessageReceived>(
         [&](const std::string& accountId,
             const std::string& conversationId,
@@ -2635,6 +2695,9 @@ ConversationTest::testVoteNoBadFile()
             cv.notify_one();
         }));
     DRing::registerSignalHandlers(confHandlers);
+    Manager::instance().sendRegister(carlaId, true);
+    CPPUNIT_ASSERT(cv.wait_for(lk, std::chrono::seconds(30), [&]() { return carlaConnected; }));
+
     CPPUNIT_ASSERT(aliceAccount->addConversationMember(convId, bobUri));
     CPPUNIT_ASSERT(cv.wait_for(lk, std::chrono::seconds(30), [&]() {
         return requestReceived && memberMessageGenerated;
@@ -2880,6 +2943,7 @@ ConversationTest::testMemberJoinsNoBadFile()
                        + DIR_SEPARATOR_STR + "convInfo";
     auto ciPathCarla = fileutils::get_data_dir() + DIR_SEPARATOR_STR + carlaAccount->getAccountID()
                        + DIR_SEPARATOR_STR + "convInfo";
+    std::remove(ciPathCarla.c_str());
     std::filesystem::copy(ciPathAlice, ciPathCarla);
 
     // Accept for alice and makes different heads
@@ -2952,6 +3016,7 @@ ConversationTest::testMemberAddedNoCertificate()
                        + DIR_SEPARATOR_STR + "convInfo";
     auto ciPathCarla = fileutils::get_data_dir() + DIR_SEPARATOR_STR + carlaAccount->getAccountID()
                        + DIR_SEPARATOR_STR + "convInfo";
+    std::remove(ciPathCarla.c_str());
     std::filesystem::copy(ciPathAlice, ciPathCarla);
 
     // Remove invite but do not add member certificate
@@ -3033,6 +3098,7 @@ ConversationTest::testMemberJoinsInviteRemoved()
                        + DIR_SEPARATOR_STR + "convInfo";
     auto ciPathCarla = fileutils::get_data_dir() + DIR_SEPARATOR_STR + carlaAccount->getAccountID()
                        + DIR_SEPARATOR_STR + "convInfo";
+    std::remove(ciPathCarla.c_str());
     std::filesystem::copy(ciPathAlice, ciPathCarla);
 
     // Let invited, but add /members + /devices
@@ -3840,6 +3906,7 @@ END:VCARD";
             const std::string& /*from*/,
             const std::vector<uint8_t>& payload,
             time_t /*received*/) {
+            auto pstr = std::string(payload.begin(), payload.begin() + payload.size());
             if (account_id == bobId
                 && std::string(payload.data(), payload.data() + payload.size()) == vcard)
                 requestReceived = true;
@@ -3867,7 +3934,7 @@ END:VCARD";
     aliceAccount->addContact(bobUri);
     std::vector<uint8_t> payload(vcard.begin(), vcard.end());
     aliceAccount->sendTrustRequest(bobUri, payload);
-    CPPUNIT_ASSERT(cv.wait_for(lk, std::chrono::seconds(5), [&]() {
+    CPPUNIT_ASSERT(cv.wait_for(lk, std::chrono::seconds(10), [&]() {
         return !convId.empty() && requestReceived;
     }));
 }
diff --git a/test/unitTest/syncHistory/syncHistory.cpp b/test/unitTest/syncHistory/syncHistory.cpp
index 8fec5e149ccb9782ebf6317160c068a3396f68a5..9a1c93c9d11d9f0be3acab55b1bd7f8749832af7 100644
--- a/test/unitTest/syncHistory/syncHistory.cpp
+++ b/test/unitTest/syncHistory/syncHistory.cpp
@@ -23,6 +23,7 @@
 #include <condition_variable>
 #include <filesystem>
 
+#include "fileutils.h"
 #include "manager.h"
 #include "jamidht/connectionmanager.h"
 #include "jamidht/multiplexed_socket.h"
@@ -59,15 +60,23 @@ private:
     void testCreateConversationThenSync();
     void testCreateConversationWithOnlineDevice();
     void testCreateConversationWithMessagesThenAddDevice();
+    void testCreateMultipleConversationThenAddDevice();
     void testReceivesInviteThenAddDevice();
     void testRemoveConversationOnAllDevices();
+    void testSyncCreateAccountExportDeleteReimportOldBackup();
+    void testSyncCreateAccountExportDeleteReimportWithConvId();
+    void testSyncCreateAccountExportDeleteReimportWithConvReq();
 
     CPPUNIT_TEST_SUITE(SyncHistoryTest);
     CPPUNIT_TEST(testCreateConversationThenSync);
     CPPUNIT_TEST(testCreateConversationWithOnlineDevice);
     CPPUNIT_TEST(testCreateConversationWithMessagesThenAddDevice);
+    CPPUNIT_TEST(testCreateMultipleConversationThenAddDevice);
     CPPUNIT_TEST(testReceivesInviteThenAddDevice);
     CPPUNIT_TEST(testRemoveConversationOnAllDevices);
+    CPPUNIT_TEST(testSyncCreateAccountExportDeleteReimportOldBackup);
+    CPPUNIT_TEST(testSyncCreateAccountExportDeleteReimportWithConvId);
+    CPPUNIT_TEST(testSyncCreateAccountExportDeleteReimportWithConvReq);
     CPPUNIT_TEST_SUITE_END();
 };
 
@@ -333,6 +342,77 @@ SyncHistoryTest::testCreateConversationWithMessagesThenAddDevice()
     CPPUNIT_ASSERT(messages[2]["body"] == "Message 1");
 }
 
+void
+SyncHistoryTest::testCreateMultipleConversationThenAddDevice()
+{
+    auto aliceAccount = Manager::instance().getAccount<JamiAccount>(aliceId);
+    // Start conversation
+    auto convId = aliceAccount->startConversation();
+    aliceAccount->sendMessage(convId, std::string("Message 1"));
+    aliceAccount->sendMessage(convId, std::string("Message 2"));
+    aliceAccount->sendMessage(convId, std::string("Message 3"));
+    std::this_thread::sleep_for(std::chrono::seconds(1));
+    auto convId2 = aliceAccount->startConversation();
+    aliceAccount->sendMessage(convId2, std::string("Message 1"));
+    aliceAccount->sendMessage(convId2, std::string("Message 2"));
+    aliceAccount->sendMessage(convId2, std::string("Message 3"));
+    std::this_thread::sleep_for(std::chrono::seconds(1));
+    auto convId3 = aliceAccount->startConversation();
+    aliceAccount->sendMessage(convId3, std::string("Message 1"));
+    aliceAccount->sendMessage(convId3, std::string("Message 2"));
+    aliceAccount->sendMessage(convId3, std::string("Message 3"));
+    std::this_thread::sleep_for(std::chrono::seconds(1));
+    auto convId4 = aliceAccount->startConversation();
+    aliceAccount->sendMessage(convId4, std::string("Message 1"));
+    aliceAccount->sendMessage(convId4, std::string("Message 2"));
+    aliceAccount->sendMessage(convId4, std::string("Message 3"));
+
+    // Now create alice2
+    auto aliceArchive = std::filesystem::current_path().string() + "/alice.gz";
+    std::remove(aliceArchive.c_str());
+    aliceAccount->exportArchive(aliceArchive);
+    std::map<std::string, std::string> details = DRing::getAccountTemplate("RING");
+    details[ConfProperties::TYPE] = "RING";
+    details[ConfProperties::DISPLAYNAME] = "ALICE2";
+    details[ConfProperties::ALIAS] = "ALICE2";
+    details[ConfProperties::UPNP_ENABLED] = "true";
+    details[ConfProperties::ARCHIVE_PASSWORD] = "";
+    details[ConfProperties::ARCHIVE_PIN] = "";
+    details[ConfProperties::ARCHIVE_PATH] = aliceArchive;
+    alice2Id = Manager::instance().addAccount(details);
+
+    std::mutex mtx;
+    std::unique_lock<std::mutex> lk {mtx};
+    std::condition_variable cv;
+    std::map<std::string, std::shared_ptr<DRing::CallbackWrapperBase>> confHandlers;
+    std::atomic_int conversationReady = 0;
+    confHandlers.insert(
+        DRing::exportable_callback<DRing::ConfigurationSignal::VolatileDetailsChanged>(
+            [&](const std::string&, const std::map<std::string, std::string>&) {
+                auto alice2Account = Manager::instance().getAccount<JamiAccount>(alice2Id);
+                if (!alice2Account)
+                    return;
+                auto details = alice2Account->getVolatileAccountDetails();
+                auto daemonStatus = details[DRing::Account::ConfProperties::Registration::STATUS];
+                if (daemonStatus == "REGISTERED")
+                    cv.notify_one();
+            }));
+    confHandlers.insert(DRing::exportable_callback<DRing::ConversationSignal::ConversationReady>(
+        [&](const std::string& accountId, const std::string& conversationId) {
+            if (accountId == alice2Id) {
+                conversationReady += 1;
+                cv.notify_one();
+            }
+        }));
+    DRing::registerSignalHandlers(confHandlers);
+    confHandlers.clear();
+
+    // Check if conversation is ready
+    CPPUNIT_ASSERT(
+        cv.wait_for(lk, std::chrono::seconds(60), [&]() { return conversationReady == 4; }));
+    DRing::unregisterSignalHandlers();
+}
+
 void
 SyncHistoryTest::testReceivesInviteThenAddDevice()
 {
@@ -463,6 +543,321 @@ SyncHistoryTest::testRemoveConversationOnAllDevices()
     DRing::unregisterSignalHandlers();
 }
 
+void
+SyncHistoryTest::testSyncCreateAccountExportDeleteReimportOldBackup()
+{
+    std::this_thread::sleep_for(std::chrono::seconds(10));
+    auto aliceAccount = Manager::instance().getAccount<JamiAccount>(aliceId);
+    auto bobAccount = Manager::instance().getAccount<JamiAccount>(bobId);
+    auto bobUri = bobAccount->getUsername();
+
+    // Backup alice before start conversation, worst scenario for invites
+    auto aliceArchive = std::filesystem::current_path().string() + "/alice.gz";
+    std::remove(aliceArchive.c_str());
+    aliceAccount->exportArchive(aliceArchive);
+
+    // Start conversation
+    auto convId = aliceAccount->startConversation();
+
+    std::mutex mtx;
+    std::unique_lock<std::mutex> lk {mtx};
+    std::condition_variable cv;
+    std::map<std::string, std::shared_ptr<DRing::CallbackWrapperBase>> confHandlers;
+    auto messageBobReceived = 0, messageAliceReceived = 0;
+    bool requestReceived = false;
+    bool conversationReady = false;
+    bool aliceReady = false;
+    confHandlers.insert(DRing::exportable_callback<DRing::ConversationSignal::MessageReceived>(
+        [&](const std::string& accountId,
+            const std::string& /* conversationId */,
+            std::map<std::string, std::string> /*message*/) {
+            if (accountId == bobId) {
+                messageBobReceived += 1;
+            } else {
+                messageAliceReceived += 1;
+            }
+            cv.notify_one();
+        }));
+    confHandlers.insert(
+        DRing::exportable_callback<DRing::ConversationSignal::ConversationRequestReceived>(
+            [&](const std::string& /*accountId*/,
+                const std::string& /* conversationId */,
+                std::map<std::string, std::string> /*metadatas*/) {
+                requestReceived = true;
+                cv.notify_one();
+            }));
+    confHandlers.insert(DRing::exportable_callback<DRing::ConversationSignal::ConversationReady>(
+        [&](const std::string& accountId, const std::string& conversationId) {
+            if (accountId == bobId) {
+                conversationReady = true;
+                cv.notify_one();
+            }
+
+            if (accountId == alice2Id && conversationId == convId) {
+                conversationReady = true;
+                cv.notify_one();
+            }
+        }));
+    confHandlers.insert(
+        DRing::exportable_callback<DRing::ConfigurationSignal::VolatileDetailsChanged>(
+            [&](const std::string&, const std::map<std::string, std::string>&) {
+                auto alice2Account = Manager::instance().getAccount<JamiAccount>(alice2Id);
+                if (!alice2Account)
+                    return;
+                auto details = alice2Account->getVolatileAccountDetails();
+                auto daemonStatus = details[DRing::Account::ConfProperties::Registration::STATUS];
+                if (daemonStatus == "REGISTERED") {
+                    aliceReady = true;
+                    cv.notify_one();
+                }
+            }));
+    DRing::registerSignalHandlers(confHandlers);
+
+    CPPUNIT_ASSERT(aliceAccount->addConversationMember(convId, bobUri));
+    CPPUNIT_ASSERT(cv.wait_for(lk, std::chrono::seconds(30), [&]() { return requestReceived; }));
+
+    bobAccount->acceptConversationRequest(convId);
+    CPPUNIT_ASSERT(cv.wait_for(lk, std::chrono::seconds(30), [&]() { return conversationReady; }));
+
+    // Wait that alice sees Bob
+    cv.wait_for(lk, std::chrono::seconds(30), [&]() { return messageAliceReceived == 1; });
+
+    // disable account (same as removed)
+    Manager::instance().sendRegister(aliceId, false);
+    std::this_thread::sleep_for(std::chrono::seconds(5));
+
+    std::map<std::string, std::string> details = DRing::getAccountTemplate("RING");
+    details[ConfProperties::TYPE] = "RING";
+    details[ConfProperties::DISPLAYNAME] = "ALICE2";
+    details[ConfProperties::ALIAS] = "ALICE2";
+    details[ConfProperties::UPNP_ENABLED] = "true";
+    details[ConfProperties::ARCHIVE_PASSWORD] = "";
+    details[ConfProperties::ARCHIVE_PIN] = "";
+    details[ConfProperties::ARCHIVE_PATH] = aliceArchive;
+    requestReceived = false;
+    conversationReady = false;
+    alice2Id = Manager::instance().addAccount(details);
+    CPPUNIT_ASSERT(cv.wait_for(lk, std::chrono::seconds(30), [&] { return aliceReady; }));
+    std::this_thread::sleep_for(std::chrono::seconds(10));
+    aliceAccount = Manager::instance().getAccount<JamiAccount>(alice2Id);
+
+    // This will trigger a conversation request. Cause alice2 can't know first conversation
+    bobAccount->sendMessage(convId, std::string("hi"));
+    CPPUNIT_ASSERT(cv.wait_for(lk, std::chrono::seconds(30), [&] { return requestReceived; }));
+
+    aliceAccount->acceptConversationRequest(convId);
+    CPPUNIT_ASSERT(cv.wait_for(lk, std::chrono::seconds(30), [&] { return conversationReady; }));
+
+    messageBobReceived = 0;
+    aliceAccount->sendMessage(convId, std::string("hi"));
+    cv.wait_for(lk, std::chrono::seconds(30), [&]() { return messageBobReceived == 1; });
+}
+
+void
+SyncHistoryTest::testSyncCreateAccountExportDeleteReimportWithConvId()
+{
+    std::this_thread::sleep_for(std::chrono::seconds(10));
+    auto aliceAccount = Manager::instance().getAccount<JamiAccount>(aliceId);
+    auto bobAccount = Manager::instance().getAccount<JamiAccount>(bobId);
+    auto bobUri = bobAccount->getUsername();
+
+    // Start conversation
+    auto convId = aliceAccount->startConversation();
+
+    std::mutex mtx;
+    std::unique_lock<std::mutex> lk {mtx};
+    std::condition_variable cv;
+    std::map<std::string, std::shared_ptr<DRing::CallbackWrapperBase>> confHandlers;
+    auto messageBobReceived = 0, messageAliceReceived = 0;
+    bool requestReceived = false;
+    bool conversationReady = false;
+    bool aliceReady = false;
+    confHandlers.insert(DRing::exportable_callback<DRing::ConversationSignal::MessageReceived>(
+        [&](const std::string& accountId,
+            const std::string& /* conversationId */,
+            std::map<std::string, std::string> /*message*/) {
+            if (accountId == bobId) {
+                messageBobReceived += 1;
+            } else {
+                messageAliceReceived += 1;
+            }
+            cv.notify_one();
+        }));
+    confHandlers.insert(
+        DRing::exportable_callback<DRing::ConversationSignal::ConversationRequestReceived>(
+            [&](const std::string& /*accountId*/,
+                const std::string& /* conversationId */,
+                std::map<std::string, std::string> /*metadatas*/) {
+                requestReceived = true;
+                cv.notify_one();
+            }));
+    confHandlers.insert(DRing::exportable_callback<DRing::ConversationSignal::ConversationReady>(
+        [&](const std::string& accountId, const std::string& conversationId) {
+            if (accountId == bobId) {
+                conversationReady = true;
+                cv.notify_one();
+            }
+
+            if (accountId == alice2Id && conversationId == convId) {
+                conversationReady = true;
+                cv.notify_one();
+            }
+        }));
+    confHandlers.insert(
+        DRing::exportable_callback<DRing::ConfigurationSignal::VolatileDetailsChanged>(
+            [&](const std::string&, const std::map<std::string, std::string>&) {
+                auto alice2Account = Manager::instance().getAccount<JamiAccount>(alice2Id);
+                if (!alice2Account)
+                    return;
+                auto details = alice2Account->getVolatileAccountDetails();
+                auto daemonStatus = details[DRing::Account::ConfProperties::Registration::STATUS];
+                if (daemonStatus == "REGISTERED") {
+                    aliceReady = true;
+                    cv.notify_one();
+                }
+            }));
+    DRing::registerSignalHandlers(confHandlers);
+
+    CPPUNIT_ASSERT(aliceAccount->addConversationMember(convId, bobUri));
+    CPPUNIT_ASSERT(cv.wait_for(lk, std::chrono::seconds(30), [&]() { return requestReceived; }));
+
+    bobAccount->acceptConversationRequest(convId);
+    CPPUNIT_ASSERT(cv.wait_for(lk, std::chrono::seconds(30), [&]() { return conversationReady; }));
+
+    // Wait that alice sees Bob
+    cv.wait_for(lk, std::chrono::seconds(30), [&]() { return messageAliceReceived == 1; });
+
+    // Backup alice after startConversation with member
+    auto aliceArchive = std::filesystem::current_path().string() + "/alice.gz";
+    std::remove(aliceArchive.c_str());
+    aliceAccount->exportArchive(aliceArchive);
+
+    // disable account (same as removed)
+    Manager::instance().sendRegister(aliceId, false);
+    std::this_thread::sleep_for(std::chrono::seconds(5));
+
+    std::map<std::string, std::string> details = DRing::getAccountTemplate("RING");
+    details[ConfProperties::TYPE] = "RING";
+    details[ConfProperties::DISPLAYNAME] = "ALICE2";
+    details[ConfProperties::ALIAS] = "ALICE2";
+    details[ConfProperties::UPNP_ENABLED] = "true";
+    details[ConfProperties::ARCHIVE_PASSWORD] = "";
+    details[ConfProperties::ARCHIVE_PIN] = "";
+    details[ConfProperties::ARCHIVE_PATH] = aliceArchive;
+    requestReceived = false;
+    conversationReady = false;
+    alice2Id = Manager::instance().addAccount(details);
+    CPPUNIT_ASSERT(cv.wait_for(lk, std::chrono::seconds(30), [&] { return aliceReady; }));
+    std::this_thread::sleep_for(std::chrono::seconds(10));
+    aliceAccount = Manager::instance().getAccount<JamiAccount>(alice2Id);
+
+    // Should retrieve conversation, no need for action as the convInfos is in the archive
+    CPPUNIT_ASSERT(cv.wait_for(lk, std::chrono::seconds(30), [&] { return conversationReady; }));
+
+    messageBobReceived = 0;
+    aliceAccount->sendMessage(convId, std::string("hi"));
+    cv.wait_for(lk, std::chrono::seconds(30), [&]() { return messageBobReceived == 1; });
+}
+
+void
+SyncHistoryTest::testSyncCreateAccountExportDeleteReimportWithConvReq()
+{
+    std::this_thread::sleep_for(std::chrono::seconds(10));
+    auto aliceAccount = Manager::instance().getAccount<JamiAccount>(aliceId);
+    auto bobAccount = Manager::instance().getAccount<JamiAccount>(bobId);
+    auto bobUri = bobAccount->getUsername();
+    auto aliceUri = aliceAccount->getUsername();
+
+    // Start conversation
+    auto convId = bobAccount->startConversation();
+
+    std::mutex mtx;
+    std::unique_lock<std::mutex> lk {mtx};
+    std::condition_variable cv;
+    std::map<std::string, std::shared_ptr<DRing::CallbackWrapperBase>> confHandlers;
+    auto messageBobReceived = 0, messageAliceReceived = 0;
+    bool requestReceived = false;
+    bool conversationReady = false;
+    bool aliceReady = false;
+    confHandlers.insert(DRing::exportable_callback<DRing::ConversationSignal::MessageReceived>(
+        [&](const std::string& accountId,
+            const std::string& /* conversationId */,
+            std::map<std::string, std::string> /*message*/) {
+            if (accountId == bobId) {
+                messageBobReceived += 1;
+            } else {
+                messageAliceReceived += 1;
+            }
+            cv.notify_one();
+        }));
+    confHandlers.insert(
+        DRing::exportable_callback<DRing::ConversationSignal::ConversationRequestReceived>(
+            [&](const std::string& /*accountId*/,
+                const std::string& /* conversationId */,
+                std::map<std::string, std::string> /*metadatas*/) {
+                requestReceived = true;
+                cv.notify_one();
+            }));
+    confHandlers.insert(DRing::exportable_callback<DRing::ConversationSignal::ConversationReady>(
+        [&](const std::string& accountId, const std::string& conversationId) {
+            if (accountId == bobId) {
+                conversationReady = true;
+                cv.notify_one();
+            }
+
+            if (accountId == alice2Id && conversationId == convId) {
+                conversationReady = true;
+                cv.notify_one();
+            }
+        }));
+    confHandlers.insert(
+        DRing::exportable_callback<DRing::ConfigurationSignal::VolatileDetailsChanged>(
+            [&](const std::string&, const std::map<std::string, std::string>&) {
+                auto alice2Account = Manager::instance().getAccount<JamiAccount>(alice2Id);
+                if (!alice2Account)
+                    return;
+                auto details = alice2Account->getVolatileAccountDetails();
+                auto daemonStatus = details[DRing::Account::ConfProperties::Registration::STATUS];
+                if (daemonStatus == "REGISTERED") {
+                    aliceReady = true;
+                    cv.notify_one();
+                }
+            }));
+    DRing::registerSignalHandlers(confHandlers);
+
+    CPPUNIT_ASSERT(bobAccount->addConversationMember(convId, aliceUri));
+    CPPUNIT_ASSERT(cv.wait_for(lk, std::chrono::seconds(30), [&]() { return requestReceived; }));
+
+    // Backup alice after startConversation with member
+    auto aliceArchive = std::filesystem::current_path().string() + "/alice.gz";
+    std::remove(aliceArchive.c_str());
+    aliceAccount->exportArchive(aliceArchive);
+
+    // disable account (same as removed)
+    Manager::instance().sendRegister(aliceId, false);
+    std::this_thread::sleep_for(std::chrono::seconds(5));
+
+    std::map<std::string, std::string> details = DRing::getAccountTemplate("RING");
+    details[ConfProperties::TYPE] = "RING";
+    details[ConfProperties::DISPLAYNAME] = "ALICE2";
+    details[ConfProperties::ALIAS] = "ALICE2";
+    details[ConfProperties::UPNP_ENABLED] = "true";
+    details[ConfProperties::ARCHIVE_PASSWORD] = "";
+    details[ConfProperties::ARCHIVE_PIN] = "";
+    details[ConfProperties::ARCHIVE_PATH] = aliceArchive;
+    conversationReady = false;
+    alice2Id = Manager::instance().addAccount(details);
+    CPPUNIT_ASSERT(cv.wait_for(lk, std::chrono::seconds(30), [&] { return aliceReady; }));
+    std::this_thread::sleep_for(std::chrono::seconds(10));
+    aliceAccount = Manager::instance().getAccount<JamiAccount>(alice2Id);
+
+    // Should get the same request as before.
+    aliceAccount->acceptConversationRequest(convId);
+    CPPUNIT_ASSERT(cv.wait_for(lk, std::chrono::seconds(30), [&]() {
+        return conversationReady && messageBobReceived == 1;
+    }));
+}
+
 } // namespace test
 } // namespace jami