Pre-verified events

session.verification_status carries a verification_status on event.object: what ID.me already knows about the user at the moment they arrive. It is emitted after login or signup and before multifactor authentication, so you can tell early in the flow whether the user already holds the identity credential your policy requires, whether they have been to your application before, and whether they are brand new to ID.me.

See User verification events for the delivery envelope and the fields every event carries.

The verification status resource

FieldTypeDescription
typestringAlways verification_status
is_existing_walletbooleanWhether the user’s ID.me wallet existed before this session. true for a returning user, false for a user who just signed up.
is_preverified_for_policybooleanWhether the wallet holds a verified identity credential right now. true when the user is already pre-verified for the requesting policy, false when they do not yet hold the level it requires.
credential_optionnullable stringHow the user obtained their IAL2 credential. See Credential options. null when the wallet holds no credential.
credential_ial_highestnullable stringThe highest identity assurance level the wallet holds. 1 for KBA, KYC, or Fortified Identity; 2 for IAL2; classic_loa3 for LOA3 without a selfie. null when the wallet holds no credential.
credential_expiration_datenullable datetimeWhen the held credential expires, in ISO 8601 format. Most relevant to community credentials such as student status, and to credentials that require an annual network renewal. null when the credential does not expire, or the wallet holds no credential.
level_of_assurancenullable integerThe level of assurance the wallet holds. IAL2 is level 3. null when the wallet holds no credential.
identity_subgroupsarray of stringsEvery identity subgroup the user holds. Use it to recognize step-up scenarios, such as a user who has already completed KYC. See Identity subgroups. Empty when the wallet holds none.
previously_accessedbooleanWhether the user has accessed this policy and this application before, not merely ID.me generally.
previously_accessed_atnullable datetimeWhen the user last accessed this policy and this application, in ISO 8601 format. null when they never have.

Credential options

credential_option names the path the user took to their IAL2 credential:

Document, License, Passcard, Passport, In-person Verification, Trusted Referee, Trusted Referee v2, or Upgrade IAL2 Selfie.

Identity subgroups

identity_subgroups lists every subgroup the user holds, drawn from:

IAL2, LOA3, KYC, Fortified, and KBA-R.

Values are echoed exactly as ID.me stores them, with no code or enum translation, so new credential options, assurance levels, and identity subgroups appear here without a breaking change. Every field is always present: a user who holds no identity credential gets null for the credential fields rather than a missing key.

Example payload

session.verification_status
{
"data": {
"source": "idme:dev",
"sourcetype": "idme:auth",
"event": {
"event_id": "5a1c8e3d-9f47-4b62-8d05-1e6a2c7f4b93",
"event": "session.verification_status",
"uuid": "c3850702f02f4f948cede41610c2a715",
"user_email": "xbzi.gqcv@gmail.com",
"application_name": "Auth Portal",
"ipaddress": "55.55.55.55",
"device_fingerprint": "lu2pFqAQyLIr0MqVpDEV",
"useragent": "Mozilla/5.0 (iPhone; CPU iPhone OS 12_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile/15E148 Safari/604.1",
"created_at": "2026-07-04T13:11:58.204617Z",
"eid": null,
"app_id": null,
"state": null,
"object": {
"type": "verification_status",
"is_existing_wallet": true,
"is_preverified_for_policy": true,
"credential_option": "Passport",
"credential_ial_highest": "2",
"credential_expiration_date": "2027-01-31T00:00:00.000Z",
"level_of_assurance": 3,
"identity_subgroups": ["IAL2", "Fortified"],
"previously_accessed": true,
"previously_accessed_at": "2026-08-01T12:00:00.000Z"
}
}
}
}

A user who is new to ID.me and holds no credential yet:

session.verification_status
{
"data": {
"source": "idme:dev",
"sourcetype": "idme:auth",
"event": {
"event_id": "e0c4b82f-71a9-4d36-b5f8-9c204ae71d63",
"event": "session.verification_status",
"uuid": "7b1f4a90de234c0b9f6c8e2a5d41738c",
"user_email": "kvto.mpqz@gmail.com",
"application_name": "Auth Portal",
"ipaddress": "55.55.55.55",
"device_fingerprint": "Rq8tZmW3oPbK1nVxYcEu",
"useragent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36",
"created_at": "2026-07-04T13:15:07.884213Z",
"eid": null,
"app_id": null,
"state": null,
"object": {
"type": "verification_status",
"is_existing_wallet": false,
"is_preverified_for_policy": false,
"credential_option": null,
"credential_ial_highest": null,
"credential_expiration_date": null,
"level_of_assurance": null,
"identity_subgroups": [],
"previously_accessed": false,
"previously_accessed_at": null
}
}
}
}

New fields may be added to the verification status resource without a breaking change. Ignore fields you do not recognize rather than rejecting the payload.