diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1aa5c52816832c998b63a046ebaae7042f740be8..b9dbf8f82c295f358f31b484eb396fe029d7f7f4 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -223,6 +223,13 @@ list (APPEND opendht_SOURCES
     src/thread_pool.cpp
 )
 
+if (APPLE)
+    list (APPEND opendht_SOURCES
+        src/compat/apple/apple_utils.h
+        src/compat/apple/apple_utils.mm
+    )
+endif()
+
 list (APPEND opendht_HEADERS
     include/opendht/def.h
     include/opendht/utils.h
diff --git a/c/opendht.cpp b/c/opendht.cpp
index a6de6b9769a63bcb47b54c969bc6a6d0e479a856..dd61b3cf45a702e916b385081923a250af9974a7 100644
--- a/c/opendht.cpp
+++ b/c/opendht.cpp
@@ -342,6 +342,7 @@ int dht_runner_run_config(dht_runner* r, in_port_t port, const dht_runner_config
         config.proxy_server = conf->proxy_server ? std::string(conf->proxy_server) : std::string{};
         config.push_node_id = conf->push_node_id ? std::string(conf->push_node_id) : std::string{};
         config.push_token = conf->push_token ? std::string(conf->push_token) : std::string{};
+        config.push_topic = conf->push_topic ? std::string(conf->push_topic) : std::string{};
         config.peer_discovery = conf->peer_discovery;
         config.peer_publish = conf->peer_publish;
 
diff --git a/c/opendht_c.h b/c/opendht_c.h
index cf67a0f896520f52e844d2c14aa6719e142720dd..5cdad798ead947551af3112133794c6a0a06843e 100644
--- a/c/opendht_c.h
+++ b/c/opendht_c.h
@@ -146,6 +146,7 @@ struct OPENDHT_PUBLIC dht_runner_config {
     const char* proxy_server;
     const char* push_node_id;
     const char* push_token;
+    const char* push_topic;
     bool peer_discovery;
     bool peer_publish;
     dht_certificate* server_ca;
diff --git a/configure.ac b/configure.ac
index ee9f1805206b0a188db472d97f116e0739488609..48f4aa528beabedf49cb9e06fd965d5b70ed6582 100644
--- a/configure.ac
+++ b/configure.ac
@@ -32,6 +32,7 @@ LT_INIT()
 LT_LANG(C++)
 AC_LANG(C++)
 AC_PROG_CXX
+AC_PROG_OBJCXX
 AX_CXX_COMPILE_STDCXX(17,[noext],[mandatory])
 
 dnl Check for logs
@@ -91,6 +92,7 @@ case "${host_os}" in
     SYS=linux
     ;;
   darwin*)
+    APPLE=1
     SYS=darwin
     ;;
   mingw32*)
@@ -110,6 +112,7 @@ case "${host_os}" in
     ;;
 esac
 
+AM_CONDITIONAL(APPLE, [test "x$SYS" = "xdarwin"])
 AM_CONDITIONAL(WIN32, [test "x$SYS" = "xmingw32"])
 AS_IF([test "x$SYS" = "xandroid"],
       [], [LDFLAGS="${LDFLAGS} -lpthread"])
@@ -188,6 +191,7 @@ AM_COND_IF([PROXY_CLIENT_OR_SERVER], [
 ])
 
 CXXFLAGS="${CXXFLAGS} -DMSGPACK_NO_BOOST -DMSGPACK_DISABLE_LEGACY_NIL -DMSGPACK_DISABLE_LEGACY_CONVERT"
+OBJCXX="$CXX $CXXFLAGS"
 
 AC_ARG_ENABLE([tools], AS_HELP_STRING([--disable-tools],[Disable tools (CLI DHT node)]),,build_tools=yes)
 AM_CONDITIONAL(ENABLE_TOOLS, test x$build_tools == xyes)
diff --git a/include/opendht/dht_interface.h b/include/opendht/dht_interface.h
index bb0362f071859d79113c9e45a1caeec1b7230c7b..41ab734d7c618fe924d97a25b36f2fca8372705b 100644
--- a/include/opendht/dht_interface.h
+++ b/include/opendht/dht_interface.h
@@ -265,6 +265,8 @@ public:
 
     virtual void setPushNotificationToken(const std::string&) {};
 
+    virtual void setPushNotificationTopic(const std::string&) {};
+
     /**
      * Call linked callback with a push notification
      * @param notification to process
diff --git a/include/opendht/dht_proxy_client.h b/include/opendht/dht_proxy_client.h
index 7be198f9c4708de35171852307f9c1e3c4edcf18..ce70a48d093bdacf473e34f050f1931d5df0ddc0 100644
--- a/include/opendht/dht_proxy_client.h
+++ b/include/opendht/dht_proxy_client.h
@@ -67,6 +67,14 @@ public:
 #endif
     }
 
+    virtual void setPushNotificationTopic(const std::string& topic) override {
+#ifdef OPENDHT_PUSH_NOTIFICATIONS
+        notificationTopic_ = topic;
+#else
+        (void) topic;
+#endif
+    }
+
     virtual ~DhtProxyClient();
 
     /**
@@ -400,6 +408,11 @@ private:
      */
     std::string deviceKey_ {};
 
+    /**
+     * Notification topic for ios notifications.
+     */
+    std::string notificationTopic_ {};
+
     const std::function<void()> loopSignal_;
 
 #ifdef OPENDHT_PUSH_NOTIFICATIONS
diff --git a/include/opendht/dht_proxy_server.h b/include/opendht/dht_proxy_server.h
index e1facd70aee390834e3aa7096f5e92aef09be721..ac4cb248535f09e865abcdf778ddd28b55f9582f 100644
--- a/include/opendht/dht_proxy_server.h
+++ b/include/opendht/dht_proxy_server.h
@@ -40,7 +40,8 @@ namespace dht {
 enum class PushType {
     None = 0,
     Android,
-    iOS
+    iOS,
+    iOSLegacy
 };
 }
 MSGPACK_ADD_ENUM(dht::PushType)
@@ -273,6 +274,7 @@ private:
                            restinio::router::route_params_t params);
 
 #ifdef OPENDHT_PUSH_NOTIFICATIONS
+    PushType getTypeFromString(const std::string& type);
     /**
      * Subscribe to push notifications for an iOS or Android device.
      * Method: SUBSCRIBE "/{InfoHash: .*}"
@@ -300,7 +302,7 @@ private:
      * @param key of the device
      * @param json, the content to send
      */
-    void sendPushNotification(const std::string& key, Json::Value&& json, PushType type, bool highPriority);
+    void sendPushNotification(const std::string& key, Json::Value&& json, PushType type, bool highPriority, const std::string& topic);
 
     /**
      * Send push notification with an expire timeout.
@@ -308,9 +310,10 @@ private:
      * @param pushToken
      * @param json
      * @param type
+     * @param topic
      */
     void handleNotifyPushListenExpire(const asio::error_code &ec, const std::string pushToken,
-                                      std::function<Json::Value()> json, PushType type);
+                                      std::function<Json::Value()> json, PushType type, const std::string& topic);
 
     /**
      * Remove a push listener between a client and a hash
@@ -382,6 +385,7 @@ private:
         std::unique_ptr<asio::steady_timer> expireNotifyTimer;
         Sp<Value> value;
         PushType type;
+        std::string topic;
 
         template <typename Packer>
         void msgpack_pack(Packer& p) const
@@ -425,6 +429,7 @@ private:
         std::unique_ptr<asio::steady_timer> expireTimer;
         std::unique_ptr<asio::steady_timer> expireNotifyTimer;
         PushType type;
+        std::string topic;
 
         template <typename Packer>
         void msgpack_pack(Packer& p) const
diff --git a/include/opendht/dhtrunner.h b/include/opendht/dhtrunner.h
index 0fdcf8d005106376f9a8a4fac1d5e856bbb5c91a..2ea3c4f83e35422d41b653def84852dbbbc8e422 100644
--- a/include/opendht/dhtrunner.h
+++ b/include/opendht/dhtrunner.h
@@ -61,6 +61,7 @@ public:
         std::string proxy_server {};
         std::string push_node_id {};
         std::string push_token {};
+        std::string push_topic {};
         bool peer_discovery {false};
         bool peer_publish {false};
         std::shared_ptr<dht::crypto::Certificate> server_ca;
@@ -447,6 +448,11 @@ public:
      */
     void setPushNotificationToken(const std::string& token);
 
+     /**
+     * Sets the push notification topic
+     */
+    void setPushNotificationTopic(const std::string& topic);
+
     /**
      * Insert a push notification to process for OpenDHT
      */
diff --git a/rust/src/dhtrunner.rs b/rust/src/dhtrunner.rs
index 114614d1ec31426ccfeffa12e5b1fc7c4bffdcf4..3470e3db4f553deb625b4d63fd3b42592bc5fbbb 100644
--- a/rust/src/dhtrunner.rs
+++ b/rust/src/dhtrunner.rs
@@ -47,6 +47,7 @@ impl DhtRunnerConfig {
             proxy_server: ptr::null(),
             push_node_id: ptr::null(),
             push_token: ptr::null(),
+            push_topic: ptr::null(),
             peer_discovery: false,
             peer_publish: false,
             server_ca: ptr::null_mut(),
@@ -73,6 +74,10 @@ impl DhtRunnerConfig {
         self.push_token = CString::new(push_token).unwrap().as_ptr();
     }
 
+    pub fn set_push_topic(&mut self, push_topic: &str) {
+        self.push_topic = CString::new(push_topic).unwrap().as_ptr();
+    }
+
     pub fn set_identity(&mut self, certificate: Box<DhtCertificate>, privatekey: Box<PrivateKey>) {
         self.dht_config.id.privatekey = Box::into_raw(privatekey);
         self.dht_config.id.certificate = Box::into_raw(certificate);
diff --git a/rust/src/ffi.rs b/rust/src/ffi.rs
index 7470cc26b89632b91f27a17b72d90d4eb5a0fb0f..97cac9acfa587ada4c9d6b15e384c9423a336b6b 100644
--- a/rust/src/ffi.rs
+++ b/rust/src/ffi.rs
@@ -118,6 +118,7 @@ pub struct DhtRunnerConfig
     pub proxy_server: *const c_char,
     pub push_node_id: *const c_char,
     pub push_token: *const c_char,
+    pub push_topic: *const c_char,
     pub peer_discovery: bool,
     pub peer_publish: bool,
     pub server_ca: *mut DhtCertificate,
diff --git a/src/Makefile.am b/src/Makefile.am
index acaccf79620963c78278408aeca154b1c830cf2b..e7a23ad7b9edf128d2a9fb6691599248a85acab5 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -30,6 +30,12 @@ libopendht_la_SOURCES  = \
         network_utils.cpp \
         thread_pool.cpp
 
+if APPLE
+libopendht_la_SOURCES += \
+        compat/apple/apple_utils.h \
+        compat/apple/apple_utils.mm
+endif
+
 if WIN32
 libopendht_la_SOURCES += rng.cpp
 endif
diff --git a/src/compat/apple/apple_utils.h b/src/compat/apple/apple_utils.h
new file mode 100644
index 0000000000000000000000000000000000000000..e308398a30146f4b10827abad30bc5f4c239d0de
--- /dev/null
+++ b/src/compat/apple/apple_utils.h
@@ -0,0 +1,26 @@
+/*
+ *  Copyright (C) 2014-2022 Savoir-faire Linux Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <string>
+
+namespace dht {
+namespace apple_utils {
+
+std::string getPlatformVersion();
+
+}
+}
diff --git a/src/compat/apple/apple_utils.mm b/src/compat/apple/apple_utils.mm
new file mode 100644
index 0000000000000000000000000000000000000000..427f4f1ca84b517ca486a2ae99f6ab2c22f3fb68
--- /dev/null
+++ b/src/compat/apple/apple_utils.mm
@@ -0,0 +1,44 @@
+/*
+ *  Copyright (C) 2014-2022 Savoir-faire Linux Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include "apple_utils.h"
+
+#ifdef __APPLE__
+#include <Foundation/Foundation.h>
+#include "TargetConditionals.h"
+#endif
+
+namespace dht {
+namespace apple_utils {
+
+std::string
+getPlatformVersion() {
+#ifdef __APPLE__
+    #if TARGET_OS_IPHONE
+    if (@available(iOS 14.5, *)) {
+        return  "ios";
+    }
+    return "apple";
+    #elif TARGET_OS_MAC
+    return "macos";
+    #endif
+#endif
+    return "";
+}
+
+}
+} /* dht */
diff --git a/src/dht_proxy_client.cpp b/src/dht_proxy_client.cpp
index 71d01aee30e7f6f25d9ca17ff6f5039eaa3c792a..1385076ab5724716e3066789678d47202bc04f86 100644
--- a/src/dht_proxy_client.cpp
+++ b/src/dht_proxy_client.cpp
@@ -22,10 +22,14 @@
 #include "dhtrunner.h"
 #include "op_cache.h"
 #include "utils.h"
+#ifdef __APPLE__
+#include "compat/apple/apple_utils.h"
+#endif
 
 #include <http_parser.h>
 #include <deque>
 
+
 namespace dht {
 
 struct DhtProxyClient::InfoState {
@@ -1303,7 +1307,8 @@ DhtProxyClient::getPushRequest(Json::Value& body) const
     body["platform"] = "android";
 #endif
 #ifdef __APPLE__
-    body["platform"] = "apple";
+    body["topic"] = notificationTopic_;
+    body["platform"] = apple_utils::getPlatformVersion();
 #endif
 }
 
diff --git a/src/dht_proxy_server.cpp b/src/dht_proxy_server.cpp
index 92c5148566b37e5c5c26b125b1396f628c70d55a..56d3ec65946b40105594bf817956f9dbca98ca7e 100644
--- a/src/dht_proxy_server.cpp
+++ b/src/dht_proxy_server.cpp
@@ -372,7 +372,7 @@ DhtProxyServer::loadState(Is& is, size_t size) {
                             pput.second.expireNotifyTimer = std::make_unique<asio::steady_timer>(io_context(), pput.second.expiration - proxy::OP_MARGIN);
                             pput.second.expireNotifyTimer->async_wait(std::bind(
                                 &DhtProxyServer::handleNotifyPushListenExpire, this,
-                                std::placeholders::_1, pput.second.pushToken, std::move(jsonProvider), pput.second.type));
+                                std::placeholders::_1, pput.second.pushToken, std::move(jsonProvider), pput.second.type, pput.second.topic));
                         }
 #endif
                         dht_->put(put.first, pput.second.value, DoneCallbackSimple{}, time_point::max(), true);
@@ -392,7 +392,7 @@ DhtProxyServer::loadState(Is& is, size_t size) {
                     for (auto& listeners : pushListener.second.listeners) {
                         for (auto& listener : listeners.second) {
                             listener.internalToken = dht_->listen(listeners.first,
-                                [this, infoHash=listeners.first, pushToken=pushListener.first, type=listener.type, clientId=listener.clientId, sessionCtx = listener.sessionCtx]
+                                [this, infoHash=listeners.first, pushToken=pushListener.first, type=listener.type, clientId=listener.clientId, sessionCtx = listener.sessionCtx, topic=listener.topic]
                                 (const std::vector<std::shared_ptr<Value>>& values, bool expired) {
                                     // Build message content
                                     Json::Value json;
@@ -414,7 +414,7 @@ DhtProxyServer::loadState(Is& is, size_t size) {
                                     auto maxPrio = 1000u;
                                     for (const auto& v : values)
                                         maxPrio = std::min(maxPrio, v->priority);
-                                    sendPushNotification(pushToken, std::move(json), type, !expired and maxPrio == 0);
+                                    sendPushNotification(pushToken, std::move(json), type, !expired and maxPrio == 0, topic);
                                     return true;
                                 }
                             );
@@ -429,7 +429,7 @@ DhtProxyServer::loadState(Is& is, size_t size) {
                                 return json;
                             };
                             listener.expireNotifyTimer->async_wait(std::bind(&DhtProxyServer::handleNotifyPushListenExpire, this,
-                                                                std::placeholders::_1, pushListener.first, std::move(jsonProvider), listener.type));
+                                                                std::placeholders::_1, pushListener.first, std::move(jsonProvider), listener.type, listener.topic));
                             // cancel push listen
                             listener.expireTimer = std::make_unique<asio::steady_timer>(io_context(), listener.expiration);
                             listener.expireTimer->async_wait(std::bind(&DhtProxyServer::handleCancelPushListen, this,
@@ -745,6 +745,21 @@ DhtProxyServer::listen(restinio::request_handle_t request,
 
 #ifdef OPENDHT_PUSH_NOTIFICATIONS
 
+PushType
+DhtProxyServer::getTypeFromString(const std::string& type) {
+    if (type == "android") {
+        return PushType::Android;
+    }
+    if (type == "apple") {
+        // proxy_client is not updated or using ios < 14.5
+        return PushType::iOSLegacy;
+    }
+    if (type == "ios") {
+        return PushType::iOS;
+    }
+    return PushType::None;
+}
+
 RequestStatus
 DhtProxyServer::subscribe(restinio::request_handle_t request,
                           restinio::router::route_params_t params)
@@ -771,7 +786,8 @@ DhtProxyServer::subscribe(restinio::request_handle_t request,
             response.set_body(RESP_MSG_NO_TOKEN);
             return response.done();
         }
-        auto type = root["platform"].asString() == "android" ? PushType::Android : PushType::iOS;
+        auto type = getTypeFromString(root["platform"].asString());
+        auto topic = root["topic"].asString();
         auto clientId = root["client_id"].asString();
         auto sessionId = root["session_id"].asString();
 
@@ -802,6 +818,7 @@ DhtProxyServer::subscribe(restinio::request_handle_t request,
         auto timeout = std::chrono::steady_clock::now() + proxy::OP_TIMEOUT;
         listener.expiration = timeout;
         listener.type = type;
+        listener.topic = topic;
         if (listener.expireNotifyTimer)
             listener.expireNotifyTimer->expires_at(timeout - proxy::OP_MARGIN);
         else
@@ -815,7 +832,7 @@ DhtProxyServer::subscribe(restinio::request_handle_t request,
             return json;
         };
         listener.expireNotifyTimer->async_wait(std::bind(&DhtProxyServer::handleNotifyPushListenExpire, this,
-                                               std::placeholders::_1, pushToken, std::move(jsonProvider), listener.type));
+                                               std::placeholders::_1, pushToken, std::move(jsonProvider), listener.type, listener.topic));
         if (!listener.expireTimer)
             listener.expireTimer = std::make_unique<asio::steady_timer>(io_context(), timeout);
         else
@@ -850,7 +867,7 @@ DhtProxyServer::subscribe(restinio::request_handle_t request,
             // =========== No existing listener for an infoHash ============
             // Add listen on dht
             listener.internalToken = dht_->listen(infoHash,
-                [this, infoHash, pushToken, type, clientId, sessionCtx = listener.sessionCtx]
+                [this, infoHash, pushToken, type, clientId, sessionCtx = listener.sessionCtx, topic]
                 (const std::vector<std::shared_ptr<Value>>& values, bool expired){
                     // Build message content
                     Json::Value json;
@@ -872,7 +889,7 @@ DhtProxyServer::subscribe(restinio::request_handle_t request,
                     auto maxPrio = 1000u;
                     for (const auto& v : values)
                         maxPrio = std::min(maxPrio, v->priority);
-                    sendPushNotification(pushToken, std::move(json), type, !expired and maxPrio == 0);
+                    sendPushNotification(pushToken, std::move(json), type, !expired and maxPrio == 0, topic);
                     return true;
                 }
             );
@@ -928,7 +945,7 @@ DhtProxyServer::unsubscribe(restinio::request_handle_t request,
 
 void
 DhtProxyServer::handleNotifyPushListenExpire(const asio::error_code &ec, const std::string pushToken,
-                                             std::function<Json::Value()> jsonProvider, PushType type)
+                                             std::function<Json::Value()> jsonProvider, PushType type, const std::string& topic)
 {
     if (ec == asio::error::operation_aborted)
         return;
@@ -938,7 +955,7 @@ DhtProxyServer::handleNotifyPushListenExpire(const asio::error_code &ec, const s
     }
     if (logger_)
         logger_->d("[proxy:server] [subscribe] sending put refresh to %s token", pushToken.c_str());
-    sendPushNotification(pushToken, jsonProvider(), type, false);
+    sendPushNotification(pushToken, jsonProvider(), type, false, topic);
 }
 
 void
@@ -980,7 +997,7 @@ DhtProxyServer::handleCancelPushListen(const asio::error_code &ec, const std::st
 }
 
 void
-DhtProxyServer::sendPushNotification(const std::string& token, Json::Value&& json, PushType type, bool highPriority)
+DhtProxyServer::sendPushNotification(const std::string& token, Json::Value&& json, PushType type, bool highPriority, const std::string& topic)
 {
     if (pushServer_.empty())
         return;
@@ -1011,6 +1028,22 @@ DhtProxyServer::sendPushNotification(const std::string& token, Json::Value&& jso
             const auto expiration = std::chrono::system_clock::now() + std::chrono::hours(24);
             uint32_t exp = std::chrono::duration_cast<std::chrono::seconds>(expiration.time_since_epoch()).count();
             notification["expiration"] = exp;
+            if (!topic.empty())
+                notification["topic"] = topic;
+            if (type == PushType::iOS) {
+                if (highPriority) {
+                    Json::Value alert(Json::objectValue);
+                    alert["title"]="hello";
+                    notification["push_type"] = "alert";
+                    notification["alert"] = alert;
+                    notification["mutable_content"] = true;
+                } else {
+                    notification["push_type"] = "background";
+                    notification["content_available"] = true;
+                }
+            } else if (type == PushType::iOSLegacy) {
+                notification["push_type"] = "voip";
+            }
         }
 
         Json::Value notifications(Json::arrayValue);
@@ -1104,13 +1137,14 @@ DhtProxyServer::put(restinio::request_handle_t request,
                 logger_->d("[proxy:server] [put %s] %s %s", infoHash.toString().c_str(),
                           value->toString().c_str(), (permanent ? "permanent" : ""));
             if (permanent) {
-                std::string pushToken, clientId, sessionId, platform;
+                std::string pushToken, clientId, sessionId, platform, topic;
                 auto& pVal = root["permanent"];
                 if (pVal.isObject()){
                     pushToken = pVal["key"].asString();
                     clientId = pVal["client_id"].asString();
                     platform = pVal["platform"].asString();
                     sessionId = pVal["session_id"].asString();
+                    topic = pVal["topic"].asString();
                 }
                 std::lock_guard<std::mutex> lock(lockSearchPuts_);
                 auto timeout = std::chrono::steady_clock::now() + proxy::OP_TIMEOUT;
@@ -1153,7 +1187,8 @@ DhtProxyServer::put(restinio::request_handle_t request,
                         bool isAndroid = platform == "android";
                         pput.pushToken = pushToken;
                         pput.clientId = clientId;
-                        pput.type = isAndroid ? PushType::Android : PushType::iOS;
+                        pput.type = getTypeFromString(platform);
+                        pput.topic = topic;
                         pput.sessionCtx = std::make_shared<PushSessionContext>(sessionId);
                         // notify push listen expire
                         auto jsonProvider = [infoHash, clientId, vid, sessionCtx = pput.sessionCtx](){
@@ -1172,7 +1207,7 @@ DhtProxyServer::put(restinio::request_handle_t request,
                             pput.expireNotifyTimer->expires_at(timeout - proxy::OP_MARGIN);
                         pput.expireNotifyTimer->async_wait(std::bind(
                             &DhtProxyServer::handleNotifyPushListenExpire, this,
-                            std::placeholders::_1, pushToken, std::move(jsonProvider), pput.type));
+                            std::placeholders::_1, pushToken, std::move(jsonProvider), pput.type, pput.topic));
                     }
 #endif
                 } else {
diff --git a/src/dhtrunner.cpp b/src/dhtrunner.cpp
index d82532d07ed0b3e2a168e84aff11ec28076b216d..210a5499b3e459238466090f91a04e748d4a6c6c 100644
--- a/src/dhtrunner.cpp
+++ b/src/dhtrunner.cpp
@@ -1109,6 +1109,8 @@ DhtRunner::enableProxy(bool proxify)
                 config_.proxy_server, config_.push_node_id, logger_);
         if (not config_.push_token.empty())
             dht_via_proxy->setPushNotificationToken(config_.push_token);
+        if (not config_.push_topic.empty())
+            dht_via_proxy->setPushNotificationTopic(config_.push_topic);
         dht_ = std::make_unique<SecureDht>(std::move(dht_via_proxy), config_.dht_config, identityAnnouncedCb_, logger_);
         // and use it
         use_proxy = proxify;
@@ -1144,6 +1146,18 @@ DhtRunner::setPushNotificationToken(const std::string& token) {
 #endif
 }
 
+void
+DhtRunner::setPushNotificationTopic(const std::string& topic) {
+    std::lock_guard<std::mutex> lck(dht_mtx);
+#if defined(OPENDHT_PROXY_CLIENT) && defined(OPENDHT_PUSH_NOTIFICATIONS)
+    config_.push_topic = topic;
+    if (dht_)
+        dht_->setPushNotificationTopic(topic);
+#else
+    (void) topic;
+#endif
+}
+
 void
 DhtRunner::pushNotificationReceived(const std::map<std::string, std::string>& data)
 {