diff --git a/src/account.h b/src/account.h
index d747bb65af78387c8530687dd53a7051c009cef2..56574850e94e5950a49630b9690580641ec1765e 100644
--- a/src/account.h
+++ b/src/account.h
@@ -390,6 +390,7 @@ public:
     // once the  backward compatibility is no more required.
     bool isIceCompIdRfc5245Compliant() const { return iceCompIdRfc5245Compliant_; }
     void enableIceCompIdRfc5245Compliance(bool enable) { iceCompIdRfc5245Compliant_ = enable; }
+    void enableAutoLoadConversations(bool enable) { autoLoadConversations_ = enable; }
 
     std::shared_ptr<Call> getCall(const std::string& callId) const
     {
@@ -486,12 +487,15 @@ protected:
 
     bool iceForMediaEnabled_ {true};
     bool iceCompIdRfc5245Compliant_ {false};
+    /**
+     * Auto load conversations when creatinf convModule()
+     */
+    bool autoLoadConversations_ {true};
 
     /**
      * private account codec searching functions
      */
-    std::shared_ptr<SystemCodecInfo> searchCodecByName(const std::string& name,
-                                                        MediaType mediaType);
+    std::shared_ptr<SystemCodecInfo> searchCodecByName(const std::string& name, MediaType mediaType);
     std::vector<unsigned> getAccountCodecInfoIdList(MediaType mediaType) const;
     void setAllCodecsActive(MediaType mediaType, bool active);
     void sortCodec();
diff --git a/src/client/configurationmanager.cpp b/src/client/configurationmanager.cpp
index 5e6381794e7d9b203655b2f6e71364e120ada22d..d2a2179e10bd5c3b635dfcb70a784d2fb54d002d 100644
--- a/src/client/configurationmanager.cpp
+++ b/src/client/configurationmanager.cpp
@@ -242,6 +242,12 @@ setAccountActive(const std::string& accountId, bool enable, bool shutdownConnect
     jami::Manager::instance().setAccountActive(accountId, enable, shutdownConnections);
 }
 
+void
+loadAccountAndConversation(const std::string& accountID, const std::string& convID)
+{
+    jami::Manager::instance().loadAccountAndConversation(accountID, convID);
+}
+
 void
 sendRegister(const std::string& accountId, bool enable)
 {
@@ -264,7 +270,6 @@ getPasswordKey(const std::string& accountID, const std::string& password)
     return {};
 }
 
-
 void
 registerAllAccounts()
 {
@@ -343,9 +348,9 @@ exportOnRing(const std::string& accountId, const std::string& password)
 
 bool
 exportToFile(const std::string& accountId,
-            const std::string& destinationPath,
-            const std::string& scheme,
-            const std::string& password)
+             const std::string& destinationPath,
+             const std::string& scheme,
+             const std::string& password)
 {
     if (const auto account = jami::Manager::instance().getAccount<jami::JamiAccount>(accountId)) {
         return account->exportArchive(destinationPath, scheme, password);
@@ -354,7 +359,10 @@ exportToFile(const std::string& accountId,
 }
 
 bool
-revokeDevice(const std::string& accountId, const std::string& deviceId, const std::string& scheme, const std::string& password)
+revokeDevice(const std::string& accountId,
+             const std::string& deviceId,
+             const std::string& scheme,
+             const std::string& password)
 {
     if (const auto account = jami::Manager::instance().getAccount<jami::JamiAccount>(accountId)) {
         return account->revokeDevice(deviceId, scheme, password);
@@ -553,8 +561,7 @@ setCodecDetails(const std::string& accountId,
                 JAMI_WARN("parameters for %s changed ", foundCodec->name.c_str());
                 if (auto call = jami::Manager::instance().getCurrentCall()) {
                     if (call->getVideoCodec() == foundCodec) {
-                        JAMI_WARN("%s running. Need to restart encoding",
-                                  foundCodec->name.c_str());
+                        JAMI_WARN("%s running. Need to restart encoding", foundCodec->name.c_str());
                         call->restartMediaSender();
                     }
                 }
@@ -1045,7 +1052,10 @@ searchUser(const std::string& account, const std::string& query)
 }
 
 bool
-registerName(const std::string& account, const std::string& name, const std::string& scheme, const std::string& password)
+registerName(const std::string& account,
+             const std::string& name,
+             const std::string& scheme,
+             const std::string& password)
 {
 #if HAVE_RINGNS
     if (auto acc = jami::Manager::instance().getAccount<JamiAccount>(account)) {
diff --git a/src/jami/configurationmanager_interface.h b/src/jami/configurationmanager_interface.h
index a88d2b08357faf8dadb4928f12a9dbfc58b9972b..7bb70e52881f2d122988d4ade9b4dd1b0d908cc3 100644
--- a/src/jami/configurationmanager_interface.h
+++ b/src/jami/configurationmanager_interface.h
@@ -61,6 +61,8 @@ LIBJAMI_PUBLIC void setAccountDetails(const std::string& accountId,
 LIBJAMI_PUBLIC void setAccountActive(const std::string& accountId,
                                      bool active,
                                      bool shutdownConnections = false);
+LIBJAMI_PUBLIC void loadAccountAndConversation(const std::string& accountID,
+                                               const std::string& convID);
 LIBJAMI_PUBLIC std::map<std::string, std::string> getAccountTemplate(const std::string& accountType);
 LIBJAMI_PUBLIC std::string addAccount(const std::map<std::string, std::string>& details,
                                       const std::string& accountId = {});
@@ -84,7 +86,8 @@ LIBJAMI_PUBLIC bool changeAccountPassword(const std::string& accountId,
                                           const std::string& password_old,
                                           const std::string& password_new);
 LIBJAMI_PUBLIC bool isPasswordValid(const std::string& accountId, const std::string& password);
-LIBJAMI_PUBLIC std::vector<uint8_t> getPasswordKey(const std::string& accountId, const std::string& password);
+LIBJAMI_PUBLIC std::vector<uint8_t> getPasswordKey(const std::string& accountId,
+                                                   const std::string& password);
 
 LIBJAMI_PUBLIC bool lookupName(const std::string& account,
                                const std::string& nameserver,
diff --git a/src/jami/jami.h b/src/jami/jami.h
index 536ba75df4d55f1f8240744ce44600e68126d27b..f896c86fed08c544c4410f785837d18b1836ae1b 100644
--- a/src/jami/jami.h
+++ b/src/jami/jami.h
@@ -44,7 +44,8 @@ enum InitFlag {
     LIBJAMI_FLAG_NO_LOCAL_AUDIO = 1 << 6,
     LIBJAMI_FLAG_NO_LOCAL_VIDEO = 1 << 7,
     LIBJAMI_FLAG_NO_LOCAL_MEDIA = LIBJAMI_FLAG_NO_LOCAL_AUDIO | LIBJAMI_FLAG_NO_LOCAL_VIDEO,
-    LIBJAMI_FLAG_NO_AUTOSYNC = 1 << 8
+    LIBJAMI_FLAG_NO_AUTOSYNC = 1 << 8,
+    LIBJAMI_FLAG_NO_AUTOLOAD = 1 << 9 // disable auto loading of accounts and conversations
 };
 
 /**
@@ -69,6 +70,7 @@ LIBJAMI_PUBLIC bool init(enum InitFlag flags) noexcept;
  * Start asynchronously daemon created by init().
  * @returns true if daemon started successfully
  */
+
 LIBJAMI_PUBLIC bool start(const std::filesystem::path& config_file = {}) noexcept;
 
 /**
@@ -185,12 +187,13 @@ private:
 
     // This is quite a ugly method used to transmit templated TFunc with their arguments in the
     // ioContext of the manager to avoid locks for signals.
-    template <typename TCallback>
+    template<typename TCallback>
     auto ioContextWrapper(TCallback&& fun)
     {
-        return [this, fun{std::move(fun)}](auto&&... args) -> decltype(fun(std::forward<decltype(args)>(args)...))
-        {
-            post([fun{std::move(fun)}, forwardArgs=std::make_tuple(std::move(args)...)]() mutable {
+        return [this, fun {std::move(fun)}](
+                   auto&&... args) -> decltype(fun(std::forward<decltype(args)>(args)...)) {
+            post([fun {std::move(fun)},
+                  forwardArgs = std::make_tuple(std::move(args)...)]() mutable {
                 std::apply(std::move(fun), std::move(forwardArgs));
             });
         };
@@ -255,8 +258,8 @@ exportable_callback(std::function<typename Ts::cb_type>&& func,
 template<typename Ts>
 std::pair<std::string, std::shared_ptr<CallbackWrapperBase>>
 exportable_serialized_callback(std::function<typename Ts::cb_type>&& func,
-                    const char* file = CURRENT_FILENAME(),
-                    uint32_t linum = CURRENT_LINE())
+                               const char* file = CURRENT_FILENAME(),
+                               uint32_t linum = CURRENT_LINE())
 {
     return std::make_pair((const std::string&) Ts::name,
                           std::make_shared<SerializedCallbackWrapper<typename Ts::cb_type>>(
diff --git a/src/jamidht/conversation_module.cpp b/src/jamidht/conversation_module.cpp
index 8346b96f34b53d82b9521c1847fd568450d0f0be..678d31f993ef2b3fff6d158ee0c78c538abd3b4a 100644
--- a/src/jamidht/conversation_module.cpp
+++ b/src/jamidht/conversation_module.cpp
@@ -95,7 +95,8 @@ struct SyncedConversation
             pending.reset();
     }
 
-    std::vector<std::map<std::string, std::string>> getMembers(bool includeLeft, bool includeBanned) const
+    std::vector<std::map<std::string, std::string>> getMembers(bool includeLeft,
+                                                               bool includeBanned) const
     {
         // conversation mtx must be locked
         if (conversation)
@@ -296,9 +297,7 @@ public:
     /**
      * @note convInfosMtx_ should be locked
      */
-    void saveConvInfos() const {
-        ConversationModule::saveConvInfos(accountId_, convInfos_);
-    }
+    void saveConvInfos() const { ConversationModule::saveConvInfos(accountId_, convInfos_); }
     /**
      * @note conversationsRequestsMtx_ should be locked
      */
@@ -377,13 +376,18 @@ public:
     std::function<void(std::string, Conversation::BootstrapStatus)> bootstrapCbTest_;
 #endif
 
-    void fixStructures(std::shared_ptr<JamiAccount> account, const std::vector<std::tuple<std::string, std::string, std::string>>& updateContactConv, const std::set<std::string>& toRm);
+    void fixStructures(
+        std::shared_ptr<JamiAccount> account,
+        const std::vector<std::tuple<std::string, std::string, std::string>>& updateContactConv,
+        const std::set<std::string>& toRm);
 
-    void cloneConversationFrom(const std::shared_ptr<SyncedConversation> conv, const std::string& deviceId, const std::string& oldConvId = "");
+    void cloneConversationFrom(const std::shared_ptr<SyncedConversation> conv,
+                               const std::string& deviceId,
+                               const std::string& oldConvId = "");
     void bootstrap(const std::string& convId);
     void cloneConversationFrom(const std::string& conversationId,
-                            const std::string& uri,
-                            const std::string& oldConvId = "");
+                               const std::string& uri,
+                               const std::string& oldConvId = "");
 };
 
 ConversationModule::Impl::Impl(std::weak_ptr<JamiAccount>&& account,
@@ -498,8 +502,8 @@ ConversationModule::Impl::fetchNewCommits(const std::string& peer,
             // it means that the contact was removed but not banned.
             // If he wants a new conversation, they must removes/re-add the contact who declined.
             JAMI_WARNING("[Account {:s}] Received a commit for {}, but conversation is removed",
-                        accountId_,
-                        conversationId);
+                         accountId_,
+                         conversationId);
             return;
         }
     }
@@ -508,7 +512,8 @@ ConversationModule::Impl::fetchNewCommits(const std::string& peer,
         std::lock_guard lk(conversationsRequestsMtx_);
         oldReq = getRequest(conversationId);
         if (oldReq != std::nullopt && oldReq->declined) {
-            JAMI_DEBUG("[Account {}] Received a request for a conversation already declined.", accountId_);
+            JAMI_DEBUG("[Account {}] Received a request for a conversation already declined.",
+                       accountId_);
             return;
         }
     }
@@ -886,10 +891,13 @@ ConversationModule::Impl::removeConversationImpl(SyncedConversation& conv)
     auto members = conv.getMembers(false, false);
     auto isSyncing = !conv.conversation;
     auto hasMembers = !isSyncing // If syncing there is no member to inform
-        && std::find_if(members.begin(), members.end(), [&](const auto& member) {
-            return member.at("uri") == username_;
-        }) != members.end()      // We must be still a member
-        && members.size() != 1;  // If there is only ourself
+                      && std::find_if(members.begin(),
+                                      members.end(),
+                                      [&](const auto& member) {
+                                          return member.at("uri") == username_;
+                                      })
+                             != members.end() // We must be still a member
+                      && members.size() != 1; // If there is only ourself
     conv.info.removed = std::time(nullptr);
     if (isSyncing)
         conv.info.erased = std::time(nullptr);
@@ -1130,9 +1138,12 @@ ConversationModule::Impl::bootstrapCb(std::string convId)
 }
 
 void
-ConversationModule::Impl::fixStructures(std::shared_ptr<JamiAccount> acc, const std::vector<std::tuple<std::string, std::string, std::string>>& updateContactConv, const std::set<std::string>& toRm)
+ConversationModule::Impl::fixStructures(
+    std::shared_ptr<JamiAccount> acc,
+    const std::vector<std::tuple<std::string, std::string, std::string>>& updateContactConv,
+    const std::set<std::string>& toRm)
 {
-    for (const auto& [uri, oldConv, newConv]: updateContactConv) {
+    for (const auto& [uri, oldConv, newConv] : updateContactConv) {
         acc->updateConvForContact(uri, oldConv, newConv);
     }
     ////////////////////////////////////////////////////////////////
@@ -1147,8 +1158,7 @@ ConversationModule::Impl::fixStructures(std::shared_ptr<JamiAccount> acc, const
             if (itConvId != request.end() && itConvFrom != request.end()) {
                 // Check if requests exists or is declined.
                 auto itReq = conversationsRequests_.find(itConvId->second);
-                auto declined = itReq == conversationsRequests_.end()
-                                || itReq->second.declined;
+                auto declined = itReq == conversationsRequests_.end() || itReq->second.declined;
                 if (declined) {
                     JAMI_WARNING("Invalid trust request found: {:s}", itConvId->second);
                     invalidPendingRequests.emplace_back(itConvFrom->second);
@@ -1158,7 +1168,8 @@ ConversationModule::Impl::fixStructures(std::shared_ptr<JamiAccount> acc, const
         auto requestRemoved = false;
         for (auto it = conversationsRequests_.begin(); it != conversationsRequests_.end();) {
             if (it->second.from == username_) {
-                JAMI_WARNING("Detected request from ourself, this makes no sense. Remove {}", it->first);
+                JAMI_WARNING("Detected request from ourself, this makes no sense. Remove {}",
+                             it->first);
                 it = conversationsRequests_.erase(it);
             } else {
                 ++it;
@@ -1167,7 +1178,6 @@ ConversationModule::Impl::fixStructures(std::shared_ptr<JamiAccount> acc, const
         if (requestRemoved) {
             saveConvRequests();
         }
-
     }
     for (const auto& invalidPendingRequest : invalidPendingRequests)
         acc->discardTrustRequest(invalidPendingRequest);
@@ -1181,7 +1191,9 @@ ConversationModule::Impl::fixStructures(std::shared_ptr<JamiAccount> acc, const
 }
 
 void
-ConversationModule::Impl::cloneConversationFrom(const std::shared_ptr<SyncedConversation> conv, const std::string& deviceId, const std::string& oldConvId)
+ConversationModule::Impl::cloneConversationFrom(const std::shared_ptr<SyncedConversation> conv,
+                                                const std::string& deviceId,
+                                                const std::string& oldConvId)
 {
     std::lock_guard lk(conv->mtx);
     const auto& conversationId = conv->info.id;
@@ -1193,7 +1205,8 @@ ConversationModule::Impl::cloneConversationFrom(const std::shared_ptr<SyncedConv
     onNeedSocket_(
         conversationId,
         deviceId,
-        [sthis=shared_from_this(), conv, conversationId, oldConvId, deviceId](const auto& channel) {
+        [sthis = shared_from_this(), conv, conversationId, oldConvId, deviceId](
+            const auto& channel) {
             auto acc = sthis->account_.lock();
             std::lock_guard lk(conv->mtx);
             if (conv->pending && !conv->pending->ready) {
@@ -1205,8 +1218,8 @@ ConversationModule::Impl::cloneConversationFrom(const std::shared_ptr<SyncedConv
                     if (!conv->pending->cloning) {
                         conv->pending->cloning = true;
                         dht::ThreadPool::io().run([w = sthis->weak(),
-                                                    conversationId,
-                                                    deviceId = conv->pending->deviceId]() {
+                                                   conversationId,
+                                                   deviceId = conv->pending->deviceId]() {
                             if (auto sthis = w.lock())
                                 sthis->handlePendingConversation(conversationId, deviceId);
                         });
@@ -1233,10 +1246,7 @@ ConversationModule::Impl::bootstrap(const std::string& convId)
 #ifdef LIBJAMI_TESTABLE
             conv->onBootstrapStatus(bootstrapCbTest_);
 #endif // LIBJAMI_TESTABLE
-            conv->bootstrap(std::bind(&ConversationModule::Impl::bootstrapCb,
-                                      this,
-                                      conv->id()),
-                            kd);
+            conv->bootstrap(std::bind(&ConversationModule::Impl::bootstrapCb, this, conv->id()), kd);
         }
     };
     std::vector<std::string> toClone;
@@ -1271,7 +1281,9 @@ ConversationModule::Impl::bootstrap(const std::string& convId)
 }
 
 void
-ConversationModule::Impl::cloneConversationFrom(const std::string& conversationId, const std::string& uri, const std::string& oldConvId)
+ConversationModule::Impl::cloneConversationFrom(const std::string& conversationId,
+                                                const std::string& uri,
+                                                const std::string& oldConvId)
 {
     auto acc = account_.lock();
     auto memberHash = dht::InfoHash(uri);
@@ -1286,16 +1298,15 @@ ConversationModule::Impl::cloneConversationFrom(const std::string& conversationI
     conv->info.created = std::time(nullptr);
     conv->info.members.emplace(username_);
     conv->info.members.emplace(uri);
-    acc->forEachDevice(
-        memberHash,
-        [w = weak(), conv, conversationId, oldConvId](
-            const std::shared_ptr<dht::crypto::PublicKey>& pk) {
-            auto sthis = w.lock();
-            auto deviceId = pk->getLongId().toString();
-            if (!sthis or deviceId == sthis->deviceId_)
-                return;
-            sthis->cloneConversationFrom(conv, deviceId, oldConvId);
-        });
+    acc->forEachDevice(memberHash,
+                       [w = weak(), conv, conversationId, oldConvId](
+                           const std::shared_ptr<dht::crypto::PublicKey>& pk) {
+                           auto sthis = w.lock();
+                           auto deviceId = pk->getLongId().toString();
+                           if (!sthis or deviceId == sthis->deviceId_)
+                               return;
+                           sthis->cloneConversationFrom(conv, deviceId, oldConvId);
+                       });
     addConvInfo(conv->info);
 }
 
@@ -1312,7 +1323,8 @@ ConversationModule::saveConvRequests(
 
 void
 ConversationModule::saveConvRequestsToPath(
-    const std::filesystem::path& path, const std::map<std::string, ConversationRequest>& conversationsRequests)
+    const std::filesystem::path& path,
+    const std::map<std::string, ConversationRequest>& conversationsRequests)
 {
     auto p = path / "convRequests";
     std::lock_guard lock(dhtnet::fileutils::getFileLock(p));
@@ -1328,7 +1340,8 @@ ConversationModule::saveConvInfos(const std::string& accountId, const ConvInfoMa
 }
 
 void
-ConversationModule::saveConvInfosToPath(const std::filesystem::path& path, const ConvInfoMap& conversations)
+ConversationModule::saveConvInfosToPath(const std::filesystem::path& path,
+                                        const ConvInfoMap& conversations)
 {
     std::ofstream file(path / "convInfo", std::ios::trunc | std::ios::binary);
     msgpack::pack(file, conversations);
@@ -1342,7 +1355,8 @@ ConversationModule::ConversationModule(std::weak_ptr<JamiAccount>&& account,
                                        NeedSocketCb&& onNeedSocket,
                                        NeedSocketCb&& onNeedSwarmSocket,
                                        UpdateConvReq&& updateConvReqCb,
-                                       OneToOneRecvCb&& oneToOneRecvCb)
+                                       OneToOneRecvCb&& oneToOneRecvCb,
+                                       bool autoLoadConversations)
     : pimpl_ {std::make_unique<Impl>(std::move(account),
                                      std::move(needsSyncingCb),
                                      std::move(sendMsgCb),
@@ -1351,7 +1365,9 @@ ConversationModule::ConversationModule(std::weak_ptr<JamiAccount>&& account,
                                      std::move(updateConvReqCb),
                                      std::move(oneToOneRecvCb))}
 {
-    loadConversations();
+    if (autoLoadConversations) {
+        loadConversations();
+    }
 }
 
 #ifdef LIBJAMI_TESTABLE
@@ -1377,13 +1393,15 @@ ConversationModule::loadConversations()
     auto conversationsRepositories = dhtnet::fileutils::readDirectory(
         fileutils::get_data_dir() / pimpl_->accountId_ / "conversations");
 
-    auto contacts = acc->getContacts(true); // Avoid to lock configurationMtx while conv Mtx is locked
+    auto contacts = acc->getContacts(
+        true); // Avoid to lock configurationMtx while conv Mtx is locked
     std::unique_lock<std::mutex> lk(pimpl_->conversationsMtx_);
     std::unique_lock<std::mutex> ilk(pimpl_->convInfosMtx_);
     pimpl_->convInfos_ = convInfos(pimpl_->accountId_);
     pimpl_->conversations_.clear();
 
-    struct Ctx {
+    struct Ctx
+    {
         std::mutex cvMtx;
         std::condition_variable cv;
         std::mutex toRmMtx;
@@ -1420,9 +1438,11 @@ ConversationModule::loadConversations()
                     // If we got a 1:1 conversation, but not in the contact details, it's rather a
                     // duplicate or a weird state
                     auto otherUri = *members.begin();
-                    auto itContact = std::find_if(ctx->contacts.cbegin(), ctx->contacts.cend(), [&](const auto& c) {
-                        return c.at("id") == otherUri;
-                    });
+                    auto itContact = std::find_if(ctx->contacts.cbegin(),
+                                                  ctx->contacts.cend(),
+                                                  [&](const auto& c) {
+                                                      return c.at("id") == otherUri;
+                                                  });
                     if (itContact == ctx->contacts.end()) {
                         JAMI_WARNING("Contact {} not found", otherUri);
                         std::lock_guard lkCv {ctx->cvMtx};
@@ -1438,22 +1458,25 @@ ConversationModule::loadConversations()
                         if (convFromDetails.empty()) {
                             if (isRemoved) {
                                 // If details is empty, contact is removed and not banned.
-                                JAMI_ERROR("Conversation {} detected for {} and should be removed", repository, otherUri);
+                                JAMI_ERROR("Conversation {} detected for {} and should be removed",
+                                           repository,
+                                           otherUri);
                                 std::lock_guard lkMtx {ctx->toRmMtx};
                                 ctx->toRm.insert(repository);
                             } else {
                                 JAMI_ERROR("No conversation detected for {} but one exists ({}). "
-                                        "Update details",
-                                        otherUri,
-                                        repository);
+                                           "Update details",
+                                           otherUri,
+                                           repository);
                                 std::lock_guard lkMtx {ctx->toRmMtx};
-                                ctx->updateContactConv.emplace_back(std::make_tuple(otherUri, convFromDetails, repository));
+                                ctx->updateContactConv.emplace_back(
+                                    std::make_tuple(otherUri, convFromDetails, repository));
                             }
                         } else {
                             JAMI_ERROR("Multiple conversation detected for {} but ({} & {})",
-                                    otherUri,
-                                    repository,
-                                    convFromDetails);
+                                       otherUri,
+                                       repository,
+                                       convFromDetails);
                             std::lock_guard lkMtx {ctx->toRmMtx};
                             ctx->toRm.insert(repository);
                         }
@@ -1466,7 +1489,8 @@ ConversationModule::loadConversations()
                         JAMI_ERROR("Missing conv info for {}. This is a bug!", repository);
                         sconv->info.created = std::time(nullptr);
                         sconv->info.members = std::move(members);
-                        sconv->info.lastDisplayed = conv->infos()[ConversationMapKeys::LAST_DISPLAYED];
+                        sconv->info.lastDisplayed
+                            = conv->infos()[ConversationMapKeys::LAST_DISPLAYED];
                         // convInfosMtx_ is already locked
                         pimpl_->convInfos_[repository] = sconv->info;
                     } else {
@@ -1492,8 +1516,8 @@ ConversationModule::loadConversations()
                 pimpl_->conversations_.emplace(repository, std::move(sconv));
             } catch (const std::logic_error& e) {
                 JAMI_WARNING("[Account {}] Conversations not loaded: {}",
-                        pimpl_->accountId_,
-                        e.what());
+                             pimpl_->accountId_,
+                             e.what());
             }
             std::lock_guard lkCv {ctx->cvMtx};
             --ctx->convNb;
@@ -1502,7 +1526,7 @@ ConversationModule::loadConversations()
     }
 
     std::unique_lock<std::mutex> lkCv {ctx->cvMtx};
-    ctx->cv.wait(lkCv, [&] {return ctx->convNb.load() == 0;});
+    ctx->cv.wait(lkCv, [&] { return ctx->convNb.load() == 0; });
 
     // Prune any invalid conversations without members and
     // set the removed flag if needed
@@ -1550,13 +1574,41 @@ ConversationModule::loadConversations()
     ilk.unlock();
     lk.unlock();
 
-    dht::ThreadPool::io().run(
-        [w = pimpl_->weak(), acc, updateContactConv = std::move(ctx->updateContactConv), toRm = std::move(ctx->toRm)]() {
-            // Will lock account manager
-            if (auto shared = w.lock())
-                shared->fixStructures(acc, updateContactConv, toRm);
-        });
+    dht::ThreadPool::io().run([w = pimpl_->weak(),
+                               acc,
+                               updateContactConv = std::move(ctx->updateContactConv),
+                               toRm = std::move(ctx->toRm)]() {
+        // Will lock account manager
+        if (auto shared = w.lock())
+            shared->fixStructures(acc, updateContactConv, toRm);
+    });
+}
+
+void
+ConversationModule::loadSingleConversation(const std::string& convId)
+{
+    auto acc = pimpl_->account_.lock();
+    if (!acc)
+        return;
+    JAMI_LOG("[Account {}] Start loading conversation {}", pimpl_->accountId_, convId);
 
+    std::unique_lock<std::mutex> lk(pimpl_->conversationsMtx_);
+    pimpl_->conversations_.clear();
+
+    try {
+        auto sconv = std::make_shared<SyncedConversation>(convId);
+
+        auto conv = std::make_shared<Conversation>(acc, convId);
+
+        conv->onNeedSocket(pimpl_->onNeedSwarmSocket_);
+
+        sconv->conversation = conv;
+        pimpl_->conversations_.emplace(convId, std::move(sconv));
+    } catch (const std::logic_error& e) {
+        JAMI_WARNING("[Account {}] Conversations not loaded: {}", pimpl_->accountId_, e.what());
+    }
+
+    lk.unlock();
 }
 
 void
@@ -1644,8 +1696,9 @@ ConversationModule::onTrustRequest(const std::string& uri,
     if (getOneToOneConversation(uri) != "") {
         // If there is already an active one to one conversation here, it's an active
         // contact and the contact will reclone this activeConv, so ignore the request
-        JAMI_WARNING("Contact is sending a request for a non active conversation. Ignore. They will "
-                  "clone the old one");
+        JAMI_WARNING(
+            "Contact is sending a request for a non active conversation. Ignore. They will "
+            "clone the old one");
         return;
     }
     std::unique_lock<std::mutex> lk(pimpl_->conversationsRequestsMtx_);
@@ -1669,8 +1722,8 @@ ConversationModule::onTrustRequest(const std::string& uri,
         pimpl_->needsSyncingCb_({});
     } else {
         JAMI_DEBUG("[Account {}] Received a request for a conversation "
-                  "already existing. Ignore",
-                  pimpl_->accountId_);
+                   "already existing. Ignore",
+                   pimpl_->accountId_);
     }
 }
 
@@ -1686,9 +1739,9 @@ ConversationModule::onConversationRequest(const std::string& from, const Json::V
     }
     std::unique_lock<std::mutex> lk(pimpl_->conversationsRequestsMtx_);
     JAMI_DEBUG("[Account {}] Receive a new conversation request for conversation {} from {}",
-              pimpl_->accountId_,
-              req.conversationId,
-              from);
+               pimpl_->accountId_,
+               req.conversationId,
+               from);
     auto convId = req.conversationId;
 
     // Already accepted request, do nothing
@@ -1697,8 +1750,9 @@ ConversationModule::onConversationRequest(const std::string& from, const Json::V
     auto oldReq = pimpl_->getRequest(convId);
     if (oldReq != std::nullopt) {
         JAMI_DEBUG("[Account {}] Received a request for a conversation already existing. "
-                  "Ignore. Declined: {}",
-                  pimpl_->accountId_, static_cast<int>(oldReq->declined));
+                   "Ignore. Declined: {}",
+                   pimpl_->accountId_,
+                   static_cast<int>(oldReq->declined));
         return;
     }
 
@@ -1707,8 +1761,9 @@ ConversationModule::onConversationRequest(const std::string& from, const Json::V
         // Already a conversation with the contact.
         // If there is already an active one to one conversation here, it's an active
         // contact and the contact will reclone this activeConv, so ignore the request
-        JAMI_WARNING("Contact is sending a request for a non active conversation. Ignore. They will "
-                "clone the old one");
+        JAMI_WARNING(
+            "Contact is sending a request for a non active conversation. Ignore. They will "
+            "clone the old one");
         return;
     }
 
@@ -1753,7 +1808,8 @@ ConversationModule::onNeedConversationRequest(const std::string& from,
 }
 
 void
-ConversationModule::acceptConversationRequest(const std::string& conversationId, const std::string& deviceId)
+ConversationModule::acceptConversationRequest(const std::string& conversationId,
+                                              const std::string& deviceId)
 {
     // For all conversation members, try to open a git channel with this conversation ID
     std::unique_lock<std::mutex> lkCr(pimpl_->conversationsRequestsMtx_);
@@ -1767,7 +1823,9 @@ ConversationModule::acceptConversationRequest(const std::string& conversationId,
                 pimpl_->cloneConversationFrom(conv, deviceId);
             }
         }
-        JAMI_WARNING("[Account {}] Request not found for conversation {}", pimpl_->accountId_, conversationId);
+        JAMI_WARNING("[Account {}] Request not found for conversation {}",
+                     pimpl_->accountId_,
+                     conversationId);
         return;
     }
     pimpl_->rmConversationRequest(conversationId);
@@ -2061,13 +2119,13 @@ ConversationModule::loadSwarmUntil(const std::string& conversationId,
             options.to = toMessage;
             options.includeTo = true;
             conv->conversation->loadMessages2(
-                    [accountId = pimpl_->accountId_, conversationId, id](auto&& messages) {
-                        emitSignal<libjami::ConversationSignal::SwarmLoaded>(id,
-                                                                             accountId,
-                                                                             conversationId,
-                                                                             messages);
-                    },
-                    options);
+                [accountId = pimpl_->accountId_, conversationId, id](auto&& messages) {
+                    emitSignal<libjami::ConversationSignal::SwarmLoaded>(id,
+                                                                         accountId,
+                                                                         conversationId,
+                                                                         messages);
+                },
+                options);
             return id;
         }
     }
@@ -2165,7 +2223,8 @@ ConversationModule::onSyncData(const SyncMsg& msg,
         auto conv = pimpl_->startConversation(convInfo);
         std::unique_lock<std::mutex> lk(conv->mtx);
         // Skip outdated info
-        if (std::max(convInfo.created, convInfo.removed) < std::max(conv->info.created, conv->info.removed))
+        if (std::max(convInfo.created, convInfo.removed)
+            < std::max(conv->info.created, conv->info.removed))
             continue;
         if (not convInfo.isRemoved()) {
             // If multi devices, it can detect a conversation that was already
@@ -2322,9 +2381,9 @@ ConversationModule::setFetched(const std::string& conversationId,
 
 void
 ConversationModule::fetchNewCommits(const std::string& peer,
-                                const std::string& deviceId,
-                                const std::string& conversationId,
-                                const std::string& commitId)
+                                    const std::string& deviceId,
+                                    const std::string& conversationId,
+                                    const std::string& commitId)
 {
     pimpl_->fetchNewCommits(peer, deviceId, conversationId, commitId);
 }
@@ -2544,7 +2603,8 @@ ConversationModule::isBanned(const std::string& convId, const std::string& uri)
     // If 1:1 we check the certificate status
     if (auto acc = pimpl_->account_.lock()) {
         if (auto am = acc->accountManager())
-            return am->getCertificateStatus(uri) == dhtnet::tls::TrustStore::PermissionStatus::BANNED;
+            return am->getCertificateStatus(uri)
+                   == dhtnet::tls::TrustStore::PermissionStatus::BANNED;
     }
     return true;
 }
@@ -2584,9 +2644,7 @@ ConversationModule::removeContact(const std::string& uri, bool banned)
     };
     auto removeConvInfo = [&](const auto& conv, const auto& members) {
         if ((isSelf && members.size() == 1)
-            || (!isSelf
-                && std::find(members.begin(), members.end(), uri)
-                        != members.end())) {
+            || (!isSelf && std::find(members.begin(), members.end(), uri) != members.end())) {
             // Mark as removed
             conv->info.removed = std::time(nullptr);
             updateClient(conv->info.id);
@@ -2899,8 +2957,7 @@ ConversationModule::convInfosFromPath(const std::filesystem::path& path)
     std::map<std::string, ConvInfo> convInfos;
     try {
         // read file
-        std::lock_guard lock(
-            dhtnet::fileutils::getFileLock(path / "convInfo"));
+        std::lock_guard lock(dhtnet::fileutils::getFileLock(path / "convInfo"));
         auto file = fileutils::loadFile("convInfo", path);
         // load values
         msgpack::unpacked result;
@@ -2925,8 +2982,7 @@ ConversationModule::convRequestsFromPath(const std::filesystem::path& path)
     std::map<std::string, ConversationRequest> convRequests;
     try {
         // read file
-        std::lock_guard lock(
-            dhtnet::fileutils::getFileLock(path / "convRequests"));
+        std::lock_guard lock(dhtnet::fileutils::getFileLock(path / "convRequests"));
         auto file = fileutils::loadFile("convRequests", path);
         // load values
         msgpack::unpacked result;
@@ -3003,11 +3059,11 @@ ConversationModule::shutdownConnections()
     {
         std::lock_guard lk(pimpl_->conversationsMtx_);
         conversations.reserve(pimpl_->conversations_.size());
-        for (auto& [k, c]: pimpl_->conversations_) {
+        for (auto& [k, c] : pimpl_->conversations_) {
             conversations.emplace_back(c);
         }
     }
-    for (const auto& c: conversations) {
+    for (const auto& c : conversations) {
         std::lock_guard lkc(c->mtx);
         if (c->conversation)
             c->conversation->shutdownConnections();
@@ -3030,18 +3086,18 @@ ConversationModule::connectivityChanged()
     {
         std::lock_guard lk(pimpl_->conversationsMtx_);
         syncedConversations.reserve(pimpl_->conversations_.size());
-        for (const auto& [k, c]: pimpl_->conversations_) {
+        for (const auto& [k, c] : pimpl_->conversations_) {
             syncedConversations.emplace_back(c);
         }
     }
     std::vector<std::shared_ptr<Conversation>> conversations;
     conversations.reserve(syncedConversations.size());
-    for (const auto& c: syncedConversations) {
+    for (const auto& c : syncedConversations) {
         std::lock_guard lkc(c->mtx);
         if (c->conversation)
             conversations.emplace_back(c->conversation);
     }
-    for (const auto& conv: conversations)
+    for (const auto& conv : conversations)
         conv->connectivityChanged();
 }
 } // namespace jami
diff --git a/src/jamidht/conversation_module.h b/src/jamidht/conversation_module.h
index eb8c3198334bf883a12733c41653d39e0efcfea0..10346e6dab023293623e5d781c46d85f5668867c 100644
--- a/src/jamidht/conversation_module.h
+++ b/src/jamidht/conversation_module.h
@@ -79,7 +79,8 @@ public:
                        NeedSocketCb&& onNeedSocket,
                        NeedSocketCb&& onNeedSwarmSocket,
                        UpdateConvReq&& updateConvReqCb,
-                       OneToOneRecvCb&& oneToOneRecvCb);
+                       OneToOneRecvCb&& oneToOneRecvCb,
+                       bool autoLoadConversations = true);
     ~ConversationModule() = default;
 
     /**
@@ -87,6 +88,8 @@ public:
      */
     void loadConversations();
 
+    void loadSingleConversation(const std::string& convId);
+
 #ifdef LIBJAMI_TESTABLE
     void onBootstrapStatus(const std::function<void(std::string, Conversation::BootstrapStatus)>& cb);
 #endif
@@ -164,7 +167,8 @@ public:
      * @param convId
      * @param deviceId      If a trust request is accepted from a device (can help to sync)
      */
-    void acceptConversationRequest(const std::string& conversationId, const std::string& deviceId = "");
+    void acceptConversationRequest(const std::string& conversationId,
+                                   const std::string& deviceId = "");
 
     /**
      * Decline a conversation's request
@@ -239,8 +243,8 @@ public:
                                       const std::string& fromMessage = "",
                                       size_t n = 0);
     uint32_t loadConversation(const std::string& conversationId,
-                                const std::string& fromMessage = "",
-                                size_t n = 0);
+                              const std::string& fromMessage = "",
+                              size_t n = 0);
     uint32_t loadConversationUntil(const std::string& conversationId,
                                    const std::string& fromMessage,
                                    const std::string& to);
@@ -471,7 +475,8 @@ public:
     static std::map<std::string, ConvInfo> convInfos(const std::string& accountId);
     static std::map<std::string, ConvInfo> convInfosFromPath(const std::filesystem::path& path);
     static std::map<std::string, ConversationRequest> convRequests(const std::string& accountId);
-    static std::map<std::string, ConversationRequest> convRequestsFromPath(const std::filesystem::path& path);
+    static std::map<std::string, ConversationRequest> convRequestsFromPath(
+        const std::filesystem::path& path);
     void addConvInfo(const ConvInfo& info);
 
     /**
@@ -486,7 +491,7 @@ public:
      * @return the related socket
      */
     std::shared_ptr<dhtnet::ChannelSocket> gitSocket(std::string_view deviceId,
-                                             std::string_view convId) const;
+                                                     std::string_view convId) const;
     void removeGitSocket(std::string_view deviceId, std::string_view convId);
     void addGitSocket(std::string_view deviceId,
                       std::string_view convId,
@@ -500,7 +505,8 @@ public:
      * @param conversationId
      * @param socket
      */
-    void addSwarmChannel(const std::string& conversationId, std::shared_ptr<dhtnet::ChannelSocket> socket);
+    void addSwarmChannel(const std::string& conversationId,
+                         std::shared_ptr<dhtnet::ChannelSocket> socket);
     /**
      * Triggers a bucket maintainance for DRTs
      */
diff --git a/src/jamidht/jamiaccount.cpp b/src/jamidht/jamiaccount.cpp
index da90b36ede08ef497a29ed8158d8e0db869cd956..58c9de7ac876ac65139e7fc4a0a5b1404bb67e04 100644
--- a/src/jamidht/jamiaccount.cpp
+++ b/src/jamidht/jamiaccount.cpp
@@ -2301,7 +2301,8 @@ JamiAccount::convModule(bool noCreation)
                                                                          convId,
                                                                          {});
                                       });
-            });
+            },
+            autoLoadConversations_);
     }
     return convModule_.get();
 }
@@ -2332,6 +2333,13 @@ JamiAccount::onTextMessage(const std::string& id,
     }
 }
 
+void
+JamiAccount::loadConversation(const std::string& convId)
+{
+    if (auto cm = convModule(false))
+        cm->loadSingleConversation(convId);
+}
+
 void
 JamiAccount::doUnregister(std::function<void(bool)> released_cb)
 {
diff --git a/src/jamidht/jamiaccount.h b/src/jamidht/jamiaccount.h
index 78ec1d5bcec2514117924af98a6a275aceda9693..b1667056780a6e5a93d38129f64936780adbb693 100644
--- a/src/jamidht/jamiaccount.h
+++ b/src/jamidht/jamiaccount.h
@@ -261,17 +261,20 @@ public:
                        const std::string& from,
                        const std::string& deviceId,
                        const std::map<std::string, std::string>& payloads) override;
+    void loadConversation(const std::string& convId);
 
     virtual bool isTlsEnabled() const override { return true; }
     bool isSrtpEnabled() const override { return true; }
 
     virtual bool getSrtpFallback() const override { return false; }
 
-    bool setCertificateStatus(const std::string& cert_id, dhtnet::tls::TrustStore::PermissionStatus status);
+    bool setCertificateStatus(const std::string& cert_id,
+                              dhtnet::tls::TrustStore::PermissionStatus status);
     bool setCertificateStatus(const std::shared_ptr<crypto::Certificate>& cert,
                               dhtnet::tls::TrustStore::PermissionStatus status,
                               bool local = true);
-    std::vector<std::string> getCertificatesByStatus(dhtnet::tls::TrustStore::PermissionStatus status);
+    std::vector<std::string> getCertificatesByStatus(
+        dhtnet::tls::TrustStore::PermissionStatus status);
 
     bool findCertificate(const std::string& id);
     bool findCertificate(
@@ -344,8 +347,12 @@ public:
      * doesn't have a password
      * @return if the archive was exported
      */
-    bool exportArchive(const std::string& destinationPath, std::string_view scheme = {}, const std::string& password = {});
-    bool revokeDevice(const std::string& device, std::string_view scheme = {}, const std::string& password = {});
+    bool exportArchive(const std::string& destinationPath,
+                       std::string_view scheme = {},
+                       const std::string& password = {});
+    bool revokeDevice(const std::string& device,
+                      std::string_view scheme = {},
+                      const std::string& password = {});
     std::map<std::string, std::string> getKnownDevices() const;
 
     bool isPasswordValid(const std::string& password);
@@ -361,7 +368,9 @@ public:
 #if HAVE_RINGNS
     void lookupName(const std::string& name);
     void lookupAddress(const std::string& address);
-    void registerName(const std::string& name, const std::string& scheme, const std::string& password);
+    void registerName(const std::string& name,
+                      const std::string& scheme,
+                      const std::string& password);
 #endif
     bool searchUser(const std::string& nameQuery);
 
@@ -370,15 +379,9 @@ public:
     /// further calls
     bool isMessageTreated(std::string_view id);
 
-    std::shared_ptr<dht::DhtRunner> dht()
-    {
-        return dht_;
-    }
+    std::shared_ptr<dht::DhtRunner> dht() { return dht_; }
 
-    const dht::crypto::Identity& identity() const
-    {
-        return id_;
-    }
+    const dht::crypto::Identity& identity() const { return id_; }
 
     void forEachDevice(const dht::InfoHash& to,
                        std::function<void(const std::shared_ptr<dht::crypto::PublicKey>&)>&& op,
@@ -426,23 +429,15 @@ public:
     std::map<std::string, std::string> getNearbyPeers() const override;
 
 #ifdef LIBJAMI_TESTABLE
-    dhtnet::ConnectionManager& connectionManager()
-    {
-        return *connectionManager_;
-    }
+    dhtnet::ConnectionManager& connectionManager() { return *connectionManager_; }
 
     /**
      * Only used for tests, disable sha3sum verification for transfers.
      * @param newValue
      */
-    void noSha3sumVerification(bool newValue)
-    {
-        noSha3sumVerification_ = newValue;
-    }
+    void noSha3sumVerification(bool newValue) { noSha3sumVerification_ = newValue; }
 
-    void publishPresence(bool newValue) {
-        publishPresence_  = newValue;
-    }
+    void publishPresence(bool newValue) { publishPresence_ = newValue; }
 #endif
 
     /**
@@ -460,7 +455,8 @@ public:
 
     void monitor();
     // conversationId optional
-    std::vector<std::map<std::string, std::string>> getConnectionList(const std::string& conversationId = "");
+    std::vector<std::map<std::string, std::string>> getConnectionList(
+        const std::string& conversationId = "");
     std::vector<std::map<std::string, std::string>> getChannelList(const std::string& connectionId);
 
     // File transfer
@@ -534,14 +530,9 @@ public:
 
     std::filesystem::path profilePath() const;
 
-    const std::shared_ptr<AccountManager>& accountManager() {
-        return accountManager_;
-    }
+    const std::shared_ptr<AccountManager>& accountManager() { return accountManager_; }
 
-    bool sha3SumVerify() const
-    {
-        return !noSha3sumVerification_;
-    }
+    bool sha3SumVerify() const { return !noSha3sumVerification_; }
 
     /**
      * Change certificate's validity period
@@ -550,7 +541,10 @@ public:
      * @param validity  New validity
      * @note forceReloadAccount may be necessary to retrigger the migration
      */
-    bool setValidity(std::string_view scheme, const std::string& pwd, const dht::InfoHash& id, int64_t validity);
+    bool setValidity(std::string_view scheme,
+                     const std::string& pwd,
+                     const dht::InfoHash& id,
+                     int64_t validity);
     /**
      * Try to reload the account to force the identity to be updated
      */
@@ -576,10 +570,7 @@ public:
      * connected. This kind of node corresponds to devices with push notifications & proxy and are
      * stored in the mobile nodes
      */
-    bool isMobile() const
-    {
-        return config().proxyEnabled and not config().deviceKey.empty();
-    }
+    bool isMobile() const { return config().proxyEnabled and not config().deviceKey.empty(); }
 
 #ifdef LIBJAMI_TESTABLE
     std::map<Uri::Scheme, std::unique_ptr<ChannelHandlerInterface>>& channelHandlers()
@@ -588,10 +579,7 @@ public:
     };
 #endif
 
-    dhtnet::tls::CertificateStore& certStore() const
-    {
-        return *certStore_;
-    }
+    dhtnet::tls::CertificateStore& certStore() const { return *certStore_; }
     /**
      * Check if a Device is connected
      * @param deviceId
@@ -723,7 +711,6 @@ private:
     std::map<dht::Value::Id, PendingMessage> sentMessages_;
     std::set<std::string, std::less<>> treatedMessages_ {};
 
-
     /* tracked buddies presence */
     mutable std::mutex buddyInfoMtx;
     std::map<dht::InfoHash, BuddyInfo> trackedBuddies_;
diff --git a/src/manager.cpp b/src/manager.cpp
index 2a9caec4b181a338152776aa67a48609cefb3f7c..0e13bc2f8f39bb9cb93b03c3dfe46dfe2acd89fc 100644
--- a/src/manager.cpp
+++ b/src/manager.cpp
@@ -187,8 +187,7 @@ check_rename(const std::filesystem::path& old_dir, const std::filesystem::path&
         for (const auto& file_iterator : std::filesystem::directory_iterator(old_dir, ec)) {
             const auto& file_path = file_iterator.path();
             auto new_path = new_dir / file_path.filename();
-            if (file_iterator.is_directory()
-                and std::filesystem::is_directory(new_path)) {
+            if (file_iterator.is_directory() and std::filesystem::is_directory(new_path)) {
                 check_rename(file_path, new_path);
             } else {
                 JAMI_WARNING("Migrating {} to {}", old_dir, new_path);
@@ -875,7 +874,13 @@ Manager::init(const std::filesystem::path& config_file, libjami::InitFlag flags)
                          getRingBufferPool().getInternalAudioFormat().sampleFormat));
         }
     }
-    registerAccounts();
+
+    if (libjami::LIBJAMI_FLAG_NO_AUTOLOAD & flags) {
+        JAMI_DBG("LIBJAMI_FLAG_NO_AUTOLOAD is set, accounts and conversations will not be loaded");
+        return;
+    } else {
+        registerAccounts();
+    }
 }
 
 void
@@ -1408,9 +1413,7 @@ Manager::addParticipant(const std::string& accountId,
 bool
 Manager::addParticipant(Call& call, Conference& conference)
 {
-    JAMI_DEBUG("Add participant {} to conference {}",
-             call.getCallId(),
-             conference.getConfId());
+    JAMI_DEBUG("Add participant {} to conference {}", call.getCallId(), conference.getConfId());
 
     // store the current call id (it will change in offHoldCall or in answerCall)
     pimpl_->bindCallToConference(call, conference);
@@ -1713,8 +1716,7 @@ Manager::addAudio(Call& call)
         auto medias = call.getAudioStreams();
         for (const auto& media : medias) {
             JAMI_DEBUG("[call:{}] Attach audio", media.first);
-            getRingBufferPool().bindRingbuffers(media.first,
-                                            RingBufferPool::DEFAULT_ID);
+            getRingBufferPool().bindRingbuffers(media.first, RingBufferPool::DEFAULT_ID);
         }
         auto oldGuard = std::move(call.audioGuard);
         call.audioGuard = startAudioStream(AudioDeviceType::PLAYBACK);
@@ -2577,9 +2579,9 @@ Manager::ManagerPimpl::processIncomingCall(const std::string& accountId, Call& i
         JAMI_WARNING("Incoming call {} has an empty media list", incomCallId);
 
     JAMI_DEBUG("Incoming call {} on account {} with {} media",
-              incomCallId,
-              accountId,
-              mediaList.size());
+               incomCallId,
+               accountId,
+               mediaList.size());
 
     emitSignal<libjami::CallSignal::IncomingCallWithMedia>(accountId,
                                                            incomCallId,
@@ -3048,6 +3050,27 @@ Manager::setAccountActive(const std::string& accountID, bool active, bool shutdo
         accountID, acc->getVolatileAccountDetails());
 }
 
+void
+Manager::loadAccountAndConversation(const std::string& accountID, const std::string& convID)
+{
+    if (const auto a = getAccount(accountID)) {
+        a->enableAutoLoadConversations(false);
+        if (a->getRegistrationState() == RegistrationState::UNLOADED) {
+            a->loadConfig();
+        }
+        a->setActive(true);
+        if (a->isUsable())
+            a->doRegister();
+        if (auto jamiAcc = std::dynamic_pointer_cast<JamiAccount>(a)) {
+            // load requests before loading conversation
+            if (auto convModule = jamiAcc->convModule()) {
+                convModule->reloadRequests();
+            }
+            jamiAcc->loadConversation(convID);
+        }
+    }
+}
+
 std::shared_ptr<AudioLayer>
 Manager::getAudioDriver()
 {
diff --git a/src/manager.h b/src/manager.h
index 32b1aa99b4f727e95299ae55c95447a9504a0881..b06d0682b3b701e5be623a3f470ccf02107ba13f 100644
--- a/src/manager.h
+++ b/src/manager.h
@@ -57,7 +57,7 @@ class io_context;
 namespace dhtnet {
 class ChannelSocket;
 class IceTransportFactory;
-}
+} // namespace dhtnet
 
 namespace jami {
 namespace video {
@@ -126,7 +126,7 @@ public:
 
     /**
      * Initialisation of thread (sound) and map.
-     * Init a new VoIPLink, audio codec and audio driver
+     * Init a new VoIPLink, audio codec and audio driver.
      */
     void init(const std::filesystem::path& config_file, libjami::InitFlag flags);
 
@@ -137,8 +137,10 @@ public:
 
     void monitor(bool continuous);
 
-    std::vector<std::map<std::string, std::string>> getConnectionList(const std::string& accountId, const std::string& conversationId);
-    std::vector<std::map<std::string, std::string>> getChannelList(const std::string& accountId, const std::string& connectionId);
+    std::vector<std::map<std::string, std::string>> getConnectionList(
+        const std::string& accountId, const std::string& conversationId);
+    std::vector<std::map<std::string, std::string>> getChannelList(const std::string& accountId,
+                                                                   const std::string& connectionId);
 
     /**
      * Accessor to audiodriver.
@@ -441,6 +443,7 @@ public:
                            const std::map<std::string, ::std::string>& details);
 
     void setAccountActive(const std::string& accountID, bool active, bool shutdownConnections);
+    void loadAccountAndConversation(const std::string& accountID, const std::string& convID);
 
     std::mt19937_64 getSeededRandomEngine();
 
@@ -771,6 +774,11 @@ public:
      */
     void registerAccounts();
 
+    /**
+     * Send registration for one account
+     */
+    void registerAccount(const std::string& accountID, const std::string& convId = {});
+
     /**
      * Send unregister for all enabled accounts
      */
@@ -864,8 +872,8 @@ public:
      * @return std::optional<std::weak_ptr<ChannelSocket>> the related socket
      */
     std::shared_ptr<dhtnet::ChannelSocket> gitSocket(const std::string_view accountId,
-                                             const std::string_view deviceId,
-                                             const std::string_view conversationId);
+                                                     const std::string_view deviceId,
+                                                     const std::string_view conversationId);
 
     void setDefaultModerator(const std::string& accountID, const std::string& peerURI, bool state);
     std::vector<std::string> getDefaultModerators(const std::string& accountID);