diff --git a/native/native_rust_library/src/backup/upload_handler.rs b/native/native_rust_library/src/backup/upload_handler.rs
--- a/native/native_rust_library/src/backup/upload_handler.rs
+++ b/native/native_rust_library/src/backup/upload_handler.rs
@@ -196,10 +196,17 @@
     backup_id: String,
   ) -> Result<(), BackupHandlerError> {
     let user_data_path = get_backup_file_path(&backup_id, false)?;
-    let user_data = tokio::fs::read(&user_data_path).await?;
-
+    let user_data = match tokio::fs::read(&user_data_path).await {
+      Ok(data) => Some(data),
+      Err(err) if err.kind() == ErrorKind::NotFound => None,
+      Err(err) => return Err(err.into()),
+    };
     let user_keys_path = get_backup_user_keys_file_path(&backup_id)?;
-    let user_keys = tokio::fs::read(&user_keys_path).await?;
+    let user_keys = match tokio::fs::read(&user_keys_path).await {
+      Ok(data) => Some(data),
+      Err(err) if err.kind() == ErrorKind::NotFound => None,
+      Err(err) => return Err(err.into()),
+    };
 
     let attachments_path = get_backup_file_path(&backup_id, true)?;
     let attachments = match tokio::fs::read(&attachments_path).await {
diff --git a/services/commtest/src/backup/backup_utils.rs b/services/commtest/src/backup/backup_utils.rs
--- a/services/commtest/src/backup/backup_utils.rs
+++ b/services/commtest/src/backup/backup_utils.rs
@@ -11,14 +11,14 @@
 pub fn generate_backup_data(predefined_byte_value: u8) -> BackupData {
   BackupData {
     backup_id: Uuid::new_v4().to_string(),
-    user_keys: generate_stable_nbytes(
+    user_keys: Some(generate_stable_nbytes(
       ByteSize::kib(4).as_u64() as usize,
       Some(predefined_byte_value),
-    ),
-    user_data: generate_stable_nbytes(
+    )),
+    user_data: Some(generate_stable_nbytes(
       ByteSize::mib(4).as_u64() as usize,
       Some(predefined_byte_value),
-    ),
+    )),
     attachments: vec![],
     siwe_backup_msg: None,
   }
diff --git a/services/commtest/tests/backup_integration_test.rs b/services/commtest/tests/backup_integration_test.rs
--- a/services/commtest/tests/backup_integration_test.rs
+++ b/services/commtest/tests/backup_integration_test.rs
@@ -57,12 +57,12 @@
   let user_keys = backup_client
     .download_backup_data(&second_backup_descriptor, RequestedData::UserKeys)
     .await?;
-  assert_eq!(user_keys, backup_data.user_keys);
+  assert_eq!(Some(user_keys), backup_data.user_keys);
 
   let user_data = backup_client
     .download_backup_data(&second_backup_descriptor, RequestedData::UserData)
     .await?;
-  assert_eq!(user_data, backup_data.user_data);
+  assert_eq!(Some(user_data), backup_data.user_data);
 
   // Test latest backup lookup for nonexistent user
   let latest_backup_descriptor = BackupDescriptor::Latest {
@@ -91,7 +91,7 @@
   let user_keys = backup_client
     .download_backup_data(&latest_backup_descriptor, RequestedData::UserKeys)
     .await?;
-  assert_eq!(user_keys, backup_data.user_keys);
+  assert_eq!(Some(user_keys), backup_data.user_keys);
 
   // Test log download
   let log_stream = backup_client
diff --git a/services/commtest/tests/backup_performance_test.rs b/services/commtest/tests/backup_performance_test.rs
--- a/services/commtest/tests/backup_performance_test.rs
+++ b/services/commtest/tests/backup_performance_test.rs
@@ -124,7 +124,7 @@
         .find(|data| data.backup_id == *backup_id)
         .expect("Request should return existing backup data");
 
-      assert_eq!(backup.user_keys, user_keys);
+      assert_eq!(backup.user_keys, Some(user_keys));
     }
 
     let mut latest_user_data_for_user = vec![];
@@ -159,7 +159,7 @@
         .find(|data| data.backup_id == *backup_id)
         .expect("Request should return existing backup data");
 
-      assert_eq!(backup.user_data, user_data);
+      assert_eq!(backup.user_data, Some(user_data));
     }
   })
   .await
diff --git a/shared/backup_client/src/lib.rs b/shared/backup_client/src/lib.rs
--- a/shared/backup_client/src/lib.rs
+++ b/shared/backup_client/src/lib.rs
@@ -56,27 +56,42 @@
       siwe_backup_msg,
     } = backup_data;
 
+    let endpoint = match (user_data.clone(), user_keys.clone()) {
+      (None, None) => return Err(Error::InvalidRequest),
+      (Some(_), Some(_)) => "backups",
+      (Some(_), None) => "backups/user_data",
+      (None, Some(_)) => "backups/user_keys",
+    };
+
     let client = reqwest::Client::new();
-    let mut form = Form::new()
-      .text("backup_id", backup_id)
-      .text(
-        "user_keys_hash",
-        Sha256::digest(&user_keys).encode_hex::<String>(),
-      )
-      .part("user_keys", Part::stream(Body::from(user_keys)))
-      .text(
-        "user_data_hash",
-        Sha256::digest(&user_data).encode_hex::<String>(),
-      )
-      .part("user_data", Part::stream(Body::from(user_data)))
-      .text("attachments", attachments.join("\n"));
+    let mut form = Form::new().text("backup_id", backup_id);
+
+    if let Some(user_keys_value) = user_keys.clone() {
+      form = form
+        .text(
+          "user_keys_hash",
+          Sha256::digest(&user_keys_value).encode_hex::<String>(),
+        )
+        .part("user_keys", Part::stream(Body::from(user_keys_value)));
+    }
+
+    if let Some(user_data_value) = user_data.clone() {
+      form = form
+        .text(
+          "user_data_hash",
+          Sha256::digest(&user_data_value).encode_hex::<String>(),
+        )
+        .part("user_data", Part::stream(Body::from(user_data_value)));
+    }
+
+    form = form.text("attachments", attachments.join("\n"));
 
     if let Some(siwe_backup_msg_value) = siwe_backup_msg {
       form = form.text("siwe_backup_msg", siwe_backup_msg_value);
     }
 
     let response = client
-      .post(self.url.join("backups")?)
+      .post(self.url.join(endpoint)?)
       .bearer_auth(user_identity.as_authorization_token()?)
       .multipart(form)
       .send()
@@ -319,8 +334,8 @@
 #[derive(Debug, Clone)]
 pub struct BackupData {
   pub backup_id: String,
-  pub user_keys: Vec<u8>,
-  pub user_data: Vec<u8>,
+  pub user_keys: Option<Vec<u8>>,
+  pub user_data: Option<Vec<u8>>,
   pub attachments: Vec<String>,
   pub siwe_backup_msg: Option<String>,
 }
@@ -375,6 +390,7 @@
   LogMissing,
   WSClosed,
   Unauthenticated,
+  InvalidRequest,
 }
 impl std::error::Error for Error {}