diff --git a/native/cpp/CommonCpp/CryptoTools/CryptoModule.h b/native/cpp/CommonCpp/CryptoTools/CryptoModule.h
--- a/native/cpp/CommonCpp/CryptoTools/CryptoModule.h
+++ b/native/cpp/CommonCpp/CryptoTools/CryptoModule.h
@@ -65,7 +65,7 @@
       const OlmBuffer &idKeys,
       const OlmBuffer &preKeys,
       const OlmBuffer &preKeySignature,
-      const OlmBuffer &oneTimeKey);
+      const std::optional<OlmBuffer> &oneTimeKey);
   bool hasSessionFor(const std::string &targetDeviceId);
   std::shared_ptr<Session> getSessionByDeviceId(const std::string &deviceId);
   void removeSessionByDeviceId(const std::string &deviceId);
diff --git a/native/cpp/CommonCpp/CryptoTools/CryptoModule.cpp b/native/cpp/CommonCpp/CryptoTools/CryptoModule.cpp
--- a/native/cpp/CommonCpp/CryptoTools/CryptoModule.cpp
+++ b/native/cpp/CommonCpp/CryptoTools/CryptoModule.cpp
@@ -288,7 +288,7 @@
     const OlmBuffer &idKeys,
     const OlmBuffer &preKeys,
     const OlmBuffer &preKeySignature,
-    const OlmBuffer &oneTimeKey) {
+    const std::optional<OlmBuffer> &oneTimeKey) {
   int newSessionVersion = 1;
   if (this->hasSessionFor(targetDeviceId)) {
     std::shared_ptr<Session> existingSession =
diff --git a/native/cpp/CommonCpp/CryptoTools/Session.h b/native/cpp/CommonCpp/CryptoTools/Session.h
--- a/native/cpp/CommonCpp/CryptoTools/Session.h
+++ b/native/cpp/CommonCpp/CryptoTools/Session.h
@@ -1,6 +1,7 @@
 #pragma once
 
 #include <memory>
+#include <optional>
 #include <string>
 
 #include "Tools.h"
@@ -21,7 +22,7 @@
       const OlmBuffer &idKeys,
       const OlmBuffer &preKeys,
       const OlmBuffer &preKeySignature,
-      const OlmBuffer &oneTimeKey);
+      const std::optional<OlmBuffer> &oneTimeKey);
   static std::unique_ptr<Session> createSessionAsResponder(
       OlmAccount *account,
       std::uint8_t *ownerIdentityKeys,
diff --git a/native/cpp/CommonCpp/CryptoTools/Session.cpp b/native/cpp/CommonCpp/CryptoTools/Session.cpp
--- a/native/cpp/CommonCpp/CryptoTools/Session.cpp
+++ b/native/cpp/CommonCpp/CryptoTools/Session.cpp
@@ -1,6 +1,7 @@
 #include "Session.h"
 #include "PlatformSpecificTools.h"
 
+#include <optional>
 #include <stdexcept>
 
 namespace comm {
@@ -16,7 +17,7 @@
     const OlmBuffer &idKeys,
     const OlmBuffer &preKeys,
     const OlmBuffer &preKeySignature,
-    const OlmBuffer &oneTimeKey) {
+    const std::optional<OlmBuffer> &oneTimeKey) {
   std::unique_ptr<Session> session(new Session());
 
   session->olmSessionBuffer.resize(::olm_session_size());
@@ -27,8 +28,31 @@
       randomBuffer,
       ::olm_create_outbound_session_random_length(session->getOlmSession()));
 
+  if (oneTimeKey) {
+    if (-1 ==
+        ::olm_create_outbound_session(
+            session->getOlmSession(),
+            account,
+            idKeys.data() + ID_KEYS_PREFIX_OFFSET,
+            KEYSIZE,
+            idKeys.data() + SIGNING_KEYS_PREFIX_OFFSET,
+            KEYSIZE,
+            preKeys.data(),
+            KEYSIZE,
+            preKeySignature.data(),
+            SIGNATURESIZE,
+            oneTimeKey->data(),
+            KEYSIZE,
+            randomBuffer.data(),
+            randomBuffer.size())) {
+      throw std::runtime_error(
+          "error createOutbound => " +
+          std::string{::olm_session_last_error(session->getOlmSession())});
+    }
+    return session;
+  }
   if (-1 ==
-      ::olm_create_outbound_session(
+      ::olm_create_outbound_session_without_otk(
           session->getOlmSession(),
           account,
           idKeys.data() + ID_KEYS_PREFIX_OFFSET,
@@ -39,8 +63,6 @@
           KEYSIZE,
           preKeySignature.data(),
           SIGNATURESIZE,
-          oneTimeKey.data(),
-          KEYSIZE,
           randomBuffer.data(),
           randomBuffer.size())) {
     throw std::runtime_error(
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
@@ -102,7 +102,7 @@
       jsi::String identityKeys,
       jsi::String prekey,
       jsi::String prekeySignature,
-      jsi::String oneTimeKeys,
+      std::optional<jsi::String> oneTimeKey,
       jsi::String keyserverID) override;
   virtual jsi::Value
   isNotificationsSessionInitialized(jsi::Runtime &rt) override;
@@ -120,7 +120,7 @@
       jsi::String identityKeys,
       jsi::String prekey,
       jsi::String prekeySignature,
-      jsi::String oneTimeKeys,
+      std::optional<jsi::String> oneTimeKey,
       jsi::String deviceID) override;
   virtual jsi::Value initializeContentInboundSession(
       jsi::Runtime &rt,
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
@@ -1082,19 +1082,30 @@
     jsi::String identityKeys,
     jsi::String prekey,
     jsi::String prekeySignature,
-    jsi::String oneTimeKey,
+    std::optional<jsi::String> oneTimeKey,
     jsi::String keyserverID) {
   auto identityKeysCpp{identityKeys.utf8(rt)};
   auto prekeyCpp{prekey.utf8(rt)};
   auto prekeySignatureCpp{prekeySignature.utf8(rt)};
-  auto oneTimeKeyCpp{oneTimeKey.utf8(rt)};
   auto keyserverIDCpp{keyserverID.utf8(rt)};
+
+  std::optional<std::string> oneTimeKeyCpp;
+  if (oneTimeKey) {
+    oneTimeKeyCpp = oneTimeKey->utf8(rt);
+  }
+
   return createPromiseAsJSIValue(
       rt, [=](jsi::Runtime &innerRt, std::shared_ptr<Promise> promise) {
         taskType job = [=, &innerRt]() {
           std::string error;
           crypto::EncryptedData result;
           try {
+            std::optional<crypto::OlmBuffer> oneTimeKeyBuffer;
+            if (oneTimeKeyCpp) {
+              oneTimeKeyBuffer = crypto::OlmBuffer(
+                  oneTimeKeyCpp->begin(), oneTimeKeyCpp->end());
+            }
+
             this->notifsCryptoModule->initializeOutboundForSendingSession(
                 keyserverIDCpp,
                 std::vector<uint8_t>(
@@ -1102,8 +1113,7 @@
                 std::vector<uint8_t>(prekeyCpp.begin(), prekeyCpp.end()),
                 std::vector<uint8_t>(
                     prekeySignatureCpp.begin(), prekeySignatureCpp.end()),
-                std::vector<uint8_t>(
-                    oneTimeKeyCpp.begin(), oneTimeKeyCpp.end()));
+                oneTimeKeyBuffer);
 
             result = this->notifsCryptoModule->encrypt(
                 keyserverIDCpp,
@@ -1293,13 +1303,18 @@
     jsi::String identityKeys,
     jsi::String prekey,
     jsi::String prekeySignature,
-    jsi::String oneTimeKey,
+    std::optional<jsi::String> oneTimeKey,
     jsi::String deviceID) {
   auto identityKeysCpp{identityKeys.utf8(rt)};
   auto prekeyCpp{prekey.utf8(rt)};
   auto prekeySignatureCpp{prekeySignature.utf8(rt)};
-  auto oneTimeKeyCpp{oneTimeKey.utf8(rt)};
   auto deviceIDCpp{deviceID.utf8(rt)};
+
+  std::optional<std::string> oneTimeKeyCpp;
+  if (oneTimeKey) {
+    oneTimeKeyCpp = oneTimeKey->utf8(rt);
+  }
+
   return createPromiseAsJSIValue(
       rt, [=](jsi::Runtime &innerRt, std::shared_ptr<Promise> promise) {
         taskType job = [=, &innerRt]() {
@@ -1307,6 +1322,11 @@
           crypto::EncryptedData initialEncryptedData;
           int sessionVersion;
           try {
+            std::optional<crypto::OlmBuffer> oneTimeKeyBuffer;
+            if (oneTimeKeyCpp) {
+              oneTimeKeyBuffer = crypto::OlmBuffer(
+                  oneTimeKeyCpp->begin(), oneTimeKeyCpp->end());
+            }
             sessionVersion =
                 this->contentCryptoModule->initializeOutboundForSendingSession(
                     deviceIDCpp,
@@ -1315,8 +1335,7 @@
                     std::vector<uint8_t>(prekeyCpp.begin(), prekeyCpp.end()),
                     std::vector<uint8_t>(
                         prekeySignatureCpp.begin(), prekeySignatureCpp.end()),
-                    std::vector<uint8_t>(
-                        oneTimeKeyCpp.begin(), oneTimeKeyCpp.end()));
+                    oneTimeKeyBuffer);
 
             const std::string initMessage = "{\"type\": \"init\"}";
             initialEncryptedData =
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
@@ -64,7 +64,7 @@
   return static_cast<CommCoreModuleSchemaCxxSpecJSI *>(&turboModule)->validateAndUploadPrekeys(rt, args[0].asString(rt), args[1].asString(rt), args[2].asString(rt));
 }
 static jsi::Value __hostFunction_CommCoreModuleSchemaCxxSpecJSI_initializeNotificationsSession(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
-  return static_cast<CommCoreModuleSchemaCxxSpecJSI *>(&turboModule)->initializeNotificationsSession(rt, args[0].asString(rt), args[1].asString(rt), args[2].asString(rt), args[3].asString(rt), args[4].asString(rt));
+  return static_cast<CommCoreModuleSchemaCxxSpecJSI *>(&turboModule)->initializeNotificationsSession(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));
 }
 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);
@@ -79,7 +79,7 @@
   return static_cast<CommCoreModuleSchemaCxxSpecJSI *>(&turboModule)->getKeyserverDataFromNotifStorage(rt, args[0].asObject(rt).asArray(rt));
 }
 static jsi::Value __hostFunction_CommCoreModuleSchemaCxxSpecJSI_initializeContentOutboundSession(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
-  return static_cast<CommCoreModuleSchemaCxxSpecJSI *>(&turboModule)->initializeContentOutboundSession(rt, args[0].asString(rt), args[1].asString(rt), args[2].asString(rt), args[3].asString(rt), args[4].asString(rt));
+  return static_cast<CommCoreModuleSchemaCxxSpecJSI *>(&turboModule)->initializeContentOutboundSession(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));
 }
 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());
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
@@ -36,12 +36,12 @@
   virtual jsi::Value getOneTimeKeys(jsi::Runtime &rt, double oneTimeKeysAmount) = 0;
   virtual jsi::Value validateAndGetPrekeys(jsi::Runtime &rt) = 0;
   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, jsi::String oneTimeKey, jsi::String keyserverID) = 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 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, jsi::String oneTimeKey, jsi::String deviceID) = 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 encrypt(jsi::Runtime &rt, jsi::String message, jsi::String deviceID) = 0;
   virtual jsi::Value encryptAndPersist(jsi::Runtime &rt, jsi::String message, jsi::String deviceID, jsi::String messageID) = 0;
@@ -230,7 +230,7 @@
       return bridging::callFromJs<jsi::Value>(
           rt, &T::validateAndUploadPrekeys, jsInvoker_, instance_, std::move(authUserID), std::move(authDeviceID), std::move(authAccessToken));
     }
-    jsi::Value initializeNotificationsSession(jsi::Runtime &rt, jsi::String identityKeys, jsi::String prekey, jsi::String prekeySignature, jsi::String oneTimeKey, jsi::String keyserverID) override {
+    jsi::Value initializeNotificationsSession(jsi::Runtime &rt, jsi::String identityKeys, jsi::String prekey, jsi::String prekeySignature, std::optional<jsi::String> oneTimeKey, jsi::String keyserverID) override {
       static_assert(
           bridging::getParameterCount(&T::initializeNotificationsSession) == 6,
           "Expected initializeNotificationsSession(...) to have 6 parameters");
@@ -270,7 +270,7 @@
       return bridging::callFromJs<jsi::Value>(
           rt, &T::getKeyserverDataFromNotifStorage, jsInvoker_, instance_, std::move(keyserverIDs));
     }
-    jsi::Value initializeContentOutboundSession(jsi::Runtime &rt, jsi::String identityKeys, jsi::String prekey, jsi::String prekeySignature, jsi::String oneTimeKey, jsi::String deviceID) override {
+    jsi::Value initializeContentOutboundSession(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::initializeContentOutboundSession) == 6,
           "Expected initializeContentOutboundSession(...) to have 6 parameters");
diff --git a/native/schema/CommCoreModuleSchema.js b/native/schema/CommCoreModuleSchema.js
--- a/native/schema/CommCoreModuleSchema.js
+++ b/native/schema/CommCoreModuleSchema.js
@@ -64,7 +64,7 @@
     identityKeys: string,
     prekey: string,
     prekeySignature: string,
-    oneTimeKey: string,
+    oneTimeKey: ?string,
     keyserverID: string,
   ) => Promise<string>;
   +isNotificationsSessionInitialized: () => Promise<boolean>;
@@ -81,7 +81,7 @@
     identityKeys: string,
     prekey: string,
     prekeySignature: string,
-    oneTimeKey: string,
+    oneTimeKey: ?string,
     deviceID: string,
   ) => Promise<OutboundSessionCreationResult>;
   +initializeContentInboundSession: (