diff --git a/keyserver/addons/rust-node-addon/rust-binding-types.js b/keyserver/addons/rust-node-addon/rust-binding-types.js
--- a/keyserver/addons/rust-node-addon/rust-binding-types.js
+++ b/keyserver/addons/rust-node-addon/rust-binding-types.js
@@ -7,6 +7,16 @@
   +accessToken: string,
 };
 
+type InboundKeyInfoResponse = {
+  +payload: string,
+  +payloadSignature: string,
+  +socialProof?: ?string,
+  +contentPrekey: string,
+  +contentPrekeySignature: string,
+  +notifPrekey: string,
+  +notifPrekeySignature: string,
+};
+
 type RustNativeBindingAPI = {
   +loginUser: (
     username: string,
@@ -35,7 +45,7 @@
     message: string,
     signature: string,
   ) => Promise<void>,
-  +publish_prekeys: (
+  +publishPrekeys: (
     userId: string,
     deviceId: string,
     accessToken: string,
@@ -44,6 +54,11 @@
     notifPrekey: string,
     notifPrekeySignature: string,
   ) => Promise<boolean>,
+  +getInboundKeysForUserDevice: (
+    identifierType: string,
+    identifierValue: string,
+    deviceId: string,
+  ) => Promise<InboundKeyInfoResponse>,
 };
 
 export type { RustNativeBindingAPI };
diff --git a/keyserver/addons/rust-node-addon/src/identity_client/get_inbound_keys_for_user.rs b/keyserver/addons/rust-node-addon/src/identity_client/get_inbound_keys_for_user.rs
new file mode 100644
--- /dev/null
+++ b/keyserver/addons/rust-node-addon/src/identity_client/get_inbound_keys_for_user.rs
@@ -0,0 +1,36 @@
+use super::*;
+
+#[napi]
+#[instrument(skip_all)]
+pub async fn get_inbound_keys_for_user_device(
+  identifier_type: String,
+  identifier_value: String,
+  device_id: String,
+) -> Result<InboundKeyInfoResponse> {
+  // Set up the gRPC client that will be used to talk to the Identity service
+  let channel = get_identity_service_channel().await?;
+  let mut identity_client = IdentityClientServiceClient::new(channel);
+
+  let identifier = match identifier_type.as_str() {
+    "walletAddress" => Some(Identifier::WalletAddress(identifier_value)),
+    "username" => Some(Identifier::Username(identifier_value)),
+    _ => return Err(Error::from_status(Status::GenericFailure)),
+  };
+
+  let inbound_keys_for_user_request = InboundKeysForUserRequest { identifier };
+
+  let mut response = identity_client
+    .get_inbound_keys_for_user(inbound_keys_for_user_request)
+    .await
+    .map_err(|e| Error::new(Status::GenericFailure, e.to_string()))?
+    .into_inner();
+
+  let inbound_key_info = InboundKeyInfoResponse::try_from(
+    response
+      .devices
+      .remove(&device_id)
+      .ok_or(Error::from_status(Status::GenericFailure))?,
+  )?;
+
+  Ok(inbound_key_info)
+}
diff --git a/keyserver/addons/rust-node-addon/src/identity_client/mod.rs b/keyserver/addons/rust-node-addon/src/identity_client/mod.rs
--- a/keyserver/addons/rust-node-addon/src/identity_client/mod.rs
+++ b/keyserver/addons/rust-node-addon/src/identity_client/mod.rs
@@ -1,5 +1,6 @@
 pub mod add_reserved_usernames;
 pub mod auth_client;
+pub mod get_inbound_keys_for_user;
 pub mod login;
 pub mod prekey;
 pub mod register_user;
@@ -10,9 +11,10 @@
 
 use identity_client::identity_client_service_client::IdentityClientServiceClient;
 use identity_client::{
-  AddReservedUsernamesRequest, DeviceKeyUpload, DeviceType, IdentityKeyInfo,
-  PreKey, RegistrationFinishRequest, RegistrationStartRequest,
-  RemoveReservedUsernameRequest,
+  inbound_keys_for_user_request::Identifier, AddReservedUsernamesRequest,
+  DeviceKeyUpload, DeviceType, IdentityKeyInfo, InboundKeyInfo,
+  InboundKeysForUserRequest, PreKey, RegistrationFinishRequest,
+  RegistrationStartRequest, RemoveReservedUsernameRequest,
 };
 use lazy_static::lazy_static;
 use napi::bindgen_prelude::*;
@@ -118,6 +120,61 @@
   pub access_token: String,
 }
 
+#[napi(object)]
+pub struct InboundKeyInfoResponse {
+  pub payload: String,
+  pub payload_signature: String,
+  pub social_proof: Option<String>,
+  pub content_prekey: String,
+  pub content_prekey_signature: String,
+  pub notif_prekey: String,
+  pub notif_prekey_signature: String,
+}
+
+impl TryFrom<InboundKeyInfo> for InboundKeyInfoResponse {
+  type Error = Error;
+
+  fn try_from(key_info: InboundKeyInfo) -> Result<Self> {
+    let identity_info = key_info
+      .identity_info
+      .ok_or(Error::from_status(Status::GenericFailure))?;
+
+    let IdentityKeyInfo {
+      payload,
+      payload_signature,
+      social_proof,
+    } = identity_info;
+
+    let content_prekey = key_info
+      .content_prekey
+      .ok_or(Error::from_status(Status::GenericFailure))?;
+
+    let PreKey {
+      pre_key: content_prekey_value,
+      pre_key_signature: content_prekey_signature,
+    } = content_prekey;
+
+    let notif_prekey = key_info
+      .notif_prekey
+      .ok_or(Error::from_status(Status::GenericFailure))?;
+
+    let PreKey {
+      pre_key: notif_prekey_value,
+      pre_key_signature: notif_prekey_signature,
+    } = notif_prekey;
+
+    Ok(Self {
+      payload,
+      payload_signature,
+      social_proof,
+      content_prekey: content_prekey_value,
+      content_prekey_signature,
+      notif_prekey: notif_prekey_value,
+      notif_prekey_signature,
+    })
+  }
+}
+
 pub fn handle_grpc_error(error: tonic::Status) -> napi::Error {
   warn!("Received error: {}", error.message());
   Error::new(Status::GenericFailure, error.message())