Online Requests, Authentication, And Messaging
This page explains the public mobileID.notifications API for request-driven workflows. It covers fetching messages and requests, handling online authentication creation, presenting PIN or face prompts when required, and responding to lifecycle and push events.
What This Covers
- fetching notifications with
FetchRequest - reading notification metadata and request details
- handling online authentication with
LoginRequestandLoginSession - accepting, declining, acknowledging, or deleting notifications
- presenting PIN and face prompts through
RequestAuthenticationDelegate - reacting to new message and pending-request lifecycle events
- forwarding APNs device tokens to the SDK
Public API Surface
Notifications
mobileID.notificationsNotifications.fetch(id:) async throws -> MobileIDNotificationNotifications.fetch(_:) async throws -> [MobileIDNotification]Notifications.handle(loginRequest:) async throws -> LoginSession
Notification Types
MobileIDNotificationMobileIDNotification.idMobileIDNotification.titleMobileIDNotification.bodyMobileIDNotification.customMessageMobileIDNotification.typeMobileIDNotification.statusMobileIDNotification.dataMobileIDNotification.eligibleCredentials()MobileIDNotification.eligibleCredentialTypes()MobileIDNotification.accept(using:delegate:) async throwsMobileIDNotification.decline() async throwsMobileIDNotification.acknowledge() async throwsMobileIDNotification.delete() async throws
Request Authentication
LoginRequest(qrCode:)LoginRequest(deepLink:)LoginSession.poll() async throws -> MobileIDNotificationRequestAuthenticationDelegatePinViewControllerFaceViewControllerAuthenticationRequest
Filtering And Push
FetchRequestFetchRequest.PageFetchRequest.NotificationFilterTypeMobileIDNotification.StatusPushNotificationsmobileID.pushNotifications.didReceive(deviceToken:)mobileID.pushNotifications.clearToken()mobileID.pushNotifications.isTokenStored
Lifecycle Events
mobileID.events.onNewMessagesReceivedmobileID.events.onPendingRequestsReceived
End-To-End Flow
1. Fetch Notifications
Use FetchRequest to load a page of notifications. The default request includes messages, lifecycle events, and requests:
Swift1import MobileIDCore23@MainActor4func loadInbox(from mobileID: MobileID) async {5 do {6 let request = FetchRequest(7 page: .first,8 statuses: [.new, .read],9 types: [.messages, .lifecycleEvents, .requests(outOfBand: nil)]10 )1112 let notifications = try await mobileID.notifications.fetch(request)13 print("Loaded \(notifications.count) notifications")14 } catch {15 print("Failed to fetch notifications: \(error)")16 }17}
Use fetch(id:) when you already have the notification identifier and want one item back.
2. Read Notification Details
MobileIDNotification gives you the public presentation fields you need for inbox and consent screens:
titleandbodyfor summary textcustomMessagefor additional copy when presentcreated,updated, andexpirationDatefor lifecycle and expiry handlingtypeandstatusfor routing the user experiencemidUidanddocumentTypefor credential-related requestseligibleCredentials()andeligibleCredentialTypes()for request fulfillment
Request notifications also expose data, which can contain request-specific metadata such as client name, logo URL, claim names, or out-of-band markers.
3. Handle Online Authentication Creation
Online authentication begins with a LoginRequest. You can create it from a QR code or a deep link:
Swift1import MobileIDCore23func makeLoginRequest(from qrCode: QrCode) throws -> LoginRequest {4 try LoginRequest(qrCode: qrCode)5}67func makeLoginRequest(from deepLink: DeepLink) throws -> LoginRequest {8 try LoginRequest(deepLink: deepLink)9}
Pass the request to mobileID.notifications.handle(loginRequest:) to start request creation:
Swift1@MainActor2func startAuthentication(from loginRequest: LoginRequest, mobileID: MobileID) async {3 do {4 let loginSession = try await mobileID.notifications.handle(loginRequest: loginRequest)5 let notification = try await loginSession.poll()6 print("Authentication request ready: \(notification.id)")7 } catch {8 print("Unable to start authentication: \(error)")9 }10}
LoginSession.poll() waits until the request notification is available or throws a retry-limit error if the backend never produces one.
4. Accept A Request With Authentication
When a request notification requires user approval, choose an eligible credential and call accept(using:delegate:):
Swift1@MainActor2func approve(request: MobileIDNotification, credential: EnrolledCredential, delegate: RequestAuthenticationDelegate) async {3 do {4 try await request.accept(using: credential, delegate: delegate)5 } catch {6 print("Request approval failed: \(error)")7 }8}
If the request requires PIN or face verification, the SDK calls your RequestAuthenticationDelegate and gives you the prompt to present:
Swift1final class NotificationAuthDelegate: RequestAuthenticationDelegate {2 private weak var navigationController: UINavigationController?34 init(navigationController: UINavigationController) {5 self.navigationController = navigationController6 }78 func notification(_ request: AuthenticationRequest, promptedForAuthentication authenticationPrompt: PinViewController) {9 navigationController?.pushViewController(authenticationPrompt, animated: true)10 }1112 func notification(_ request: AuthenticationRequest, promptedForAuthentication authenticationPrompt: FaceViewController) {13 navigationController?.pushViewController(authenticationPrompt, animated: true)14 }1516 func didFinishAuthentication(of request: AuthenticationRequest) {17 navigationController?.popToRootViewController(animated: true)18 }1920 func notificationDidBecomeBusy(_ request: AuthenticationRequest, expectedInterval: NavigatorBusyStateInterval) {21 // Show a loading state.22 }2324 func notificationDidBecomeIdle(_ request: AuthenticationRequest) {25 // Hide the loading state.26 }27}
Keep the prompt presentation in one place so request-driven authentication feels consistent across your app.
5. Decline, Acknowledge, Or Delete
Use the matching action for the notification type and user intent:
Swift1func dismissMessage(_ notification: MobileIDNotification) async {2 do {3 try await notification.acknowledge()4 } catch {5 print("Acknowledge failed: \(error)")6 }7}89func declineRequest(_ notification: MobileIDNotification) async {10 do {11 try await notification.decline()12 } catch {13 print("Decline failed: \(error)")14 }15}1617func removeNotification(_ notification: MobileIDNotification) async {18 do {19 try await notification.delete()20 } catch {21 print("Delete failed: \(error)")22 }23}
Use acknowledge() for informational messages, decline() for requests the user does not want to approve, and delete() when the user wants to remove the card from the inbox.
6. Filter Requests And Messages
FetchRequest supports paging, status filtering, and type filtering:
Swift1let requestPage = FetchRequest.Page(number: 0, size: 20)2let requestFilter = FetchRequest(3 page: requestPage,4 statuses: [.new],5 types: [.messages, .requests(outOfBand: false)]6)
Useful filter options include:
.lifecycleEvents.messages.requests(outOfBand: nil).requests(outOfBand: true).requests(outOfBand: false)
Use FetchRequest.Page.next() when you implement pagination.
7. React To Push And Lifecycle Events
Forward the APNs token so the SDK can receive push-driven updates:
Swift1import UIKit23func application(4 _ application: UIApplication,5 didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data6) {7 mobileID.pushNotifications.didReceive(deviceToken: deviceToken)8}
When the SDK reports new message or pending-request availability through mobileID.events, refresh the inbox view:
Swift1func configureNotificationsEvents(for mobileID: MobileID) {2 mobileID.events.onNewMessagesReceived = { notifications in3 print("New messages: \(notifications.count)")4 }56 mobileID.events.onPendingRequestsReceived = { notifications in7 print("Pending requests: \(notifications.count)")8 }9}
Use mobileID.pushNotifications.isTokenStored to inspect registration state and clearToken() if you need to stop forwarding pushes.
8. Handle Errors Safely
Notification APIs surface errors for invalid payloads, expired or unsupported requests, timeout conditions, and authentication failures. Handle them with a user-facing recovery path and avoid showing raw backend details directly.
Common examples include:
NotificationsError.retryLimitExceededNotificationsError.unsupportedDeepLinkNotificationsError.invalidLoginRequestPayloadNotificationsError.authenticationKeyExpiredISO18013.Error.invalidAuthenticationISO18013.Error.credentialLocked
Implementation Notes
- Use
fetch(id:)for direct lookups andfetch(_:)for inbox screens. - Treat request notifications and message notifications as separate user journeys.
- Keep authentication prompt presentation in the UI layer, not inside a network service.
- Use
eligibleCredentials()to present only valid choices to the user. - Call
poll()on the returnedLoginSessionuntil the request notification becomes available. - Refresh the inbox after lifecycle callbacks or push-driven updates.
Related Pages
Getting StartedPIN And Liveness VerificationOnline And Offline Presentments (ISO 18013)Credential Wallet And Lifecycle