In-person verification quickstart guide
This quickstart is for evaluating the MATTR Pi mDocs Verifier SDKs for in-person verification. In about 10 minutes you will configure a sample verifier mobile app (iOS, Android, or React Native), run it on a test device and use it to verify an mDoc presented in-person from a different device using the proximity presentation workflow defined by ISO/IEC 18013-5:2021.
Use this guide as a fast evaluation path to see the Verifier Mobile SDK working end-to-end on real devices. For detailed information and API examples, explore the tutorial and reference documentation tailored for each platform.
User experience
In this quickstart you will perform this exact flow yourself using the sample verifier app and the GO Hold example app:
- The holder uses their wallet application to generate and present a QR code.
- The verifier scans the QR code, connects with the wallet, and requests an mDoc for verification.
- The wallet application displays matching credentials to the holder and asks for consent to share them with the verifier.
- The verifier application receives the wallet's response and verifies the provided credential.
- Verification results are displayed to the verifier.
Prerequisites
- Access to the MATTR Pi mDocs Verifier SDK for your chosen platform (iOS, Android, or React Native). Apply for access here.
- Two physical mobile devices to run the verifier and holder applications:
- Development environment set up for your chosen platform (e.g., Xcode for iOS, Android Studio for Android, or a React Native development environment).
Steps
In this quickstart you will:
- Configure a local sample verifier project for your platform.
- Run a sample verifier app and verify a credential presented in-person from a holder device.
- Review the structure of the sample project so you can see how to integrate the SDK into your own app.
Use the tabs below to follow platform-specific setup steps.
Configure the sample verifier project (5-10 Minutes)
- Download and unzip the sample iOS proximity verifier project.
- Use Xcode to open the
.xcodeprojfile in the unzipped folder. - Drag the
MobileCredentialVerifierSDK-*version*.xcframeworkfolder (obtained from MATTR as part of the SDK package) into your project. - Configure
MobileCredentialVerifierSDK-*version*.xcframeworkto Embed & sign. - Set a unique bundle identifier for the project in the Xcode project settings (e.g.,
com.yourname.proximityverifier). - Run the project on a physical iOS device (simulators do not support the required Bluetooth capabilities).
- Download and unzip the sample Android proximity verifier project.
- Open the project in Android Studio.
- Unzip the
mobile-credential-verifier-*version*.zipfile (obtained from MATTR as part of the SDK package). - Drag the unzipped
globalfolder into the project'srepofolder. - Sync Project with Gradle files to recognize the new module.
- Run the project on a physical Android device (emulators do not support the required Bluetooth capabilities).
-
Access the completed sample verifier codebase by either:
-
Cloning the MATTR sample-apps repository:
Clone the repository git clone https://github.com/mattrglobal/sample-apps.gitor
-
Downloading just the relevant directory using the download-directory.github.io utility.
-
-
Open the completed sample verifier project in your code editor. You can find it in the
sample-apps/react-native-mdocs-verifier-tutorial/react-native-mdocs-verifier-tutorial-completedirectory. -
Open the
app.config.tsfile. -
Update the iOS
bundleIdentifierto a unique value for your application, e.g.com.mycompany.myapp.app.config.ts bundleIdentifier: "com.mycompany.myapp", -
Update the Android
packageto a unique value, e.g.com.mycompany.myapp:app.config.ts package: "com.mycompany.myapp", -
Navigate to the starter project directory and install dependencies:
Install dependencies yarn install
You must be logged in to npm with access to the MATTR Pi mDocs Verifier SDK package to install dependencies successfully. If you have not yet been granted access to the SDK, apply for access here.
-
Run the following command to generate the iOS and Android project files:
Generate project files yarn expo prebuild
You should now see the ios and android folders in your project root.
- Connect your testing device(s) and run the following command(s) to start the application(s):
iOS
yarn ios --deviceAndroid
yarn android --deviceVerify a credential using the sample verifier app (3 Minutes)
- On your holder testing device, launch the GO Hold example app.
- Tap the Blue Share button.
- Select Respond or Collect. This will open the camera view (You may need to allow the app to access your camera).
- Scan the following QR code:

- Follow the on-screen instructions to claim the credential (Note that this workflow requires an active internet connection).
- Once the credential is claimed, select the Blue Share button again.
- Select Share Credential and then choose the Connection QR tab to display a QR code.
- On your verifier testing device, launch the sample verifier app and select the Scan QR Code button.
- Use the verifier testing device to scan the QR code displayed on the holder testing device.
- On your holder testing device, consent to sharing the information with the verifier.
- On your verifier testing device, review the verification results displayed in the app.
Behind the scenes, the Verifier Mobile SDK handles device engagement, secure session establishment, and verification of the mDoc according to ISO/IEC 18013-5:2021.
Review the codebase
The sample verifier application uses the Verifier Mobile SDK to verify mDocs presented in-person from a wallet. Once you have the sample application running, use this section to inspect the key SDK calls you will reuse in your own application.
The sample projects include code comments that explain the purpose of each step and how it maps to the in-person verification workflow. The key steps for handling in-person verification with the SDK are outlined below, along with links to the relevant API reference documentation for each platform.
Initialize the SDK
In the sample app, SDK initialization happens once during startup so the verifier can handle in-person sessions.
mobileCredentialVerifier.initialize()MobileCredentialVerifier.initialize(activity)const result = await initialize();
if (result.isErr()) {
// Handle error: result.error
}Adding a trusted issuer certificate
In the sample app, a trusted issuer certificate is added during startup after SDK initialization. This allows the verifier to validate the authenticity of credentials issued by trusted issuers.
try await mobileCredentialVerifier.addTrustedIssuerCertificates(certificates: [certificate])certificate: Pass the IACA certificate of an issuer you want your application to trust.
MobileCredentialVerifier.addTrustedIssuerCertificates(certificates = listOf(certificate))certificate: Pass the IACA certificate of an issuer you want your application to trust.
await mobileCredentialVerifier.addTrustedIssuerCertificates([certificate])certificate: Pass the IACA certificate of an issuer you want your application to trust.
Create a presentation request object
Before sending a presentation request to the holder, the verifier application needs to create a request object that defines the type of credential and specific attributes being requested for verification.
let mobileCredentialRequest = MobileCredentialRequest(
docType: "<DocType>",
namespaces: [
"<Namespace>": [
"<AttributeName1>": false,
"<AttributeName2>": false,
"<AttributeName3>": false
]
]
)docType: The type of credential being requested (e.g., an mDL).namespaces: A dictionary mapping each namespace to its requested attributes. Each attribute is a key with a Boolean indicating whether the verifier intends to retain this attribute (true) or not (false).
val mobileCredentialRequest = MobileCredentialRequest(
docType = "<DocType>",
namespaces = NameSpaces(
mapOf(
"<Namespace>" to DataElements(
mapOf(
"<AttributeName1>" to false,
"<AttributeName2>" to false,
"<AttributeName3>" to false
)
)
)
)
)docType: The type of credential being requested (e.g., an mDL).namespaces: A map of requested attributes under each namespace, where false indicates the verifier does not intent to retain this attribute.
const mobileCredentialRequest = {
docType: '<DocType>',
namespaces: {
'<Namespace>': {
'<AttributeName1>': false,
'<AttributeName2>': false,
'<AttributeName3>': false
}
}
}docType: The type of credential being requested (e.g., an mDL).namespaces: An object that defines the attributes being requested for each namespace. A value offalseindicates the verifier does not intent to retain this attribute.
Create a proximity presentation session
Once the verifier application receives a device engagement string (e.g., from scanning a QR code presented by the holder), it can create a proximity presentation session to establish a secure connection with the holder's wallet and send presentation requests.
- Extend a class with the
ProximityPresentationSessionListenerprotocol:
extension VerifierViewModel: ProximityPresentationSessionListener {
public func onEstablished() {
// Handle session establishment: show presentation session details or send a request.
}
public func onTerminated(error: (any Error)?) {
/// Handle session termination
print("Session Terminated")
}
}- Call the
createProximityPresentationSessionfunction with an instance of the extended class:
mobileCredentialVerifier.createProximityPresentationSession(encodedDeviceEngagementString: deviceEngagementString, listener: self)encodedDeviceEngagementString: Pass the device engagement string retrieved from a QR code presented by the holder.listener: An object that conforms toProximityPresentationSessionListenerprotocol and will handle the session events.
- Implement the
ProximityPresentationSessionListenerinterface:
val sessionListener = object : ProximityPresentationSessionListener {
override fun onEstablished() {
// Handle session establishment: show presentation session details or send a request.
}
override fun onTerminated(error: Throwable?) {
Log.d("SessionListener", "Session Terminated")
}
}- Call the
createProximityPresentationSessionfunction with an instance of the extended class:
MobileCredentialVerifier.createProximityPresentationSession(activity, deviceEngagementString, sessionListener)deviceEngagementString: Pass the device engagement string retrieved from a QR code presented by the holder.sessionListener: An object that implementsProximityPresentationSessionListenerinterface and will handle the session events.
const proximityPresentationSession =
await mobileCredentialVerifier.createProximityPresentationSession({
encodedDeviceEngagementString: encodedDeviceEngagementString,
onSessionTerminated: (error) => {
// Handle session termination or error
}
})encodedDeviceEngagementString: Pass the device engagement string retrieved from a QR code presented by the holder.onSessionTerminated: A callback triggered when the session ends or fails.
The
createProximityPresentationSession
method returns an empty success response, indicating that the session has been created and the
verifier application can send a presentation request to the holder.
Listen to NFC session requests
To support NFC-based device engagement in addition to QR code scanning, the verifier application can listen for NFC session requests. When an NFC session request is received, the SDK will automatically create a proximity presentation session and trigger the appropriate session listener callbacks.
This capability is currently only available in the Android SDK.
MobileCredentialVerifier.registerForNfcDeviceEngagement(activity, sessionListener)-
sessionListener: An object that implements theProximityPresentationSessionListenerinterface and will handle the session events.Stop listening to NFC session requests MobileCredentialVerifier.deregisterForNfcDeviceEngagement(activity)
This capability is currently only available in the Android SDK.
Send a presentation request
After a proximity presentation session is established (e.g., after scanning a QR code or receiving an NFC engagement), the verifier application can send a presentation request to the holder's wallet to request specific credentials for verification.
try await mobileCredentialVerifier.sendProximityPresentationRequest(request: [mobileCredentialRequest], checkStatus: true)request: Pass theMobileCredentialRequestobject created in the previous step.checkStatus: A Boolean indicating whether to check credential revocation status. Set totrue(default) to check credential revocation status as part of the verification, orfalseto skip status checking.
MobileCredentialVerifier.sendProximityPresentationRequest(request = listOf(mobileCredentialRequest), checkStatus = true)request: Pass theMobileCredentialRequestobject created in the previous step.checkStatus: A Boolean indicating whether to check credential revocation status. Set totrue(default) to check credential revocation status as part of the verification, orfalseto skip status checking.
const mobileCredentialResponse =
await proximityPresentationSession.sendProximityPresentationRequest({
request: mobileCredentialRequest,
checkStatus: true
})request: Pass theMobileCredentialRequestobject created two steps up.checkStatus: A Boolean indicating whether to check credential revocation status. Set totrue(default) to check credential revocation status as part of the verification, orfalseto skip status checking.
Handle the presentation response
After sending a presentation request, the verifier application will receive a response from the holder's wallet containing the credentials that match the request along with their verification status. The application can then handle this response to display verification results to the user.
The
requestMobileCredentials
method returns a
MobileCredentialResponse
object. This response contains the presentation details provided by the holder, including any errors
encountered and the verification status of the credentials returned in the response:
let mobileCredentialResponse = MobileCredentialResponse(
credentialErrors: [/* CredentialError */],
credentials: [
MobileCredentialPresentation(
branding: /* Branding information for displaying the credential */,
claimErrors: [
/* Namespace */: [
/* ElementID */: /* MobileCredentialResponseErrorCode */
]
],
claims: [
/* Namespace */: [
/* ElementID */: /* MobileCredentialElementValue */
]
],
docType: /* DocType */,
issuerInfo: /* IssuerInfo */,
validityInfo: /* Validity */,
verificationResult: /* VerificationResult */
)
]
)credentialErrors: Any requested docTypes not returned by the holder.credentials: A list of presented credentials with their data, status, and any attribute-specific errors.
The
sendProximityPresentationRequest
method returns a
MobileCredentialResponse
object. This response contains the presentation details provided by the holder, including any errors
encountered and the verification status of the credentials returned in the response:
data class MobileCredentialResponse(
val credentials: List<MobileCredentialPresentation>?,
val credentialErrors: List<CredentialError>?
)data class MobileCredentialPresentation(
val docType: DocType,
val validityInfo: MobileCredentialValidity,
val claimErrors: Map<NameSpace, Map<DataElementIdentifier, ErrorCode>>?,
val claims: Map<NameSpace, Map<DataElementIdentifier, MobileCredentialElement>>?,
val branding: Branding?,
val issuerInfo: IssuerInfo?,
val verificationResult: MobileCredentialVerificationResult
)data class CredentialError(
val docType: DocType,
val errorCode: ErrorCode
)
typealias DocType = String
typealias ErrorCode = IntcredentialErrors: Any requested docTypes not returned by the holder.credentials: A list of presented credentials with their data, status, and any attribute-specific errors.
The
sendProximityPresentationRequest
returns a
MobileCredentialResponse
object. This response contains the presentation details provided by the holder, including any errors
encountered and the verification status of the credentials returned in the response:
const mobileCredentialResponse = {
credentialErrors: [/* CredentialError */],
credentials: [
{
branding: /* Branding */,
claimErrors: {
/* Namespace */: {
/* ElementID */: /* MobileCredentialResponseErrorCode */
}
},
claims: {
/* Namespace */: {
/* ElementID */: /* MobileCredentialElementValue */
}
},
docType: /* DocType */,
issuerInfo: /* IssuerInfo */,
validityInfo: /* Validity */,
verificationResult: /* VerificationResult */
}
]
};
credentialErrors: Any requested docTypes not returned by the holder.credentials: A list of presented credentials with their data, status, and any attribute-specific errors.
Next steps
- For your evaluation:
- Note how long it took to configure and run the sample verifier app and complete an in-person verification.
- Consider how the sample’s presentation request and UI map to your real in-person verification use cases (for example, which attributes you would request and how you would display them).
- Explore the in-person verification tutorial for detailed instructions, configuration options, and production-grade patterns.
- Review the mDocs Verifier SDK overview to understand platform support, capabilities, and how proximity and remote verification relate.
How would you rate this page?
Last updated on