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 LoginRequest and LoginSession
  • 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.notifications
  • Notifications.fetch(id:) async throws -> MobileIDNotification
  • Notifications.fetch(_:) async throws -> [MobileIDNotification]
  • Notifications.handle(loginRequest:) async throws -> LoginSession

Notification Types 

  • MobileIDNotification
  • MobileIDNotification.id
  • MobileIDNotification.title
  • MobileIDNotification.body
  • MobileIDNotification.customMessage
  • MobileIDNotification.type
  • MobileIDNotification.status
  • MobileIDNotification.data
  • MobileIDNotification.eligibleCredentials()
  • MobileIDNotification.eligibleCredentialTypes()
  • MobileIDNotification.accept(using:delegate:) async throws
  • MobileIDNotification.decline() async throws
  • MobileIDNotification.acknowledge() async throws
  • MobileIDNotification.delete() async throws

Request Authentication 

  • LoginRequest(qrCode:)
  • LoginRequest(deepLink:)
  • LoginSession.poll() async throws -> MobileIDNotification
  • RequestAuthenticationDelegate
  • PinViewController
  • FaceViewController
  • AuthenticationRequest

Filtering And Push 

  • FetchRequest
  • FetchRequest.Page
  • FetchRequest.NotificationFilterType
  • MobileIDNotification.Status
  • PushNotifications
  • mobileID.pushNotifications.didReceive(deviceToken:)
  • mobileID.pushNotifications.clearToken()
  • mobileID.pushNotifications.isTokenStored

Lifecycle Events 

  • mobileID.events.onNewMessagesReceived
  • mobileID.events.onPendingRequestsReceived

End-To-End Flow 

diagram

1. Fetch Notifications 

Use FetchRequest to load a page of notifications. The default request includes messages, lifecycle events, and requests:

Swift
1import MobileIDCore
2
3@MainActor
4func 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 )
11
12 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:

  • title and body for summary text
  • customMessage for additional copy when present
  • created, updated, and expirationDate for lifecycle and expiry handling
  • type and status for routing the user experience
  • midUid and documentType for credential-related requests
  • eligibleCredentials() and eligibleCredentialTypes() 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:

Swift
1import MobileIDCore
2
3func makeLoginRequest(from qrCode: QrCode) throws -> LoginRequest {
4 try LoginRequest(qrCode: qrCode)
5}
6
7func makeLoginRequest(from deepLink: DeepLink) throws -> LoginRequest {
8 try LoginRequest(deepLink: deepLink)
9}

Pass the request to mobileID.notifications.handle(loginRequest:) to start request creation:

Swift
1@MainActor
2func 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:):

Swift
1@MainActor
2func 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:

Swift
1final class NotificationAuthDelegate: RequestAuthenticationDelegate {
2 private weak var navigationController: UINavigationController?
3
4 init(navigationController: UINavigationController) {
5 self.navigationController = navigationController
6 }
7
8 func notification(_ request: AuthenticationRequest, promptedForAuthentication authenticationPrompt: PinViewController) {
9 navigationController?.pushViewController(authenticationPrompt, animated: true)
10 }
11
12 func notification(_ request: AuthenticationRequest, promptedForAuthentication authenticationPrompt: FaceViewController) {
13 navigationController?.pushViewController(authenticationPrompt, animated: true)
14 }
15
16 func didFinishAuthentication(of request: AuthenticationRequest) {
17 navigationController?.popToRootViewController(animated: true)
18 }
19
20 func notificationDidBecomeBusy(_ request: AuthenticationRequest, expectedInterval: NavigatorBusyStateInterval) {
21 // Show a loading state.
22 }
23
24 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:

Swift
1func dismissMessage(_ notification: MobileIDNotification) async {
2 do {
3 try await notification.acknowledge()
4 } catch {
5 print("Acknowledge failed: \(error)")
6 }
7}
8
9func declineRequest(_ notification: MobileIDNotification) async {
10 do {
11 try await notification.decline()
12 } catch {
13 print("Decline failed: \(error)")
14 }
15}
16
17func 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:

Swift
1let 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:

Swift
1import UIKit
2
3func application(
4 _ application: UIApplication,
5 didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
6) {
7 mobileID.pushNotifications.didReceive(deviceToken: deviceToken)
8}

When the SDK reports new message or pending-request availability through mobileID.events, refresh the inbox view:

Swift
1func configureNotificationsEvents(for mobileID: MobileID) {
2 mobileID.events.onNewMessagesReceived = { notifications in
3 print("New messages: \(notifications.count)")
4 }
5
6 mobileID.events.onPendingRequestsReceived = { notifications in
7 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.retryLimitExceeded
  • NotificationsError.unsupportedDeepLink
  • NotificationsError.invalidLoginRequestPayload
  • NotificationsError.authenticationKeyExpired
  • ISO18013.Error.invalidAuthentication
  • ISO18013.Error.credentialLocked

Implementation Notes 

  • Use fetch(id:) for direct lookups and fetch(_:) 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 returned LoginSession until the request notification becomes available.
  • Refresh the inbox after lifecycle callbacks or push-driven updates.
  • Getting Started
  • PIN And Liveness Verification
  • Online And Offline Presentments (ISO 18013)
  • Credential Wallet And Lifecycle