diff --git a/services/tunnelbroker/rust-notifications/src/apns.rs b/services/tunnelbroker/rust-notifications/src/apns.rs
--- a/services/tunnelbroker/rust-notifications/src/apns.rs
+++ b/services/tunnelbroker/rust-notifications/src/apns.rs
@@ -1,8 +1,10 @@
+use crate::ffi::apns_status;
 use a2::{
-  Client, Endpoint, NotificationBuilder, NotificationOptions,
-  PlainNotificationBuilder,
+  Client, Endpoint, Error,
+  ErrorReason::{BadDeviceToken, Unregistered},
+  NotificationBuilder, NotificationOptions, PlainNotificationBuilder,
 };
-use anyhow::Result;
+use anyhow::{anyhow, Result};
 use std::fs::File;
 
 pub async fn send_by_a2_client(
@@ -12,7 +14,7 @@
   topic: &str,
   message: &str,
   sandbox: bool,
-) -> Result<u16> {
+) -> Result<apns_status> {
   let mut certificate = File::open(certificate_path)?;
   let endpoint = if sandbox {
     Endpoint::Sandbox
@@ -28,6 +30,27 @@
   let builder = PlainNotificationBuilder::new(message);
   let mut payload = builder.build(device_token, options);
   payload.aps.content_available = Some(1);
-  let response = client.send(payload).await?;
-  Ok(response.code)
+  match client.send(payload).await {
+    Ok(_) => Ok(apns_status::Ok),
+    Err(Error::ResponseError(response)) => {
+      if let Some(error_body) = response.error {
+        match error_body.reason {
+          // We are returning `Ok` with the error types here to distinguish the exact 
+          // error type in a C++ side
+          BadDeviceToken => Ok(apns_status::BadDeviceToken),
+          Unregistered => Ok(apns_status::Unregistered),
+          _ => Err(anyhow!(
+            "Notification was not accepted by APNs, reason: {:?}",
+            error_body.reason
+          )),
+        }
+      } else {
+        Err(anyhow!(
+          "Unhandled response error from APNs, response: {:?}",
+          response
+        ))
+      }
+    }
+    Err(error) => Err(anyhow::Error::new(error)),
+  }
 }
diff --git a/services/tunnelbroker/rust-notifications/src/lib.rs b/services/tunnelbroker/rust-notifications/src/lib.rs
--- a/services/tunnelbroker/rust-notifications/src/lib.rs
+++ b/services/tunnelbroker/rust-notifications/src/lib.rs
@@ -1,3 +1,4 @@
+use crate::ffi::apns_status;
 use anyhow::Result;
 use env_logger;
 use lazy_static::lazy_static;
@@ -8,6 +9,12 @@
 
 #[cxx::bridge]
 mod ffi {
+  #[cxx_name = "apnsReturnStatus"]
+  enum apns_status {
+    Ok,
+    Unregistered,
+    BadDeviceToken,
+  }
   extern "Rust" {
     #[cxx_name = "sendNotifToAPNS"]
     fn send_notif_to_apns(
@@ -17,7 +24,7 @@
       topic: &str,
       message: &str,
       sandbox: bool,
-    ) -> Result<u16>;
+    ) -> Result<apns_status>;
 
     #[cxx_name = "sendNotifToFCM"]
     fn send_notif_to_fcm(
@@ -44,7 +51,7 @@
   topic: &str,
   message: &str,
   sandbox: bool,
-) -> Result<u16> {
+) -> Result<apns_status> {
   RUNTIME.block_on(apns::send_by_a2_client(
     certificate_path,
     certificate_password,