Skip to main content

Push notifications (APNs)

The iOS SDK delivers branded incoming-call notifications via APNs. You hand us the raw Data device token; we handle hex encoding, server registration, payload templating, and stale-token deactivation.

1. Register for remote notifications​

Standard APNs registration at app launch (or after the user signs in):

import UIKit
import UserNotifications

class AppDelegate: UIResponder, UIApplicationDelegate {
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil
) -> Bool {
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { granted, _ in
guard granted else { return }
Task { @MainActor in application.registerForRemoteNotifications() }
}
return true
}
}

2. Forward the device token to Relavoi​

When APNs returns the token in didRegisterForRemoteNotificationsWithDeviceToken, pass the raw Data directly to the SDK. Do not convert to hex yourself — the SDK does it (lowercase hex, no spaces). appBundleId is optional; pass Bundle.main.bundleIdentifier so the backend can target the right app for pushes.

The full signature is registerToken(userPhone:deviceToken:appBundleId:), where deviceToken is the raw Data and appBundleId defaults to nil.

import RelavoiSDK

func application(
_ application: UIApplication,
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
) {
Task {
do {
try await Relavoi.shared.push.registerToken(
userPhone: currentUser.phone,
deviceToken: deviceToken,
appBundleId: Bundle.main.bundleIdentifier
)
} catch {
print("Failed to register push token: \(error)")
}
}
}

func application(
_ application: UIApplication,
didFailToRegisterForRemoteNotificationsWithError error: Error
) {
print("APNs registration failed: \(error)")
}

3. Handle stale tokens​

If APNs reports the token as unregistered, the Relavoi backend deactivates it automatically and returns no more pushes for it. On the next successful registerToken call after a fresh APNs registration, the SDK reactivates.

You can explicitly deactivate (e.g. on logout). deactivateToken requires the same raw Data device token you registered:

try await Relavoi.shared.push.deactivateToken(deviceToken: deviceToken)

4. Notification payload shape​

Relavoi pushes are standard APNs alerts with aps.alert.title, aps.alert.body, and a relavoi data dictionary containing sessionId, callId, and eventType. You can inspect them in userNotificationCenter(_:didReceive:) if you want to deep-link into your app:

extension AppDelegate: UNUserNotificationCenterDelegate {
func userNotificationCenter(
_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: @escaping () -> Void
) {
if let sessionId = response.notification.request.content.userInfo["sessionId"] as? String {
router.openSession(sessionId)
}
completionHandler()
}
}

5. Background modes​

For higher-priority delivery during in-progress calls, enable Background Modes -> Remote notifications in your target capabilities. The Relavoi backend automatically uses apns-priority: 10 and apns-push-type: alert for call notifications.

:::tip Test deliverability Use POST /v1/webhooks/test with a call.incoming payload to send a real push to your device while developing. Combined with TestFlight, it provides an end-to-end check without scripting APNs. :::