Understanding results
After a successful verification, call fetchSessionResults() from your backend to retrieve the verified identity data. This guide explains the response format, common field types, and how to handle errors.
Response structure
Section titled “Response structure”fetchSessionResults() returns a SessionResultsData object:
| Field | Type | Description |
|---|---|---|
status | 'success' | 'error' | Whether credential verification passed. |
response | Record<string, Record<string, unknown>> | Verified fields, keyed by ISO 18013-5 namespace. Present on both success and error (may contain partial data on error). |
errors | Record<string, unknown> | Empty object on success. Contains error details when status is 'error'. |
warnings | Record<string, unknown> | May be non-empty even on success (e.g., CRL fetch issues that didn’t block verification). |
Namespaces
Section titled “Namespaces”The response object is keyed by namespace strings defined in ISO 18013-5. The standard mDL namespace is org.iso.18013.5.1. Each namespace maps element names to their values:
const mdl = results.response['org.iso.18013.5.1'];const givenName = mdl.given_name; // "Jane"Fields you didn’t request or that the wallet omitted will be absent — always check for presence before accessing.
Data types
Section titled “Data types”| Element | Type | Example |
|---|---|---|
family_name, given_name, issuing_authority, etc. | string | "Doe" |
birth_date, issue_date, expiry_date | string (ISO 8601 date) | "1990-03-15" |
age_over_18, age_over_21, etc. | boolean | true |
age_in_years | integer | 34 |
portrait | number[] (byte array, typically PNG) | [137, 80, 78, ...] |
driving_privileges | object[] | Array of privilege objects |
Displaying a portrait
Section titled “Displaying a portrait”The portrait field is a byte array. To display it as an image:
const base64 = btoa(String.fromCharCode(...new Uint8Array(mdl.portrait)));const imgSrc = `data:image/png;base64,${base64}`;Success examples
Section titled “Success examples”Age verification only
Section titled “Age verification only”Using NAMESPACES_MDL_AGE_OVER_18_ONLY:
{ "status": "success", "response": { "org.iso.18013.5.1": { "age_over_18": true } }, "errors": {}, "warnings": {}}const mdl = results.response['org.iso.18013.5.1'];if (mdl.age_over_18) { // User is 18 or older}Age in years
Section titled “Age in years”Using launchAgeInYearsVerification():
{ "status": "success", "response": { "org.iso.18013.5.1": { "age_in_years": 34 } }, "errors": {}, "warnings": {}}const mdl = results.response['org.iso.18013.5.1'];if (mdl.age_in_years >= 21) { // User is 21 or older}Name only
Section titled “Name only”Using NAMESPACES_MDL_NAME_ONLY:
{ "status": "success", "response": { "org.iso.18013.5.1": { "family_name": "Doe", "given_name": "Jane" } }, "errors": {}, "warnings": {}}const mdl = results.response['org.iso.18013.5.1'];const fullName = `${mdl.given_name} ${mdl.family_name}`;All mandatory fields
Section titled “All mandatory fields”Using NAMESPACES_MDL_ALL_MANDATORY:
{ "status": "success", "response": { "org.iso.18013.5.1": { "birth_date": "1990-03-15", "document_number": "DL123456", "driving_privileges": [ { "vehicle_category_code": "C", "issue_date": "2020-01-01", "expiry_date": "2028-01-01" } ], "expiry_date": "2028-06-30", "family_name": "Doe", "given_name": "Jane", "issue_date": "2020-06-30", "issuing_authority": "CA DMV", "issuing_country": "US", "portrait": [137, 80, 78, 71, 13, 10, 26, 10], "un_distinguishing_sign": "USA" } }, "errors": {}, "warnings": {}}Handling errors
Section titled “Handling errors”Errors fall into two categories: verification errors (returned in the response) and exceptions (thrown as JavaScript Errors).
Verification errors
Section titled “Verification errors”When credential verification fails, fetchSessionResults() returns a result with status: 'error'. The errors object contains details, and response may contain partial data:
{ "status": "error", "response": { "org.iso.18013.5.1": { "family_name": "Doe" } }, "errors": { "parsing_errors": "..." }, "warnings": {}}Always check status before using response data:
const results = await fetchSessionResults(id, apiKey);
if (results.status === 'success') { const mdl = results.response['org.iso.18013.5.1']; // Use verified data} else { console.error('Verification errors:', results.errors); // Show a user-friendly message — prompt them to try again}When retrying after a verification error, always create a new session with fetchSessionData(). Do not reuse the existing session.
Exceptions
Section titled “Exceptions”fetchSessionResults() throws an Error for issues that prevent returning a structured result:
| Scenario | Error message contains | What to do |
|---|---|---|
| Session expired or already consumed | "Not Found" | Sessions expire after 10 minutes and are single-read. Create a new session. |
| Session still in progress | "Conflict" | The user hasn’t completed verification yet. Wait and retry, or poll with a delay. |
| Invalid API key | "Unauthorized" | Check that your API key is correct and matches your environment. |
| Network failure | "Error making request" | Check network connectivity and the verifier URL. |
try { const results = await fetchSessionResults(id, apiKey); // Handle results...} catch (error) { if (error.message.includes('Not Found')) { // Session expired — create a new one } else if (error.message.includes('Conflict')) { // Still in progress — retry after a delay } else { console.error('Unexpected error:', error.message); }}Stability
Section titled “Stability”status,response,errors,warnings— these top-level keys are stable across SDK versions.- Namespace keys (e.g.,
org.iso.18013.5.1) are defined by ISO 18013-5 and stable. - Element names within namespaces (e.g.,
family_name,birth_date) are defined by ISO and AAMVA standards and stable. - Error key strings inside
errors(e.g.,parsing_errors) are internal and may change. Don’t match on specific error keys for control flow — treat a non-emptyerrorsobject as “something went wrong.” - Breaking changes to the SDK are communicated through semver.