diff --git a/src/account.cpp b/src/account.cpp
index a961e6980e3afdb2e5a55fb6bb07f242193e19c4..29eb4588125d96992fdcba7c7f4d95730c35c817 100644
--- a/src/account.cpp
+++ b/src/account.cpp
@@ -96,6 +96,7 @@ const char* const Account::DEFAULT_MODERATORS_KEY = "defaultModerators";
 const char* const Account::LOCAL_MODERATORS_ENABLED_KEY = "localModeratorsEnabled";
 const char* const Account::ALL_MODERATORS_ENABLED_KEY = "allModeratorsEnabled";
 const char* const Account::PROXY_PUSH_TOKEN_KEY = "proxyPushToken";
+const char* const Account::PROXY_PUSH_IOS_TOPIC_KEY = "proxyPushiOSTopic";
 
 // For portability, do not specify the absolute file name of the ring
 // tone.  Instead, specify its base name to be looked in
@@ -236,6 +237,7 @@ Account::serialize(YAML::Emitter& out) const
     out << YAML::Key << LOCAL_MODERATORS_ENABLED_KEY << YAML::Value << localModeratorsEnabled_;
     out << YAML::Key << ALL_MODERATORS_ENABLED_KEY << YAML::Value << allModeratorsEnabled_;
     out << YAML::Key << PROXY_PUSH_TOKEN_KEY << YAML::Value << deviceKey_;
+    out << YAML::Key << PROXY_PUSH_IOS_TOPIC_KEY << YAML::Value << notificationTopic_;
 }
 
 void
@@ -294,6 +296,7 @@ Account::unserialize(const YAML::Node& node)
     parseValueOptional(node, LOCAL_MODERATORS_ENABLED_KEY, localModeratorsEnabled_);
     parseValueOptional(node, ALL_MODERATORS_ENABLED_KEY, allModeratorsEnabled_);
     parseValueOptional(node, PROXY_PUSH_TOKEN_KEY, deviceKey_);
+    parseValueOptional(node, PROXY_PUSH_IOS_TOPIC_KEY, notificationTopic_);
 }
 
 void
diff --git a/src/account.h b/src/account.h
index 0b519b1975e0765643c9df42ef8c29b75fe59579..e88f0a2aac903348d7caf406dec6864e862f4b6f 100644
--- a/src/account.h
+++ b/src/account.h
@@ -198,6 +198,11 @@ public:
         deviceKey_ = pushDeviceToken;
     }
 
+    virtual void setPushNotificationTopic(const std::string& topic = "")
+    {
+        notificationTopic_ = topic;
+    }
+
     /**
      * Tell if the account is enable or not.
      * @return true if enabled, false otherwise
@@ -461,6 +466,7 @@ protected:
     static const char* const PROXY_ENABLED_KEY;
     static const char* const PROXY_SERVER_KEY;
     static const char* const PROXY_PUSH_TOKEN_KEY;
+    static const char* const PROXY_PUSH_IOS_TOPIC_KEY;
     static const char* const ACTIVE_CODEC_KEY;
     static const char* const DEFAULT_MODERATORS_KEY;
     static const char* const LOCAL_MODERATORS_ENABLED_KEY;
@@ -604,6 +610,11 @@ protected:
      */
     std::string deviceKey_ {};
 
+    /**
+     * Push notification topic.
+     */
+    std::string notificationTopic_ {};
+
     /**
      * private account codec searching functions
      */
diff --git a/src/client/configurationmanager.cpp b/src/client/configurationmanager.cpp
index e3fa3edc30e574da81e5c2bc6733329716122eef..bd9689961e76c5bc2bb8d00b75352a8baf8eb4fb 100644
--- a/src/client/configurationmanager.cpp
+++ b/src/client/configurationmanager.cpp
@@ -1027,6 +1027,13 @@ setPushNotificationToken(const std::string& token)
         account->setPushNotificationToken(token);
     }
 }
+void
+setPushNotificationTopic(const std::string& topic)
+{
+    for (const auto& account : jami::Manager::instance().getAllAccounts()) {
+        account->setPushNotificationTopic(topic);
+    }
+}
 
 void
 pushNotificationReceived(const std::string& from, const std::map<std::string, std::string>& data)
diff --git a/src/jami/configurationmanager_interface.h b/src/jami/configurationmanager_interface.h
index 75644e63003f98853ee84d197e47873ab64dec64..44731f67b6d94161519fbe2c5580b63c6a1abd97 100644
--- a/src/jami/configurationmanager_interface.h
+++ b/src/jami/configurationmanager_interface.h
@@ -58,7 +58,9 @@ DRING_PUBLIC std::map<std::string, std::string> getVolatileAccountDetails(
     const std::string& accountID);
 DRING_PUBLIC void setAccountDetails(const std::string& accountID,
                                     const std::map<std::string, std::string>& details);
-DRING_PUBLIC void setAccountActive(const std::string& accountID, bool active, bool shutdownConnections = false);
+DRING_PUBLIC void setAccountActive(const std::string& accountID,
+                                   bool active,
+                                   bool shutdownConnections = false);
 DRING_PUBLIC std::map<std::string, std::string> getAccountTemplate(const std::string& accountType);
 DRING_PUBLIC std::string addAccount(const std::map<std::string, std::string>& details,
                                     const std::string& accountID = {});
@@ -254,6 +256,12 @@ DRING_PUBLIC void enableProxyClient(const std::string& accountID, bool enable);
  */
 DRING_PUBLIC void setPushNotificationToken(const std::string& pushDeviceToken);
 
+/**
+ * Set the topic for ios
+ * bundle_id for ios 14.5 and higher
+ * bundle_id.voip for ios prior 14.5
+ */
+DRING_PUBLIC void setPushNotificationTopic(const std::string& topic);
 /**
  * To be called by clients with relevant data when a push notification is received.
  */
diff --git a/src/jamidht/jamiaccount.cpp b/src/jamidht/jamiaccount.cpp
index 88291d7ea55fc44e8072977a4b3e43879806120b..82a2afd402bbd99821f173666987019ea6e346aa 100644
--- a/src/jamidht/jamiaccount.cpp
+++ b/src/jamidht/jamiaccount.cpp
@@ -1963,6 +1963,7 @@ JamiAccount::doRegister_()
         config.dht_config.cert_cache_all = true;
         config.push_node_id = getAccountID();
         config.push_token = deviceKey_;
+        config.push_topic = notificationTopic_;
         config.threaded = true;
         config.peer_discovery = dhtPeerDiscovery_;
         config.peer_publish = dhtPeerDiscovery_;
@@ -3502,6 +3503,13 @@ JamiAccount::setPushNotificationToken(const std::string& token)
     dht_->setPushNotificationToken(deviceKey_);
 }
 
+void
+JamiAccount::setPushNotificationTopic(const std::string& topic)
+{
+    notificationTopic_ = topic;
+    dht_->setPushNotificationTopic(notificationTopic_);
+}
+
 /**
  * To be called by clients with relevant data when a push notification is received.
  */
diff --git a/src/jamidht/jamiaccount.h b/src/jamidht/jamiaccount.h
index bf9250fa7f262191a0bc2026ef377640d6d4e044..8f876c0940b2626f13707a3a6197063c65407739 100644
--- a/src/jamidht/jamiaccount.h
+++ b/src/jamidht/jamiaccount.h
@@ -401,11 +401,20 @@ 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_;
+    }
 
-    const std::shared_future<tls::DhParams> dhParams() const { return dhParams_; }
+    const std::shared_future<tls::DhParams> dhParams() const
+    {
+        return dhParams_;
+    }
 
     void forEachDevice(const dht::InfoHash& to,
                        std::function<void(const std::shared_ptr<dht::crypto::PublicKey>&)>&& op,
@@ -420,6 +429,8 @@ public:
 
     void setPushNotificationToken(const std::string& pushDeviceToken = "") override;
 
+    void setPushNotificationTopic(const std::string& topic) override;
+
     /**
      * To be called by clients with relevant data when a push notification is received.
      */
@@ -462,13 +473,19 @@ public:
     void getIceOptions(std::function<void(IceTransportOptions&&)> cb) noexcept;
 
 #ifdef DRING_TESTABLE
-    ConnectionManager& connectionManager() { return *connectionManager_; }
+    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;
+    }
 #endif
 
     /**
@@ -581,9 +598,15 @@ public:
 
     std::string profilePath() const;
 
-    AccountManager* accountManager() { return accountManager_.get(); }
+    AccountManager* accountManager()
+    {
+        return accountManager_.get();
+    }
 
-    bool sha3SumVerify() const { return !noSha3sumVerification_; }
+    bool sha3SumVerify() const
+    {
+        return !noSha3sumVerification_;
+    }
 
     /**
      * Change certificate's validity period