diff --git a/src/api/lrc.h b/src/api/lrc.h
index aec00d77a1adcc912c94cfa6ad8dfd7bef2c4783..f11c94d8fb52b19d182a0a25ae792df3e6d28fe3 100644
--- a/src/api/lrc.h
+++ b/src/api/lrc.h
@@ -91,10 +91,25 @@ public:
     void subscribeToDebugReceived();
 
     /**
-     * Helper: get call list from daemon
+     * Helper: get active call list from daemon
      */
     static std::vector<std::string> activeCalls();
 
+    /**
+     * Helper: get call list from daemon
+     */
+    static std::vector<std::string> getCalls();
+
+    /**
+     * Helper: get conference list from daemon
+     */
+    static std::vector<std::string> getConferences();
+
+    /**
+     * Helper: get subcalls list for a conference from daemon
+     */
+    static std::vector<std::string> getConferenceSubcalls(const std::string& id);
+
   private:
     std::unique_ptr<LrcPimpl> lrcPimpl_;
 };
diff --git a/src/conversationmodel.cpp b/src/conversationmodel.cpp
index 918e1b71f94b440b806f451bb14b6d37d550b53a..a8d406b717fe02a2a05919c7e4e86728f89a64ef 100644
--- a/src/conversationmodel.cpp
+++ b/src/conversationmodel.cpp
@@ -1510,7 +1510,25 @@ ConversationModelPimpl::slotCallStatusChanged(const std::string& callId, int cod
             return conversation.callId == callId;
         });
 
-    if (i == conversations.end()) return;
+    if (i == conversations.end()) {
+        // In this case, the user didn't pass through placeCall
+        // This means that a participant was invited to a call
+        // or a call was placed via dbus.
+        // We have to update the model
+        try {
+            auto call = linked.owner.callModel->getCall(callId);
+            for (auto& conversation: conversations) {
+                if (conversation.participants.front() == call.peerUri) {
+                    conversation.callId = callId;
+                    dirtyConversations = {true, true};
+                    emit linked.conversationUpdated(conversation.uid);
+                }
+            }
+        } catch (std::out_of_range& e) {
+            qDebug() << "ConversationModelPimpl::slotCallStatusChanged can't get inexistant call";
+        }
+        return;
+    }
 
     auto& conversation = *i;
     auto uid = conversation.uid;
@@ -1668,7 +1686,7 @@ void
 ConversationModelPimpl::slotCallAddedToConference(const std::string& callId, const std::string& confId)
 {
     for (auto& conversation: conversations) {
-        if (conversation.callId == callId) {
+        if (conversation.callId == callId || conversation.confId == confId) {
             conversation.confId = confId;
             dirtyConversations = {true, true};
             emit linked.selectConversation(conversation.uid);
diff --git a/src/lrc.cpp b/src/lrc.cpp
index 91acd433715df2e0763ea8ffc1749ac137631a96..cbb795ec0aab421e8a8600cc362e0d295e67d103 100644
--- a/src/lrc.cpp
+++ b/src/lrc.cpp
@@ -149,6 +149,42 @@ Lrc::activeCalls()
     return result;
 }
 
+std::vector<std::string>
+Lrc::getCalls()
+{
+    QStringList callLists = CallManager::instance().getCallList();
+    std::vector<std::string> result;
+    result.reserve(callLists.size());
+    for (const auto &call : callLists) {
+        result.emplace_back(call.toStdString());
+    }
+    return result;
+}
+
+std::vector<std::string>
+Lrc::getConferences()
+{
+    QStringList conferencesList = CallManager::instance().getConferenceList();
+    std::vector<std::string> result;
+    result.reserve(conferencesList.size());
+    for (const auto &conf : conferencesList) {
+        result.emplace_back(conf.toStdString());
+    }
+    return result;
+}
+
+std::vector<std::string>
+Lrc::getConferenceSubcalls(const std::string& cid)
+{
+    QStringList callList = CallManager::instance().getParticipantList(cid.c_str());
+    std::vector<std::string> result;
+    result.reserve(callList.size());
+    foreach(const auto& callId, callList) {
+        result.emplace_back(callId.toStdString());
+    }
+    return result;
+}
+
 bool
 isFinished(const QString& callState)
 {
diff --git a/src/newcallmodel.cpp b/src/newcallmodel.cpp
index b75425ae1b3b739bf1e1cb42c1c8f3579d7c7059..1d3b5712da1cb0717b228cef7762b67306e7c0ba 100644
--- a/src/newcallmodel.cpp
+++ b/src/newcallmodel.cpp
@@ -207,9 +207,12 @@ NewCallModel::getConferenceFromURI(const std::string& uri) const
         if (call.second->type == call::Type::CONFERENCE) {
             QStringList callList = CallManager::instance().getParticipantList(call.first.c_str());
             foreach(const auto& callId, callList) {
-                if (pimpl_->calls[callId.toStdString()]->peerUri == uri) {
-                    return *call.second;
-                }
+                try {
+                    if (pimpl_->calls.find(callId.toStdString()) != pimpl_->calls.end()
+                        && pimpl_->calls[callId.toStdString()]->peerUri == uri) {
+                        return *call.second;
+                    }
+                } catch (...) {}
             }
         }
     }
@@ -372,18 +375,70 @@ NewCallModel::transferToCall(const std::string& callId, const std::string& callI
 void
 NewCallModel::joinCalls(const std::string& callIdA, const std::string& callIdB) const
 {
-    if (!hasCall(callIdA) || !hasCall(callIdB)) return;
-
-    auto& call1 = pimpl_->calls[callIdA];
-    auto& call2 = pimpl_->calls[callIdB];
-    if (call1->type == call::Type::CONFERENCE && call2->type == call::Type::CONFERENCE)
-        CallManager::instance().joinConference(callIdA.c_str(), callIdB.c_str());
-    else if (call1->type == call::Type::CONFERENCE)
-        CallManager::instance().addParticipant(callIdB.c_str(), callIdA.c_str());
-    else if (call2->type == call::Type::CONFERENCE)
-        CallManager::instance().addParticipant(callIdA.c_str(), callIdB.c_str());
-    else
+    // Get call informations
+    call::Info call1, call2;
+    std::string accountIdCall1 = {}, accountIdCall2 = {};
+    for (const auto &account_id : owner.accountModel->getAccountList()) {
+        try {
+            auto &accountInfo = owner.accountModel->getAccountInfo(account_id);
+            if (accountInfo.callModel->hasCall(callIdA)) {
+                call1 = accountInfo.callModel->getCall(callIdA);
+                accountIdCall1 = account_id;
+            }
+            if (accountInfo.callModel->hasCall(callIdB)) {
+                call2 = accountInfo.callModel->getCall(callIdB);
+                accountIdCall2 = account_id;
+            }
+            if (!accountIdCall1.empty() && !accountIdCall2.empty()) break;
+        } catch (...) {}
+    }
+    if (accountIdCall1.empty() || accountIdCall2.empty()) {
+        qWarning() << "Can't join inexistent calls.";
+        return;
+    }
+
+    if (call1.type == call::Type::CONFERENCE && call2.type == call::Type::CONFERENCE) {
+        bool joined = CallManager::instance().joinConference(callIdA.c_str(), callIdB.c_str());
+
+        if (!joined) {
+            qWarning() << "Conference: " << callIdA.c_str() << " couldn't join conference " << callIdB.c_str();
+            return;
+        }
+        if (accountIdCall1 != owner.id) {
+            // If the conference is added from another account
+            try {
+                auto &accountInfo = owner.accountModel->getAccountInfo(accountIdCall1);
+                if (accountInfo.callModel->hasCall(callIdA)) {
+                    emit accountInfo.callModel->callAddedToConference(callIdA, callIdB);
+                }
+            } catch (...) {}
+        } else {
+            emit callAddedToConference(callIdA, callIdB);
+        }
+    } else if (call1.type == call::Type::CONFERENCE || call2.type == call::Type::CONFERENCE) {
+        auto call = call1.type == call::Type::CONFERENCE ? callIdB : callIdA;
+        auto conf = call1.type == call::Type::CONFERENCE ? callIdA : callIdB;
+        auto accountCall = call1.type == call::Type::CONFERENCE ? accountIdCall2 : accountIdCall1;
+        bool joined = CallManager::instance().addParticipant(call.c_str(), conf.c_str());
+        if (!joined) {
+            qWarning() << "Call: " << call.c_str() << " couldn't join conference " << conf.c_str();
+            return;
+        }
+        if (accountCall != owner.id) {
+            // If the call is added from another account
+            try {
+                auto &accountInfo = owner.accountModel->getAccountInfo(accountCall);
+                if (accountInfo.callModel->hasCall(call)) {
+                    accountInfo.callModel->pimpl_->slotConferenceCreated(conf);
+                }
+            } catch (...) {}
+        } else
+            emit callAddedToConference(call, conf);
+    }
+    else {
         CallManager::instance().joinParticipant(callIdA.c_str(), callIdB.c_str());
+        // NOTE: This will trigger slotConferenceCreated.
+    }
 }
 
 void