diff --git a/src/account.cpp b/src/account.cpp
index ba9603c87da59682cf3eb9c28081f91d9a7a1fd4..667581bdf67f5ce0f47432228928c9b2523943c6 100644
--- a/src/account.cpp
+++ b/src/account.cpp
@@ -78,6 +78,7 @@ const char * const Account::PASSWORD_KEY                  = "password";
 const char * const Account::HOSTNAME_KEY                  = "hostname";
 const char * const Account::ACCOUNT_ENABLE_KEY            = "enable";
 const char * const Account::ACCOUNT_AUTOANSWER_KEY        = "autoAnswer";
+const char * const Account::ACCOUNT_ISRENDEZVOUS_KEY      = "rendezVous";
 const char * const Account::ACCOUNT_ACTIVE_CALL_LIMIT_KEY = "activeCallLimit";
 const char * const Account::MAILBOX_KEY                   = "mailbox";
 const char * const Account::DEFAULT_USER_AGENT            = PACKAGE_NAME;
@@ -101,6 +102,7 @@ Account::Account(const std::string &accountID)
     , alias_()
     , enabled_(true)
     , autoAnswerEnabled_(false)
+    , isRendezVous_(false)
     , registrationState_(RegistrationState::UNREGISTERED)
     , systemCodecContainer_(getSystemCodecContainer())
     , accountCodecInfoList_()
@@ -227,6 +229,7 @@ Account::serialize(YAML::Emitter& out) const
     out << YAML::Key << ACTIVE_CODEC_KEY << YAML::Value << activeCodecs;
     out << YAML::Key << MAILBOX_KEY << YAML::Value << mailBox_;
     out << YAML::Key << ACCOUNT_AUTOANSWER_KEY << YAML::Value << autoAnswerEnabled_;
+    out << YAML::Key << ACCOUNT_ISRENDEZVOUS_KEY << YAML::Value << isRendezVous_;
     out << YAML::Key << ACCOUNT_ACTIVE_CALL_LIMIT_KEY << YAML::Value << activeCallLimit_;
     out << YAML::Key << RINGTONE_ENABLED_KEY << YAML::Value << ringtoneEnabled_;
     out << YAML::Key << RINGTONE_PATH_KEY << YAML::Value << ringtonePath_;
@@ -246,6 +249,7 @@ Account::unserialize(const YAML::Node& node)
     parseValue(node, ALIAS_KEY, alias_);
     parseValue(node, ACCOUNT_ENABLE_KEY, enabled_);
     parseValue(node, ACCOUNT_AUTOANSWER_KEY, autoAnswerEnabled_);
+    parseValueOptional(node, ACCOUNT_ISRENDEZVOUS_KEY, isRendezVous_);
     parseValue(node, ACCOUNT_ACTIVE_CALL_LIMIT_KEY, activeCallLimit_);
     //parseValue(node, PASSWORD_KEY, password_);
 
@@ -298,6 +302,7 @@ Account::setAccountDetails(const std::map<std::string, std::string> &details)
     parseString(details, Conf::CONFIG_ACCOUNT_MAILBOX, mailBox_);
     parseString(details, Conf::CONFIG_ACCOUNT_USERAGENT, userAgent_);
     parseBool(details, Conf::CONFIG_ACCOUNT_AUTOANSWER, autoAnswerEnabled_);
+    parseBool(details, Conf::CONFIG_ACCOUNT_ISRENDEZVOUS, isRendezVous_);
     parseInt(details, DRing::Account::ConfProperties::ACTIVE_CALL_LIMIT, activeCallLimit_);
     parseBool(details, Conf::CONFIG_RINGTONE_ENABLED, ringtoneEnabled_);
     parseString(details, Conf::CONFIG_RINGTONE_PATH, ringtonePath_);
@@ -328,6 +333,7 @@ Account::getAccountDetails() const
         {Conf::CONFIG_ACCOUNT_USERAGENT,    hasCustomUserAgent_ ? userAgent_ : DEFAULT_USER_AGENT},
         {Conf::CONFIG_ACCOUNT_HAS_CUSTOM_USERAGENT, hasCustomUserAgent_ ? userAgent_ : DEFAULT_USER_AGENT},
         {Conf::CONFIG_ACCOUNT_AUTOANSWER,   autoAnswerEnabled_ ? TRUE_STR : FALSE_STR},
+        {Conf::CONFIG_ACCOUNT_ISRENDEZVOUS,   isRendezVous_ ? TRUE_STR : FALSE_STR},
         {DRing::Account::ConfProperties::ACTIVE_CALL_LIMIT,   std::to_string(activeCallLimit_)},
         {Conf::CONFIG_RINGTONE_ENABLED,     ringtoneEnabled_ ? TRUE_STR : FALSE_STR},
         {Conf::CONFIG_RINGTONE_PATH,        ringtonePath_},
diff --git a/src/account.h b/src/account.h
index 75e2cd2e78abcfb6aa23cd7cb6d4abca113dc990..4049e33a194bb0b02a233498f266e0573350da32 100644
--- a/src/account.h
+++ b/src/account.h
@@ -181,8 +181,6 @@ class Account : public Serializable, public std::enable_shared_from_this<Account
             return false;
         }
 
-        std::vector<std::shared_ptr<Call>> getCalls();
-
         /**
          * Tell if the account is enable or not.
          * @return true if enabled, false otherwise
@@ -289,6 +287,10 @@ class Account : public Serializable, public std::enable_shared_from_this<Account
             mailBox_ = mb;
         }
 
+        bool isRendezVous() const {
+            return isRendezVous_;
+        }
+
         void attachCall(const std::string& id);
         void detachCall(const std::string& id);
 
@@ -384,6 +386,7 @@ class Account : public Serializable, public std::enable_shared_from_this<Account
         static const char * const HOSTNAME_KEY;
         static const char * const ACCOUNT_ENABLE_KEY;
         static const char * const ACCOUNT_AUTOANSWER_KEY;
+        static const char * const ACCOUNT_ISRENDEZVOUS_KEY;
         static const char * const ACCOUNT_ACTIVE_CALL_LIMIT_KEY;
         static const char * const MAILBOX_KEY;
         static const char * const USER_AGENT_KEY;
@@ -437,6 +440,9 @@ class Account : public Serializable, public std::enable_shared_from_this<Account
         /* If true, automatically answer calls to this account */
         bool autoAnswerEnabled_;
 
+        /* If true mix calls into a conference */
+        bool isRendezVous_;
+
         /**
          * The number of concurrent calls for the account
          * -1: Unlimited
diff --git a/src/account_schema.h b/src/account_schema.h
index 519e35d351318ed0a3f6ae1c9c2252fb30fa13e4..f0e1c91f5c559311d8896a0f5a43e524de03e235 100644
--- a/src/account_schema.h
+++ b/src/account_schema.h
@@ -36,6 +36,7 @@ static const char *const CONFIG_ACCOUNT_DISPLAYNAME             = "Account.displ
 static const char *const CONFIG_ACCOUNT_MAILBOX                 = "Account.mailbox";
 static const char *const CONFIG_ACCOUNT_ENABLE                  = "Account.enable";
 static const char *const CONFIG_ACCOUNT_AUTOANSWER              = "Account.autoAnswer";
+static const char *const CONFIG_ACCOUNT_ISRENDEZVOUS            = "Account.rendezVous";
 static const char *const CONFIG_ACCOUNT_REGISTRATION_EXPIRE     = "Account.registrationExpire";
 static const char *const CONFIG_ACCOUNT_DTMF_TYPE               = "Account.dtmfType";
 static const char *const CONFIG_RINGTONE_PATH                   = "Account.ringtonePath";
diff --git a/src/dring/account_const.h b/src/dring/account_const.h
index dcb4dc79c00a11b2ca8bcff43e1e16036ba24350..f13d5c1c97cb9611f3415ca54c134ec896fb7550 100644
--- a/src/dring/account_const.h
+++ b/src/dring/account_const.h
@@ -115,6 +115,7 @@ constexpr static const char ENABLED                 [] = "Account.enable";
 constexpr static const char MAILBOX                 [] = "Account.mailbox";
 constexpr static const char DTMF_TYPE               [] = "Account.dtmfType";
 constexpr static const char AUTOANSWER              [] = "Account.autoAnswer";
+constexpr static const char ISRENDEZVOUS            [] = "Account.rendezVous";
 constexpr static const char ACTIVE_CALL_LIMIT       [] = "Account.activeCallLimit";
 constexpr static const char HOSTNAME                [] = "Account.hostname";
 constexpr static const char USERNAME                [] = "Account.username";
diff --git a/src/manager.cpp b/src/manager.cpp
index 4ea29251b57a3b4d35e6028b5dd725fdc81d0154..66e875b189e49c1f050d37c9f25d8fbc0cb4ad30 100644
--- a/src/manager.cpp
+++ b/src/manager.cpp
@@ -43,6 +43,7 @@
 #include "string_utils.h"
 #include "jamidht/jamiaccount.h"
 #include "sip/sipvoiplink.h"
+#include "account.h"
 #include <opendht/rng.h>
 using random_device = dht::crypto::random_device;
 
@@ -535,11 +536,17 @@ Manager::ManagerPimpl::processRemainingParticipants(Conference& conf)
         auto p = participants.begin();
         if (auto call = base_.getCallFromCallID(*p)) {
             call->setConfId("");
-            // if we are not listening to this conference
-            if (current_call_id != conf.getConfID())
-                base_.onHoldCall(call->getCallId());
-            else
-                switchCall(call);
+            // if we are not listening to this conference and not a rendez-vous
+            auto isRdv = false;
+            if (auto acc = std::dynamic_pointer_cast<JamiAccount>(base_.getAccount(call->getAccountId())))
+                isRdv = acc->getAccountDetails()[Conf::CONFIG_ACCOUNT_ISRENDEZVOUS] == TRUE_STR;
+
+            if (!isRdv) {
+                if (current_call_id != conf.getConfID())
+                    base_.onHoldCall(call->getCallId());
+                else
+                    switchCall(call);
+            }
         }
 
         JAMI_DBG("No remaining participants, remove conference");
@@ -1344,6 +1351,10 @@ Manager::addParticipant(const std::string& callId,
 
     pimpl_->bindCallToConference(*call, *conf);
 
+    // Don't attach current user yet
+    if (conf->getState() == Conference::State::ACTIVE_DETACHED)
+        return true;
+
     // TODO: remove this ugly hack => There should be different calls when double clicking
     // a conference to add main participant to it, or (in this case) adding a participant
     // toconference
@@ -1384,7 +1395,7 @@ Manager::getCallFromCallID(const std::string& callID) const
 }
 
 bool
-Manager::joinParticipant(const std::string& callId1, const std::string& callId2)
+Manager::joinParticipant(const std::string& callId1, const std::string& callId2, bool attached)
 {
     if (callId1 == callId2) {
         JAMI_ERR("Cannot join participant %s to itself", callId1.c_str());
@@ -1412,8 +1423,12 @@ Manager::joinParticipant(const std::string& callId1, const std::string& callId2)
     pimpl_->bindCallToConference(*call2, *conf);
 
     // Switch current call id to this conference
-    pimpl_->switchCall(conf->getConfID());
-    conf->setState(Conference::State::ACTIVE_ATTACHED);
+    if (attached) {
+        pimpl_->switchCall(conf->getConfID());
+        conf->setState(Conference::State::ACTIVE_ATTACHED);
+    } else {
+        conf->detach();
+    }
 
     pimpl_->conferenceMap_.emplace(conf->getConfID(), conf);
     emitSignal<DRing::CallSignal::ConferenceCreated>(conf->getConfID());
@@ -1836,8 +1851,42 @@ Manager::incomingCall(Call &call, const std::string& accountId)
     emitSignal<DRing::CallSignal::IncomingCall>(accountId, callID, call.getPeerDisplayName() + " " + from);
 
     auto currentCall = getCurrentCall();
-    if (pimpl_->autoAnswer_) {
-        runOnMainThread([this, callID]{ answerCall(callID); });
+    if (call.getAccount().isRendezVous()) {
+        runOnMainThread([this, callID] {
+            answerCall(callID);
+            auto call = getCallFromCallID(callID);
+            auto accountId = call->getAccountId();
+            for (const auto& cid: getCallList()) {
+                if (auto call = getCallFromCallID(cid)) {
+                    if (call->getState() != Call::CallState::ACTIVE)
+                        continue;
+                    if (call->getAccountId() == accountId) {
+                        if (cid != callID) {
+                            if (call->getConfId().empty()) {
+                                joinParticipant(callID, cid, false);
+                            } else {
+                                addParticipant(callID, call->getConfId());
+                            }
+                            return;
+                        }
+                    }
+                }
+            }
+            // First call
+            auto conf = std::make_shared<Conference>();
+
+            // Bind calls according to their state
+            pimpl_->bindCallToConference(*call, *conf);
+            conf->detach();
+
+            pimpl_->conferenceMap_.emplace(conf->getConfID(), conf);
+            emitSignal<DRing::CallSignal::ConferenceCreated>(conf->getConfID());
+
+        });
+    } else if (pimpl_->autoAnswer_) {
+        runOnMainThread([this, callID]{
+            answerCall(callID);
+        });
     } else if (currentCall) {
         // Test if already calling this person
         if (currentCall->getAccountId() == accountId
diff --git a/src/manager.h b/src/manager.h
index 247d647206bb51396447ce9e09d19b880632accd..44f5c527483f0723a50b271f966ea31db4df2b64 100644
--- a/src/manager.h
+++ b/src/manager.h
@@ -285,7 +285,8 @@ class DRING_TESTABLE Manager {
          * @param the second call id
          */
         bool joinParticipant(const std::string& call_id1,
-                             const std::string& call_id2);
+                             const std::string& call_id2,
+                             bool attached = true);
 
         /**
          * Create a conference from a list of participant
diff --git a/src/media/video/video_rtp_session.cpp b/src/media/video/video_rtp_session.cpp
index ed39906ddd107d53313d695e28f5db85f41fd09d..e770d00ca3288f5c9a89f95b1a979dbf451526b1 100644
--- a/src/media/video/video_rtp_session.cpp
+++ b/src/media/video/video_rtp_session.cpp
@@ -333,15 +333,16 @@ VideoRtpSession::enterConference(Conference* conference)
     JAMI_DBG("[call:%s] enterConference (conf: %s)", callID_.c_str(),
              conference->getConfID().c_str());
 
-    if (send_.enabled or receiveThread_) {
-        videoMixer_ = conference->getVideoMixer();
+    // TODO is this correct? The video Mixer should be enabled for a detached conference even if we are not sending values
+    videoMixer_ = conference->getVideoMixer();
 #if defined(__APPLE__) && TARGET_OS_MAC
-        videoMixer_->setParameters(localVideoParams_.width,
-                                   localVideoParams_.height,
-                                   av_get_pix_fmt(localVideoParams_.pixel_format.c_str()));
+    videoMixer_->setParameters(localVideoParams_.width,
+                                localVideoParams_.height,
+                                av_get_pix_fmt(localVideoParams_.pixel_format.c_str()));
 #else
-        videoMixer_->setParameters(localVideoParams_.width, localVideoParams_.height);
+    videoMixer_->setParameters(localVideoParams_.width, localVideoParams_.height);
 #endif
+    if (send_.enabled or receiveThread_) {
         setupConferenceVideoPipeline(*conference_);
 
         // Restart encoder with conference parameter ON in order to unlink HW encoder