diff --git a/lib/types/crypto-types.js b/lib/types/crypto-types.js
--- a/lib/types/crypto-types.js
+++ b/lib/types/crypto-types.js
@@ -171,6 +171,7 @@
     contentIdentityKeys: OLMIdentityKeys,
     contentInitializationInfo: OlmSessionInitializationInfo,
   ) => Promise<OutboundSessionCreationResult>,
+  +isContentSessionInitialized: (deviceID: string) => Promise<boolean>,
   +keyserverNotificationsSessionCreator: (
     cookie: ?string,
     notificationsIdentityKeys: OLMIdentityKeys,
@@ -182,6 +183,12 @@
     notificationsIdentityKeys: OLMIdentityKeys,
     notificationsInitializationInfo: OlmSessionInitializationInfo,
   ) => Promise<EncryptedData>,
+  +isDeviceNotificationsSessionInitialized: (
+    deviceID: string,
+  ) => Promise<boolean>,
+  +isNotificationsSessionInitializedWithDevices: (
+    deviceIDs: $ReadOnlyArray<string>,
+  ) => Promise<{ +[deviceID: string]: boolean }>,
   +reassignNotificationsSession?: (
     prevCookie: ?string,
     newCookie: ?string,
diff --git a/lib/utils/__mocks__/config.js b/lib/utils/__mocks__/config.js
--- a/lib/utils/__mocks__/config.js
+++ b/lib/utils/__mocks__/config.js
@@ -24,6 +24,9 @@
     contentOutboundSessionCreator: jest.fn(),
     keyserverNotificationsSessionCreator: jest.fn(),
     notificationsOutboundSessionCreator: jest.fn(),
+    isContentSessionInitialized: jest.fn(),
+    isDeviceNotificationsSessionInitialized: jest.fn(),
+    isNotificationsSessionInitializedWithDevices: jest.fn(),
     getOneTimeKeys: jest.fn(),
     validateAndUploadPrekeys: jest.fn(),
     signMessage: jest.fn(),
diff --git a/native/cpp/CommonCpp/NativeModules/CommCoreModule.h b/native/cpp/CommonCpp/NativeModules/CommCoreModule.h
--- a/native/cpp/CommonCpp/NativeModules/CommCoreModule.h
+++ b/native/cpp/CommonCpp/NativeModules/CommCoreModule.h
@@ -110,6 +110,12 @@
       jsi::String keyserverID) override;
   virtual jsi::Value
   isNotificationsSessionInitialized(jsi::Runtime &rt) override;
+  virtual jsi::Value isDeviceNotificationsSessionInitialized(
+      jsi::Runtime &rt,
+      jsi::String deviceID) override;
+  virtual jsi::Value isNotificationsSessionInitializedWithDevices(
+      jsi::Runtime &rt,
+      jsi::Array deviceIDs) override;
   virtual jsi::Value updateKeyserverDataInNotifStorage(
       jsi::Runtime &rt,
       jsi::Array keyserversData) override;
@@ -133,6 +139,8 @@
       jsi::String deviceID,
       double sessionVersion,
       bool overwrite) override;
+  virtual jsi::Value
+  isContentSessionInitialized(jsi::Runtime &rt, jsi::String deviceID) override;
   virtual jsi::Value initializeNotificationsOutboundSession(
       jsi::Runtime &rt,
       jsi::String identityKeys,
diff --git a/native/cpp/CommonCpp/NativeModules/CommCoreModule.cpp b/native/cpp/CommonCpp/NativeModules/CommCoreModule.cpp
--- a/native/cpp/CommonCpp/NativeModules/CommCoreModule.cpp
+++ b/native/cpp/CommonCpp/NativeModules/CommCoreModule.cpp
@@ -1207,6 +1207,96 @@
       });
 }
 
+jsi::Value CommCoreModule::isDeviceNotificationsSessionInitialized(
+    jsi::Runtime &rt,
+    jsi::String deviceID) {
+  auto deviceIDCpp{deviceID.utf8(rt)};
+  return createPromiseAsJSIValue(
+      rt, [=](jsi::Runtime &innerRt, std::shared_ptr<Promise> promise) {
+        taskType job = [=, &innerRt]() {
+          if (this->contentCryptoModule == nullptr ||
+              this->notifsCryptoModule == nullptr) {
+            this->jsInvoker_->invokeAsync([=, &innerRt]() {
+              promise->reject("user has not been initialized");
+            });
+            return;
+          }
+
+          std::string error;
+          bool result;
+          try {
+            result = NotificationsCryptoModule::
+                isDeviceNotificationsSessionInitialized(deviceIDCpp);
+          } catch (const std::exception &e) {
+            error = e.what();
+          }
+
+          this->jsInvoker_->invokeAsync([=, &innerRt]() {
+            if (error.size()) {
+              promise->reject(error);
+              return;
+            }
+            promise->resolve(result);
+          });
+        };
+        this->cryptoThread->scheduleTask(job);
+      });
+}
+
+jsi::Value CommCoreModule::isNotificationsSessionInitializedWithDevices(
+    jsi::Runtime &rt,
+    jsi::Array deviceIDs) {
+  std::vector<std::string> deviceIDsCpp;
+  for (auto idx = 0; idx < deviceIDs.size(rt); idx++) {
+    std::string deviceIDCpp =
+        deviceIDs.getValueAtIndex(rt, idx).asString(rt).utf8(rt);
+    deviceIDsCpp.push_back(deviceIDCpp);
+  }
+
+  return createPromiseAsJSIValue(
+      rt, [=](jsi::Runtime &innerRt, std::shared_ptr<Promise> promise) {
+        taskType job = [=, &innerRt]() {
+          if (this->contentCryptoModule == nullptr ||
+              this->notifsCryptoModule == nullptr) {
+            this->jsInvoker_->invokeAsync([=, &innerRt]() {
+              promise->reject("user has not been initialized");
+            });
+            return;
+          }
+
+          std::string error;
+          std::vector<std::pair<std::string, bool>> result;
+
+          try {
+            result = NotificationsCryptoModule::
+                isNotificationsSessionInitializedWithDevices(deviceIDsCpp);
+          } catch (const std::exception &e) {
+            error = e.what();
+          }
+
+          auto resultPtr =
+              std::make_shared<std::vector<std::pair<std::string, bool>>>(
+                  std::move(result));
+
+          this->jsInvoker_->invokeAsync(
+              [&innerRt, resultPtr, error, promise]() {
+                if (error.size()) {
+                  promise->reject(error);
+                  return;
+                }
+
+                jsi::Object jsiResult = jsi::Object(innerRt);
+                for (const auto &deviceResult : *resultPtr) {
+                  jsiResult.setProperty(
+                      innerRt, deviceResult.first.c_str(), deviceResult.second);
+                }
+                promise->resolve(std::move(jsiResult));
+              });
+        };
+        this->cryptoThread->scheduleTask(job);
+      });
+}
+
 jsi::Value CommCoreModule::updateKeyserverDataInNotifStorage(
     jsi::Runtime &rt,
     jsi::Array keyserversData) {
@@ -1453,6 +1543,42 @@
       });
 }
 
+jsi::Value CommCoreModule::isContentSessionInitialized(
+    jsi::Runtime &rt,
+    jsi::String deviceID) {
+  auto deviceIDCpp{deviceID.utf8(rt)};
+  return createPromiseAsJSIValue(
+      rt, [=](jsi::Runtime &innerRt, std::shared_ptr<Promise> promise) {
+        taskType job = [=, &innerRt]() {
+          std::string error;
+          bool result;
+
+          if (this->contentCryptoModule == nullptr ||
+              this->notifsCryptoModule == nullptr) {
+            this->jsInvoker_->invokeAsync([=, &innerRt]() {
+              promise->reject("user has not been initialized");
+            });
+            return;
+          }
+
+          try {
+            result = this->contentCryptoModule->hasSessionFor(deviceIDCpp);
+          } catch (const std::exception &e) {
+            error = e.what();
+          }
+
+          this->jsInvoker_->invokeAsync([=, &innerRt]() {
+            if (error.size()) {
+              promise->reject(error);
+              return;
+            }
+            promise->resolve(result);
+          });
+        };
+        this->cryptoThread->scheduleTask(job);
+      });
+}
+
 jsi::Value CommCoreModule::initializeNotificationsOutboundSession(
     jsi::Runtime &rt,
     jsi::String identityKeys,
diff --git a/native/cpp/CommonCpp/Notifications/BackgroundDataStorage/NotificationsCryptoModule.h b/native/cpp/CommonCpp/Notifications/BackgroundDataStorage/NotificationsCryptoModule.h
--- a/native/cpp/CommonCpp/Notifications/BackgroundDataStorage/NotificationsCryptoModule.h
+++ b/native/cpp/CommonCpp/Notifications/BackgroundDataStorage/NotificationsCryptoModule.h
@@ -54,6 +54,9 @@
   static bool isNotificationsSessionInitialized(const std::string &keyserverID);
   static bool
   isDeviceNotificationsSessionInitialized(const std::string &deviceID);
+  static std::vector<std::pair<std::string, bool>>
+  isNotificationsSessionInitializedWithDevices(
+      const std::vector<std::string> &deviceIDs);
 
   class BaseStatefulDecryptResult {
     BaseStatefulDecryptResult(
diff --git a/native/cpp/CommonCpp/Notifications/BackgroundDataStorage/NotificationsCryptoModule.cpp b/native/cpp/CommonCpp/Notifications/BackgroundDataStorage/NotificationsCryptoModule.cpp
--- a/native/cpp/CommonCpp/Notifications/BackgroundDataStorage/NotificationsCryptoModule.cpp
+++ b/native/cpp/CommonCpp/Notifications/BackgroundDataStorage/NotificationsCryptoModule.cpp
@@ -6,6 +6,7 @@
 #include "../../Tools/Logger.h"
 #include "../../Tools/PlatformSpecificTools.h"
 
+#include "Logger.h"
 #include <fcntl.h>
 #include <folly/String.h>
 #include <folly/dynamic.h>
@@ -14,6 +15,7 @@
 #include <fstream>
 #include <memory>
 #include <sstream>
+#include <unordered_set>
 
 namespace comm {
 const std::string
@@ -296,6 +298,26 @@
   return CommMMKV::getString(peerNotificationsSessionKey).has_value();
 }
 
+std::vector<std::pair<std::string, bool>>
+NotificationsCryptoModule::isNotificationsSessionInitializedWithDevices(
+    const std::vector<std::string> &deviceIDs) {
+  std::vector<std::string> allKeys = CommMMKV::getAllKeys();
+  std::unordered_set<std::string> allKeysSet(allKeys.begin(), allKeys.end());
+  std::vector<std::pair<std::string, bool>> result;
+
+  for (const auto &deviceID : deviceIDs) {
+    std::string mmkvDeviceIDKey =
+        NotificationsCryptoModule::getDeviceNotificationsSessionKey(deviceID);
+    if (allKeysSet.find(mmkvDeviceIDKey) == allKeysSet.end()) {
+      result.push_back({deviceID, false});
+    } else {
+      result.push_back({deviceID, true});
+    }
+  }
+
+  return result;
+}
+
 NotificationsCryptoModule::BaseStatefulDecryptResult::BaseStatefulDecryptResult(
     std::string picklingKey,
     std::string decryptedData)
diff --git a/native/cpp/CommonCpp/_generated/commJSI-generated.cpp b/native/cpp/CommonCpp/_generated/commJSI-generated.cpp
--- a/native/cpp/CommonCpp/_generated/commJSI-generated.cpp
+++ b/native/cpp/CommonCpp/_generated/commJSI-generated.cpp
@@ -69,6 +69,12 @@
 static jsi::Value __hostFunction_CommCoreModuleSchemaCxxSpecJSI_isNotificationsSessionInitialized(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
   return static_cast<CommCoreModuleSchemaCxxSpecJSI *>(&turboModule)->isNotificationsSessionInitialized(rt);
 }
+static jsi::Value __hostFunction_CommCoreModuleSchemaCxxSpecJSI_isDeviceNotificationsSessionInitialized(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
+  return static_cast<CommCoreModuleSchemaCxxSpecJSI *>(&turboModule)->isDeviceNotificationsSessionInitialized(rt, args[0].asString(rt));
+}
+static jsi::Value __hostFunction_CommCoreModuleSchemaCxxSpecJSI_isNotificationsSessionInitializedWithDevices(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
+  return static_cast<CommCoreModuleSchemaCxxSpecJSI *>(&turboModule)->isNotificationsSessionInitializedWithDevices(rt, args[0].asObject(rt).asArray(rt));
+}
 static jsi::Value __hostFunction_CommCoreModuleSchemaCxxSpecJSI_updateKeyserverDataInNotifStorage(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
   return static_cast<CommCoreModuleSchemaCxxSpecJSI *>(&turboModule)->updateKeyserverDataInNotifStorage(rt, args[0].asObject(rt).asArray(rt));
 }
@@ -84,6 +90,9 @@
 static jsi::Value __hostFunction_CommCoreModuleSchemaCxxSpecJSI_initializeContentInboundSession(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
   return static_cast<CommCoreModuleSchemaCxxSpecJSI *>(&turboModule)->initializeContentInboundSession(rt, args[0].asString(rt), args[1].asObject(rt), args[2].asString(rt), args[3].asNumber(), args[4].asBool());
 }
+static jsi::Value __hostFunction_CommCoreModuleSchemaCxxSpecJSI_isContentSessionInitialized(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
+  return static_cast<CommCoreModuleSchemaCxxSpecJSI *>(&turboModule)->isContentSessionInitialized(rt, args[0].asString(rt));
+}
 static jsi::Value __hostFunction_CommCoreModuleSchemaCxxSpecJSI_initializeNotificationsOutboundSession(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
   return static_cast<CommCoreModuleSchemaCxxSpecJSI *>(&turboModule)->initializeNotificationsOutboundSession(rt, args[0].asString(rt), args[1].asString(rt), args[2].asString(rt), args[3].isNull() || args[3].isUndefined() ? std::nullopt : std::make_optional(args[3].asString(rt)), args[4].asString(rt));
 }
@@ -244,11 +253,14 @@
   methodMap_["validateAndUploadPrekeys"] = MethodMetadata {3, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_validateAndUploadPrekeys};
   methodMap_["initializeNotificationsSession"] = MethodMetadata {5, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_initializeNotificationsSession};
   methodMap_["isNotificationsSessionInitialized"] = MethodMetadata {0, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_isNotificationsSessionInitialized};
+  methodMap_["isDeviceNotificationsSessionInitialized"] = MethodMetadata {1, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_isDeviceNotificationsSessionInitialized};
+  methodMap_["isNotificationsSessionInitializedWithDevices"] = MethodMetadata {1, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_isNotificationsSessionInitializedWithDevices};
   methodMap_["updateKeyserverDataInNotifStorage"] = MethodMetadata {1, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_updateKeyserverDataInNotifStorage};
   methodMap_["removeKeyserverDataFromNotifStorage"] = MethodMetadata {1, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_removeKeyserverDataFromNotifStorage};
   methodMap_["getKeyserverDataFromNotifStorage"] = MethodMetadata {1, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_getKeyserverDataFromNotifStorage};
   methodMap_["initializeContentOutboundSession"] = MethodMetadata {5, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_initializeContentOutboundSession};
   methodMap_["initializeContentInboundSession"] = MethodMetadata {5, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_initializeContentInboundSession};
+  methodMap_["isContentSessionInitialized"] = MethodMetadata {1, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_isContentSessionInitialized};
   methodMap_["initializeNotificationsOutboundSession"] = MethodMetadata {5, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_initializeNotificationsOutboundSession};
   methodMap_["encrypt"] = MethodMetadata {2, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_encrypt};
   methodMap_["encryptNotification"] = MethodMetadata {2, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_encryptNotification};
diff --git a/native/cpp/CommonCpp/_generated/commJSI.h b/native/cpp/CommonCpp/_generated/commJSI.h
--- a/native/cpp/CommonCpp/_generated/commJSI.h
+++ b/native/cpp/CommonCpp/_generated/commJSI.h
@@ -38,11 +38,14 @@
   virtual jsi::Value validateAndUploadPrekeys(jsi::Runtime &rt, jsi::String authUserID, jsi::String authDeviceID, jsi::String authAccessToken) = 0;
   virtual jsi::Value initializeNotificationsSession(jsi::Runtime &rt, jsi::String identityKeys, jsi::String prekey, jsi::String prekeySignature, std::optional<jsi::String> oneTimeKey, jsi::String keyserverID) = 0;
   virtual jsi::Value isNotificationsSessionInitialized(jsi::Runtime &rt) = 0;
+  virtual jsi::Value isDeviceNotificationsSessionInitialized(jsi::Runtime &rt, jsi::String deviceID) = 0;
+  virtual jsi::Value isNotificationsSessionInitializedWithDevices(jsi::Runtime &rt, jsi::Array deviceIDs) = 0;
   virtual jsi::Value updateKeyserverDataInNotifStorage(jsi::Runtime &rt, jsi::Array keyserversData) = 0;
   virtual jsi::Value removeKeyserverDataFromNotifStorage(jsi::Runtime &rt, jsi::Array keyserverIDsToDelete) = 0;
   virtual jsi::Value getKeyserverDataFromNotifStorage(jsi::Runtime &rt, jsi::Array keyserverIDs) = 0;
   virtual jsi::Value initializeContentOutboundSession(jsi::Runtime &rt, jsi::String identityKeys, jsi::String prekey, jsi::String prekeySignature, std::optional<jsi::String> oneTimeKey, jsi::String deviceID) = 0;
   virtual jsi::Value initializeContentInboundSession(jsi::Runtime &rt, jsi::String identityKeys, jsi::Object encryptedContent, jsi::String deviceID, double sessionVersion, bool overwrite) = 0;
+  virtual jsi::Value isContentSessionInitialized(jsi::Runtime &rt, jsi::String deviceID) = 0;
   virtual jsi::Value initializeNotificationsOutboundSession(jsi::Runtime &rt, jsi::String identityKeys, jsi::String prekey, jsi::String prekeySignature, std::optional<jsi::String> oneTimeKey, jsi::String deviceID) = 0;
   virtual jsi::Value encrypt(jsi::Runtime &rt, jsi::String message, jsi::String deviceID) = 0;
   virtual jsi::Value encryptNotification(jsi::Runtime &rt, jsi::String payload, jsi::String deviceID) = 0;
@@ -253,6 +256,22 @@
       return bridging::callFromJs<jsi::Value>(
           rt, &T::isNotificationsSessionInitialized, jsInvoker_, instance_);
     }
+    jsi::Value isDeviceNotificationsSessionInitialized(jsi::Runtime &rt, jsi::String deviceID) override {
+      static_assert(
+          bridging::getParameterCount(&T::isDeviceNotificationsSessionInitialized) == 2,
+          "Expected isDeviceNotificationsSessionInitialized(...) to have 2 parameters");
+
+      return bridging::callFromJs<jsi::Value>(
+          rt, &T::isDeviceNotificationsSessionInitialized, jsInvoker_, instance_, std::move(deviceID));
+    }
+    jsi::Value isNotificationsSessionInitializedWithDevices(jsi::Runtime &rt, jsi::Array deviceIDs) override {
+      static_assert(
+          bridging::getParameterCount(&T::isNotificationsSessionInitializedWithDevices) == 2,
+          "Expected isNotificationsSessionInitializedWithDevices(...) to have 2 parameters");
+
+      return bridging::callFromJs<jsi::Value>(
+          rt, &T::isNotificationsSessionInitializedWithDevices, jsInvoker_, instance_, std::move(deviceIDs));
+    }
     jsi::Value updateKeyserverDataInNotifStorage(jsi::Runtime &rt, jsi::Array keyserversData) override {
       static_assert(
           bridging::getParameterCount(&T::updateKeyserverDataInNotifStorage) == 2,
@@ -293,6 +312,14 @@
       return bridging::callFromJs<jsi::Value>(
           rt, &T::initializeContentInboundSession, jsInvoker_, instance_, std::move(identityKeys), std::move(encryptedContent), std::move(deviceID), std::move(sessionVersion), std::move(overwrite));
     }
+    jsi::Value isContentSessionInitialized(jsi::Runtime &rt, jsi::String deviceID) override {
+      static_assert(
+          bridging::getParameterCount(&T::isContentSessionInitialized) == 2,
+          "Expected isContentSessionInitialized(...) to have 2 parameters");
+
+      return bridging::callFromJs<jsi::Value>(
+          rt, &T::isContentSessionInitialized, jsInvoker_, instance_, std::move(deviceID));
+    }
     jsi::Value initializeNotificationsOutboundSession(jsi::Runtime &rt, jsi::String identityKeys, jsi::String prekey, jsi::String prekeySignature, std::optional<jsi::String> oneTimeKey, jsi::String deviceID) override {
       static_assert(
           bridging::getParameterCount(&T::initializeNotificationsOutboundSession) == 6,
diff --git a/native/crypto/olm-api.js b/native/crypto/olm-api.js
--- a/native/crypto/olm-api.js
+++ b/native/crypto/olm-api.js
@@ -42,6 +42,7 @@
       overwrite,
     );
   },
+  isContentSessionInitialized: commCoreModule.isContentSessionInitialized,
   async contentOutboundSessionCreator(
     contentIdentityKeys: OLMIdentityKeys,
     contentInitializationInfo: OlmSessionInitializationInfo,
@@ -95,6 +96,10 @@
       deviceID,
     );
   },
+  isDeviceNotificationsSessionInitialized:
+    commCoreModule.isDeviceNotificationsSessionInitialized,
+  isNotificationsSessionInitializedWithDevices:
+    commCoreModule.isNotificationsSessionInitializedWithDevices,
   async getOneTimeKeys(numberOfKeys: number): Promise<OneTimeKeysResultValues> {
     const { contentOneTimeKeys, notificationsOneTimeKeys } =
       await commCoreModule.getOneTimeKeys(numberOfKeys);
diff --git a/native/schema/CommCoreModuleSchema.js b/native/schema/CommCoreModuleSchema.js
--- a/native/schema/CommCoreModuleSchema.js
+++ b/native/schema/CommCoreModuleSchema.js
@@ -68,6 +68,12 @@
     keyserverID: string,
   ) => Promise<string>;
   +isNotificationsSessionInitialized: () => Promise<boolean>;
+  +isDeviceNotificationsSessionInitialized: (
+    deviceID: string,
+  ) => Promise<boolean>;
+  +isNotificationsSessionInitializedWithDevices: (
+    deviceIDs: $ReadOnlyArray<string>,
+  ) => Promise<{ +[deviceID: string]: boolean }>;
   +updateKeyserverDataInNotifStorage: (
     keyserversData: $ReadOnlyArray<{ +id: string, +unreadCount: number }>,
   ) => Promise<void>;
@@ -91,6 +97,7 @@
     sessionVersion: number,
     overwrite: boolean,
   ) => Promise<string>;
+  +isContentSessionInitialized: (deviceID: string) => Promise<boolean>;
   +initializeNotificationsOutboundSession: (
     identityKeys: string,
     prekey: string,
diff --git a/web/crypto/olm-api.js b/web/crypto/olm-api.js
--- a/web/crypto/olm-api.js
+++ b/web/crypto/olm-api.js
@@ -51,6 +51,13 @@
   decryptAndPersist: proxyToWorker('decryptAndPersist'),
   contentInboundSessionCreator: proxyToWorker('contentInboundSessionCreator'),
   contentOutboundSessionCreator: proxyToWorker('contentOutboundSessionCreator'),
+  isContentSessionInitialized: proxyToWorker('isContentSessionInitialized'),
+  isDeviceNotificationsSessionInitialized: proxyToWorker(
+    'isDeviceNotificationsSessionInitialized',
+  ),
+  isNotificationsSessionInitializedWithDevices: proxyToWorker(
+    'isNotificationsSessionInitializedWithDevices',
+  ),
   keyserverNotificationsSessionCreator: proxyToWorker(
     'keyserverNotificationsSessionCreator',
   ),
diff --git a/web/shared-worker/worker/worker-crypto.js b/web/shared-worker/worker/worker-crypto.js
--- a/web/shared-worker/worker/worker-crypto.js
+++ b/web/shared-worker/worker/worker-crypto.js
@@ -731,6 +731,12 @@
 
     return { encryptedData, sessionVersion: newSessionVersion };
   },
+  async isContentSessionInitialized(deviceID: string) {
+    if (!cryptoStore) {
+      throw new Error('Crypto account not initialized');
+    }
+    return !!cryptoStore.contentSessions[deviceID];
+  },
   async notificationsOutboundSessionCreator(
     deviceID: string,
     notificationsIdentityKeys: OLMIdentityKeys,
@@ -739,6 +745,7 @@
     const dataPersistenceKey = getOlmDataKeyForDeviceID(deviceID);
     const dataEncryptionKeyDBLabel =
       getOlmEncryptionKeyDBLabelForDeviceID(deviceID);
+
     return createAndPersistNotificationsOutboundSession(
       notificationsIdentityKeys,
       notificationsInitializationInfo,
@@ -746,6 +753,37 @@
       dataEncryptionKeyDBLabel,
     );
   },
+  async isDeviceNotificationsSessionInitialized(deviceID: string) {
+    const dataPersistenceKey = getOlmDataKeyForDeviceID(deviceID);
+    const dataEncryptionKeyDBLabel =
+      getOlmEncryptionKeyDBLabelForDeviceID(deviceID);
+
+    const allKeys = await localforage.keys();
+    const allKeysSet = new Set(allKeys);
+    return (
+      allKeysSet.has(dataPersistenceKey) &&
+      allKeysSet.has(dataEncryptionKeyDBLabel)
+    );
+  },
+  async isNotificationsSessionInitializedWithDevices(
+    deviceIDs: $ReadOnlyArray<string>,
+  ) {
+    const allKeys = await localforage.keys();
+    const allKeysSet = new Set(allKeys);
+
+    const deviceInfoPairs = deviceIDs.map(deviceID => {
+      const dataPersistenceKey = getOlmDataKeyForDeviceID(deviceID);
+      const dataEncryptionKeyDBLabel =
+        getOlmEncryptionKeyDBLabelForDeviceID(deviceID);
+      return [
+        deviceID,
+        allKeysSet.has(dataPersistenceKey) &&
+          allKeysSet.has(dataEncryptionKeyDBLabel),
+      ];
+    });
+
+    return Object.fromEntries(deviceInfoPairs);
+  },
   async keyserverNotificationsSessionCreator(
     cookie: ?string,
     notificationsIdentityKeys: OLMIdentityKeys,