<!--
{
  "documentType" : "article",
  "framework" : "PassKit",
  "identifier" : "/documentation/PassKit/requesting-identity-data-from-a-wallet-pass",
  "metadataVersion" : "0.1.0",
  "role" : "article",
  "title" : "Requesting identity data from a Wallet pass"
}
-->

# Requesting identity data from a Wallet pass

Initiate a request for identity information by prompting a user for permission and decrypting a response payload.

## Discussion

The Wallet app allows people to store an identification card, for example, a mobile driver’s license (mDL), or national identification card from a government issuing authority, or a digital ID issued by Apple.

Beginning on iPhone with iOS 16, you can request information from IDs in Wallet to verify a person’s age or identity. If a person accepts the request, the system gets the information from their issuing authority and your app receives a payload. After decryption, the payload contains data that follows the ISO 18013-5 specification. To use the elements your app requests, send the payload to your server for verification.

For design guidance, see [Human Interface Guidelines > Technologies > Wallet](https://developer.apple.com/design/human-interface-guidelines/technologies/wallet/introduction).

> Important:
> Building an app with this entitlement requires macOS 13 or later. For more information about the entitlement, see [Getting started with the Verify with Wallet API](https://developer.apple.com/wallet/get-started-with-verify-with-wallet/).

### Create an identity document descriptor

Before you request information from an ID in Wallet, you create an object to describe the elements you need. Your app can only request the elements your entitlement grants. There are a few identity document descriptor options:

- [`PKIdentityDriversLicenseDescriptor`](/documentation/PassKit/PKIdentityDriversLicenseDescriptor): For requesting information from a person’s state or mobile driver’s license.
- [`PKIdentityNationalIDCardDescriptor`](/documentation/PassKit/PKIdentityNationalIDCardDescriptor): For requesting information from their national identificaton card, and add the elements to the request.
- [`PKIdentityPhotoIDDescriptor`](/documentation/PassKit/PKIdentityPhotoIDDescriptor): For requesting information from a digital ID.
- [`PKIdentityAnyOfDescriptor`](/documentation/PassKit/PKIdentityAnyOfDescriptor): For requesting information for more than one identity document.

For each element, you specify your intent to store the resulting data by using [`mayStore(days:)`](/documentation/PassKit/PKIdentityIntentToStore/mayStore(days:)), [`mayStore`](/documentation/PassKit/PKIdentityIntentToStore/mayStore), or [`willNotStore`](/documentation/PassKit/PKIdentityIntentToStore/willNotStore). Upon request, the system presents the information for a person to review in a system sheet.

The framework allows for requesting the Boolean [`age(atLeast:)`](/documentation/PassKit/PKIdentityElement/age(atLeast:)) element for any age between `1` and `125` only if the issuer includes it. If an app requests [`age(atLeast:)`](/documentation/PassKit/PKIdentityElement/age(atLeast:)) and the `age_over_XX` element isn’t present in the mobile driver’s license, the framework falls back to a request for the age element.

An app can’t include both an [`age(atLeast:)`](/documentation/PassKit/PKIdentityElement/age(atLeast:)) element and an [`age`](/documentation/PassKit/PKIdentityElement/age) element in the same request.

The following code shows how you create the different identity document descriptors:

**PKIdentityDriversLicenseDescriptor:**

```swift
    let driversLicenseDescriptor = PKIdentityDriversLicenseDescriptor()
    driversLicenseDescriptor.addElements(
        [.age(atLeast: 18)],
        intentToStore: .willNotStore
    )
    driversLicenseDescriptor.addElements(
        [.givenName, 
        .familyName,
        .portrait],
        intentToStore: .mayStore(days: 30)
    )
```

**PKIdentityNationalIDCardDescriptor:**

```swift
    let nationalIDCardDescriptor = PKIdentityNationalIDCardDescriptor()
    nationalIDCardDescriptor.addElements(
        [.age(atLeast: 18)],
        intentToStore: .willNotStore
    )
    nationalIDCardDescriptor.addElements(
        [.givenName, 
        .familyName,
        .portrait],
        intentToStore: .mayStore(days: 30)
    )
```

**PKIdentityPhotoIDDescriptor:**

```swift
    let identityPhotoIDDescriptor = PKIdentityPhotoIDDescriptor()
    identityPhotoIDDescriptor.addElements(
        [.age(atLeast: 18)],
        intentToStore: .willNotStore
    )
    identityPhotoIDDescriptor.addElements(
        [.documentNumber, 
        .issuingAuthority,
        .familyName,
        .givenName],
        intentToStore: .mayStore(days: 30)
    )
```

**PKIdentityOfAnyDescriptor:**

```swift
    let identityPhotoIDDescriptor = PKIdentityPhotoIDDescriptor()
    identityPhotoIDDescriptor.addElements(
        [.documentNumber, 
        .issuingAuthority,
        .familyName,
        .givenName],
        intentToStore: .mayStore(days: 30)
    )

    let driversLicenseDescriptor = PKIdentityDriversLicenseDescriptor()
    driversLicenseDescriptor.addElements(
        [.givenName, 
        .familyName,
        .portrait],
        intentToStore: .mayStore(days: 30)
    )

   let anyDescriptor = PKIdentityAnyOfDescriptor(descriptors: [identityPhotoIDDescriptor, driversLicenseDescriptor])
```

To check whether the identity document you describe is available to request, create a [`PKIdentityAuthorizationController`](/documentation/PassKit/PKIdentityAuthorizationController) and call [`checkCanRequestDocument(_:completion:)`](/documentation/PassKit/PKIdentityAuthorizationController/checkCanRequestDocument(_:completion:)). If the document exists, show a [`PKIdentityButton`](/documentation/PassKit/PKIdentityButton) to allow the user to begin the authorization request.

```swift
let controller = PKIdentityAuthorizationController()
controller.checkCanRequestDocument(descriptor) { canRequest in
    // Show or hide the identity button.
}
```

### Create a request

To create an identity request, you need the merchant identifier you configure in the developer portal. A merchant identifier never expires, and you can use the same one that you use for Apple Pay.

A request also needs a [`nonce`](/documentation/PassKit/PKIdentityRequest/nonce) to prevent your server from using a response document more than once. Your server needs the [`nonce`](/documentation/PassKit/PKIdentityRequest/nonce) to decrypt the response document, so generate it there and associate it with the user’s session.

```swift
let request = PKIdentityRequest()
request.descriptor = descriptor
request.merchantIdentifier = // The merchant identifier.
request.nonce = // The nonce your server generates.
```

Your app’s `Info.plist` file needs to provide a message for the `NSIdentityUsageDescription` key. If this key is missing, any attempt to request a document fails.

### Request the document

When requesting a document, the system presents a sheet to the user to confirm the request before retrieving any data. If the user rejects the request, your app receives a [`PKIdentityError.Code.cancelled`](/documentation/PassKit/PKIdentityError-swift.struct/Code/cancelled) error.

```swift
do {
    let document = try await controller.requestDocument(request)
} catch {
    // Handle the error.
}
```

When you receive a [`PKIdentityDocument`](/documentation/PassKit/PKIdentityDocument), you’re ready to verify the request payload. The data in the [`encryptedData`](/documentation/PassKit/PKIdentityDocument/encryptedData) property isn’t readable on the device, so you need to send it to your server for verification.

The elements in the descriptors map this way in their responses:

- [`PKIdentityDriversLicenseDescriptor`](/documentation/PassKit/PKIdentityDriversLicenseDescriptor) maps to a set of elements in the ISO and American Association of Motor Vehicle Administrators (AAMVA) namespaces.
- [`PKIdentityPhotoIDDescriptor`](/documentation/PassKit/PKIdentityPhotoIDDescriptor) maps to a set of elements in the ISO.
- [`PKIdentityNationalIDCardDescriptor`](/documentation/PassKit/PKIdentityNationalIDCardDescriptor) maps to a set of elements in the ISO and JP namespace.
- See [`PKIdentityDriversLicenseDescriptor`](/documentation/PassKit/PKIdentityDriversLicenseDescriptor), [`PKIdentityPhotoIDDescriptor`](/documentation/PassKit/PKIdentityPhotoIDDescriptor), and [`PKIdentityNationalIDCardDescriptor`](/documentation/PassKit/PKIdentityNationalIDCardDescriptor) for a list of elements.

> Note:
> Only one request can be in progress at a time. Otherwise, the system returns a ``doc://com.apple.passkit/documentation/PassKit/PKIdentityError-swift.struct/Code/requestAlreadyInProgress`` error.

To learn more about verifying identity requests, see <doc://com.apple.documentation/documentation/PassKit/verifying-wallet-identity-requests>.

### Test the implementation

Even if you don’t live in an area that supports IDs in Wallet, you can test your implementation through the iPhone simulator or by downloading a developer profile on your local device. When you request a document, you receive a mock mDL that’s similar to a real ID. When you test with the simulator, the response doesn’t include a real issuing authority or device signature. The developer test profile produces a real device signature, but not a real issuer signature. A mock mDL isn’t visible in the Wallet app, so don’t treat it as real. To activate a mock mDL on your device, download the Wallet identity developer profile from [Profiles and Logs](https://developer.apple.com/bug-reporting/profiles-and-logs/).

---

Copyright &copy; 2026 Apple Inc. All rights reserved. | [Terms of Use](https://www.apple.com/legal/internet-services/terms/site.html) | [Privacy Policy](https://www.apple.com/privacy/privacy-policy)