diff --git a/src/account.h b/src/account.h
index f11a5007612f49198e3d6279cdbb888ab6387a30..4285dd97135081006124f3b7aae7d974afd3a89f 100644
--- a/src/account.h
+++ b/src/account.h
@@ -49,18 +49,17 @@
 #include <mutex>
 #include <chrono>
 
-namespace jami {
-namespace upnp {
-class Controller;
-}
-} // namespace jami
-
 namespace YAML {
 class Emitter;
 class Node;
 } // namespace YAML
 
 namespace jami {
+static constexpr uint64_t DRING_ID_MAX_VAL = 9007199254740992;
+
+namespace upnp {
+class Controller;
+} // namespace upnp
 
 class Call;
 class SystemCodecContainer;
diff --git a/src/call_factory.cpp b/src/call_factory.cpp
index 5b6d20cfbecc7064326f46c34a81f8a63b8ce70d..e01db1024f527b4d02b822192abc769cf0ba84f8 100644
--- a/src/call_factory.cpp
+++ b/src/call_factory.cpp
@@ -23,12 +23,23 @@
 #include "call_factory.h"
 #include "sip/sipcall.h"
 #include "sip/sipaccountbase.h"
+#include "string_utils.h"
 
 namespace jami {
 
-std::shared_ptr<Call>
-CallFactory::createSipCall(const std::shared_ptr<Account>& account,
-                           const std::string& id,
+// generate something like 7ea037947eb9fb2f
+std::string
+CallFactory::getNewCallID() const
+{
+    std::string random_id;
+    do {
+        random_id = std::to_string(std::uniform_int_distribution<uint64_t>(1, DRING_ID_MAX_VAL)(rand_));
+    } while (hasCall(random_id));
+    return random_id;
+}
+
+std::shared_ptr<SIPCall>
+CallFactory::newSipCall(const std::shared_ptr<SIPAccountBase>& account,
                            Call::CallType type,
                            const std::map<std::string, std::string>& details)
 {
@@ -37,26 +48,10 @@ CallFactory::createSipCall(const std::shared_ptr<Account>& account,
         return nullptr;
     }
 
-    if (hasCall(id, Call::LinkType::SIP)) {
-        JAMI_ERR("Call %s already exists", id.c_str());
-        return nullptr;
-    }
-
-    if (std::strcmp(account->getAccountType(), "SIP") != 0
-        and std::strcmp(account->getAccountType(), "RING") != 0) {
-        JAMI_ERR("Invalid account type %s!", account->getAccountType());
-        assert(false);
-    }
-
-    auto accountBase = std::dynamic_pointer_cast<SIPAccountBase>(account);
-    assert(accountBase);
-
-    auto call = std::make_shared<SIPCall>(accountBase, id, type, details);
-    assert(call);
-
     std::lock_guard<std::recursive_mutex> lk(callMapsMutex_);
+    auto id = getNewCallID();
+    auto call = std::make_shared<SIPCall>(account, id, type, details);
     callMaps_[call->getLinkType()].emplace(id, call);
-
     return call;
 }
 
diff --git a/src/call_factory.h b/src/call_factory.h
index 343374925750bac18641ba8e7bc36e6bb272112a..4a2225c92ffbd9004e0ce8ec1a7a4a9dea313eb4 100644
--- a/src/call_factory.h
+++ b/src/call_factory.h
@@ -32,9 +32,14 @@
 
 namespace jami {
 
+class SIPAccountBase;
+class SIPCall;
+
 class CallFactory
 {
-private:
+public:
+    CallFactory(std::mt19937_64& rand) : rand_(rand) {}
+
     /**
      * Create a new call instance.
      * @param account Account used to create this call
@@ -42,21 +47,23 @@ private:
      * @param type Set the call type
      * @param details Call details
      */
-    std::shared_ptr<Call> createSipCall(const std::shared_ptr<Account>& account,
-                                        const std::string& id,
+    std::shared_ptr<SIPCall> newSipCall(const std::shared_ptr<SIPAccountBase>& account,
                                         Call::CallType type,
                                         const std::map<std::string, std::string>& details = {});
 
-public:
-    template<class A>
-    std::shared_ptr<Call> newCall(std::shared_ptr<A> account,
-                                  const std::string& id,
+    template<class C>
+    std::shared_ptr<C> newCall(std::shared_ptr<Account> account,
                                   Call::CallType type,
                                   const std::map<std::string, std::string>& details = {})
     {
-        return createSipCall(account, id, type, details);
+        if (auto base = std::dynamic_pointer_cast<SIPAccountBase>(account)) {
+            return std::dynamic_pointer_cast<C>(newSipCall(base, type, details));
+        }
+        return nullptr;
     }
 
+    std::string getNewCallID() const;
+
     /**
      * Forbid creation of new calls.
      */
@@ -78,6 +85,11 @@ public:
     std::shared_ptr<Call> getCall(const std::string& id) const;
     std::shared_ptr<Call> getCall(const std::string& id, Call::LinkType link) const;
 
+    template<class C>
+    std::shared_ptr<C> getCall(const std::string& id) {
+        return std::dynamic_pointer_cast<C>(getCall(id, C::LINK_TYPE));
+    }
+
     /**
      * Return if given call exists. Type can optionally be specified.
      */
@@ -114,6 +126,7 @@ public:
     std::size_t callCount(Call::LinkType link) const;
 
 private:
+
     /**
      * @brief Get the calls map
      * @param link The call type
@@ -130,6 +143,8 @@ private:
         return nullptr;
     }
 
+    std::mt19937_64& rand_;
+
     mutable std::recursive_mutex callMapsMutex_ {};
 
     std::atomic_bool allowNewCall_ {true};
diff --git a/src/conference.cpp b/src/conference.cpp
index f0eca3af16ceb7e2108ffea82148e731b5fe10ec..3228946a48066b303cc4ddf8474fdf28da19dc5c 100644
--- a/src/conference.cpp
+++ b/src/conference.cpp
@@ -46,7 +46,7 @@ using namespace std::literals;
 namespace jami {
 
 Conference::Conference()
-    : id_(Manager::instance().getNewCallID())
+    : id_(Manager::instance().callFactory.getNewCallID())
 #ifdef ENABLE_VIDEO
     , mediaInput_(Manager::instance().getVideoManager().videoDeviceMonitor.getMRLForDefaultDevice())
 #endif
diff --git a/src/jamidht/jamiaccount.cpp b/src/jamidht/jamiaccount.cpp
index d9748e5eed0aa36f388c39a7f300177f6614aea4..41b799750d0907cae141b267d1b716537326af33 100644
--- a/src/jamidht/jamiaccount.cpp
+++ b/src/jamidht/jamiaccount.cpp
@@ -368,15 +368,7 @@ JamiAccount::newIncomingCall(const std::string& from,
                     if (cit->transport != sipTr)
                         continue;
 
-                    auto newCall = Manager::instance().callFactory.newCall<JamiAccount>(
-                        shared(), Manager::instance().getNewCallID(), Call::CallType::INCOMING);
-                    auto call = std::dynamic_pointer_cast<SIPCall>(newCall);
-                    assert(call);
-
-                    if (!call)
-                        return {};
-
-                    std::weak_ptr<SIPCall> wcall = call;
+                    auto call = Manager::instance().callFactory.newCall<SIPCall>(shared(), Call::CallType::INCOMING);
                     call->setPeerUri(RING_URI_PREFIX + from);
                     call->setPeerNumber(from);
                     call->updateDetails(details);
@@ -415,14 +407,7 @@ JamiAccount::newOutgoingCall(std::string_view toUrl,
     auto suffix = stripPrefix(toUrl);
     JAMI_DBG() << *this << "Calling DHT peer " << suffix;
     auto& manager = Manager::instance();
-    auto newCall = manager.callFactory.newCall<JamiAccount>(shared(),
-                                                            manager.getNewCallID(),
-                                                            Call::CallType::OUTGOING,
-                                                            volatileCallDetails);
-
-    auto call = std::dynamic_pointer_cast<SIPCall>(newCall);
-    assert(call);
-
+    auto call = manager.callFactory.newCall<SIPCall>(shared(), Call::CallType::OUTGOING, volatileCallDetails);
     call->setIPToIP(true);
     call->setSecure(isTlsEnabled());
 
@@ -524,13 +509,7 @@ JamiAccount::startOutgoingCall(const std::shared_ptr<SIPCall>& call, const std::
     // NOTE: dummyCall is a call used to avoid to mark the call as failed if the
     // cached connection is failing with ICE (close event still not detected).
     auto& manager = Manager::instance();
-    auto newCall = manager.callFactory.newCall<JamiAccount>(shared(),
-                                                            manager.getNewCallID(),
-                                                            Call::CallType::OUTGOING,
-                                                            call->getDetails());
-    auto dummyCall = std::dynamic_pointer_cast<SIPCall>(newCall);
-    assert(dummyCall);
-
+    auto dummyCall = manager.callFactory.newCall<SIPCall>(shared(), Call::CallType::OUTGOING, call->getDetails());
     dummyCall->setIPToIP(true);
     dummyCall->setSecure(isTlsEnabled());
     call->addSubCall(*dummyCall);
@@ -551,14 +530,8 @@ JamiAccount::startOutgoingCall(const std::shared_ptr<SIPCall>& call, const std::
                 and state != Call::ConnectionState::TRYING)
                 return;
 
-            auto newCall = Manager::instance()
-                               .callFactory.newCall<JamiAccount>(shared(),
-                                                                 Manager::instance().getNewCallID(),
-                                                                 Call::CallType::OUTGOING,
-                                                                 call->getDetails());
-            auto dev_call = std::dynamic_pointer_cast<SIPCall>(newCall);
-            assert(dev_call);
-
+            auto dev_call = Manager::instance()
+                               .callFactory.newCall<SIPCall>(shared(), Call::CallType::OUTGOING, call->getDetails());
             dev_call->setIPToIP(true);
             dev_call->setSecure(isTlsEnabled());
             dev_call->setState(Call::ConnectionState::TRYING);
@@ -602,13 +575,7 @@ JamiAccount::startOutgoingCall(const std::shared_ptr<SIPCall>& call, const std::
         JAMI_WARN("[call %s] A channeled socket is detected with this peer.",
                   call->getCallId().c_str());
 
-        auto newCall = manager.callFactory.newCall<JamiAccount>(shared(),
-                                                                manager.getNewCallID(),
-                                                                Call::CallType::OUTGOING,
-                                                                call->getDetails());
-        auto dev_call = std::dynamic_pointer_cast<SIPCall>(newCall);
-        assert(dev_call);
-
+        auto dev_call = manager.callFactory.newCall<SIPCall>(shared(), Call::CallType::OUTGOING, call->getDetails());
         dev_call->setIPToIP(true);
         dev_call->setSecure(isTlsEnabled());
         dev_call->setTransport(transport);
@@ -2430,13 +2397,8 @@ JamiAccount::incomingCall(dht::IceCandidates&& msg,
                           const std::shared_ptr<dht::crypto::Certificate>& from_cert,
                           const dht::InfoHash& from)
 {
-    auto newCall = Manager::instance()
-                       .callFactory.newCall<JamiAccount>(shared(),
-                                                         Manager::instance().getNewCallID(),
-                                                         Call::CallType::INCOMING);
-    auto call = std::dynamic_pointer_cast<SIPCall>(newCall);
-    assert(call);
-
+    auto call = Manager::instance()
+                       .callFactory.newCall<SIPCall>(shared(), Call::CallType::INCOMING);
     if (!call) {
         return;
     }
diff --git a/src/manager.cpp b/src/manager.cpp
index a864f040409acbb6802f30a8329cc821a269f448..b3c6e0ac38f42cfaa7526a16a842150a93435c85 100644
--- a/src/manager.cpp
+++ b/src/manager.cpp
@@ -421,8 +421,6 @@ struct Manager::ManagerPimpl
 
     std::atomic_bool finished_ {false};
 
-    std::mt19937_64 rand_;
-
     /* ICE support */
     std::unique_ptr<IceTransportFactory> ice_tf_;
 
@@ -446,7 +444,6 @@ Manager::ManagerPimpl::ManagerPimpl(Manager& base)
     , toneCtrl_(base.preferences)
     , dtmfBuf_(0, AudioFormat::MONO())
     , ringbufferpool_(new RingBufferPool)
-    , rand_(dht::crypto::getSeededRandomEngine<std::mt19937_64>())
 #ifdef ENABLE_VIDEO
     , videoManager_(new VideoManager)
 #endif
@@ -714,7 +711,8 @@ Manager::instance()
 }
 
 Manager::Manager()
-    : preferences()
+    : rand_(dht::crypto::getSeededRandomEngine<std::mt19937_64>())
+    , preferences()
     , voipPreferences()
     , audioPreference()
     , shortcutPreferences()
@@ -724,7 +722,7 @@ Manager::Manager()
 #ifdef ENABLE_VIDEO
     , videoPreferences()
 #endif
-    , callFactory()
+    , callFactory(rand_)
     , accountFactory()
     , dataTransfers(std::make_unique<DataTransferFacade>())
     , pimpl_(new ManagerPimpl(*this))
@@ -2769,18 +2767,11 @@ Manager::testAccountICEInitialization(const std::string& accountID)
 std::string
 Manager::getNewAccountId()
 {
-    std::string newAccountID;
-    static std::uniform_int_distribution<uint64_t> rand_acc_id;
-
-    const std::vector<std::string> accountList(getAccountList());
-
+    std::string random_id;
     do {
-        std::ostringstream accId;
-        accId << std::hex << rand_acc_id(pimpl_->rand_);
-        newAccountID = accId.str();
-    } while (std::find(accountList.begin(), accountList.end(), newAccountID) != accountList.end());
-
-    return newAccountID;
+        random_id = to_hex_string(std::uniform_int_distribution<uint64_t>()(rand_));
+    } while (getAccount(random_id));
+    return random_id;
 }
 
 std::string
@@ -2847,19 +2838,6 @@ Manager::removeAccounts()
         removeAccount(acc);
 }
 
-std::string
-Manager::getNewCallID()
-{
-    std::ostringstream random_id;
-
-    // generate something like s7ea037947eb9fb2f
-    do {
-        random_id.clear();
-        random_id << std::uniform_int_distribution<uint64_t>(1, DRING_ID_MAX_VAL)(pimpl_->rand_);
-    } while (callFactory.hasCall(random_id.str()));
-
-    return random_id.str();
-}
 
 std::vector<std::string_view>
 Manager::loadAccountOrder() const
diff --git a/src/manager.h b/src/manager.h
index 60012200fa2895dabcf0f9362cf0cdde38e292cd..c5a2bb1ef097d925b9717c8497b4cc3c47121c56 100644
--- a/src/manager.h
+++ b/src/manager.h
@@ -64,12 +64,13 @@ class JamiAccount;
 class SIPVoIPLink;
 class JamiPluginManager;
 
-static constexpr uint64_t DRING_ID_MAX_VAL = 9007199254740992;
 
 /** Manager (controller) of daemon */
 // TODO DRING_PUBLIC only if tests
 class DRING_TESTABLE Manager
 {
+private:
+    std::mt19937_64 rand_;
 public:
     // TODO DRING_PUBLIC only if tests
     static DRING_TESTABLE Manager& instance();
@@ -752,12 +753,6 @@ public:
      */
     bool incomingCallsWaiting();
 
-    /**
-     * Return a new random callid that is not present in the list
-     * @return std::string A brand new callid
-     */
-    std::string getNewCallID();
-
     /**
      * Get the current call
      * @return std::shared_ptr<Call> A call shared pointer (could be empty)
diff --git a/src/plugin/callservicesmanager.cpp b/src/plugin/callservicesmanager.cpp
index 13541e0d793322181b788731d4294d85e520ed3e..a1749bb46bbc97110330016f87ed7e0bd9425928 100644
--- a/src/plugin/callservicesmanager.cpp
+++ b/src/plugin/callservicesmanager.cpp
@@ -253,10 +253,9 @@ CallServicesManager::toggleCallMediaHandler(const uintptr_t mediaHandlerId,
     }
 #ifndef __ANDROID__
     if (applyRestart) {
-        auto sipCall = std::dynamic_pointer_cast<SIPCall>(
-            Manager::instance().callFactory.getCall(callId, Call::LinkType::SIP));
-        assert(sipCall);
-        sipCall->getVideoRtp().restartSender();
+        if (auto call = Manager::instance().callFactory.getCall<SIPCall>(callId)) {
+            call->getVideoRtp().restartSender();
+        }
     }
 #endif
 }
diff --git a/src/sip/sipaccount.cpp b/src/sip/sipaccount.cpp
index 5657dc7264ec86079233297e1fa0570de47052ca..30e2209adcf481b94ca9c4d41a962529079a0961 100644
--- a/src/sip/sipaccount.cpp
+++ b/src/sip/sipaccount.cpp
@@ -180,14 +180,7 @@ SIPAccount::newIncomingCall(const std::string& from UNUSED,
                             const std::shared_ptr<SipTransport>&)
 {
     auto& manager = Manager::instance();
-    auto call = manager.callFactory.newCall<SIPAccount>(shared(),
-                                                        manager.getNewCallID(),
-                                                        Call::CallType::INCOMING,
-                                                        details);
-
-    auto sipCall = std::dynamic_pointer_cast<SIPCall>(call);
-    assert(sipCall);
-    return sipCall;
+    return manager.callFactory.newCall<SIPCall>(shared(), Call::CallType::INCOMING, details);
 }
 
 template<>
@@ -201,13 +194,7 @@ SIPAccount::newOutgoingCall(std::string_view toUrl,
     JAMI_DBG() << *this << "Calling SIP peer " << toUrl;
 
     auto& manager = Manager::instance();
-    auto newCall = manager.callFactory.newCall<SIPAccount>(shared(),
-                                                           manager.getNewCallID(),
-                                                           Call::CallType::OUTGOING,
-                                                           volatileCallDetails);
-    auto call = std::dynamic_pointer_cast<SIPCall>(newCall);
-    assert(call);
-
+    auto call = manager.callFactory.newCall<SIPCall>(shared(), Call::CallType::OUTGOING, volatileCallDetails);
     call->setSecure(isTlsEnabled());
 
     if (isIP2IP()) {
diff --git a/src/sip/sipcall.cpp b/src/sip/sipcall.cpp
index e77e5724ee84136573984c26869c16cee9dd6424..022e0d29d9afd1577609af9e166ed0b16bec4769 100644
--- a/src/sip/sipcall.cpp
+++ b/src/sip/sipcall.cpp
@@ -738,9 +738,7 @@ SIPCall::transfer(const std::string& to)
 bool
 SIPCall::attendedTransfer(const std::string& to)
 {
-    auto toCall = std::dynamic_pointer_cast<SIPCall>(
-        Manager::instance().callFactory.getCall(to, getLinkType()));
-
+    auto toCall = Manager::instance().callFactory.getCall<SIPCall>(to);
     if (!toCall)
         return false;
 
diff --git a/src/sip/sipcall.h b/src/sip/sipcall.h
index dd12e380b475c684a9ceb50485b3e379b4a8af27..619769accb12f1d988a4f2288282d1e4e694f35d 100644
--- a/src/sip/sipcall.h
+++ b/src/sip/sipcall.h
@@ -74,6 +74,7 @@ class Controller;
 class SIPCall : public Call
 {
 public:
+    static constexpr LinkType LINK_TYPE = LinkType::SIP;
     /**
      * Destructor
      */
@@ -90,7 +91,7 @@ public:
             const std::map<std::string, std::string>& details = {});
 
     // Inherited from Call class
-    LinkType getLinkType() const { return LinkType::SIP; }
+    LinkType getLinkType() const override { return LINK_TYPE; }
     void answer() override;
     void hangup(int reason) override;
     void refuse() override;
@@ -180,7 +181,7 @@ public:
 
     void requestKeyframe();
 
-    void updateRecState(bool state);
+    void updateRecState(bool state) override;
 
     std::shared_ptr<SIPAccountBase> getSIPAccount() const;