--- title: "Document + Selfie IDV | Veriff.com" slug: "document-selfie-idv" description: "Complete identity verification using document analysis and facial comparison. Available via SDK and API." tags: ["Automatic Setup Supported", "Decision Webhook", "Hybrid setup supported", "Identity Verification"] updated: 2025-07-18T11:26:35Z published: 2025-07-18T11:26:35Z canonical: "devdocs.veriff.com/document-selfie-idv" --- > ## Documentation Index > Fetch the complete documentation index at: https://devdocs.veriff.com/llms.txt > Use this file to discover all available pages before exploring further. # Document + Selfie IDV This is the **type of identity verification** where Veriff analyses the images of the end-user and of their ID document **(selfie + document)**, verifies the data, and returns the decision and data extracted from the document. You can add Veriff’s IDV to your systems via **native** **SDKs, web flow (aka web SDKs) and API**. All session-related **info is returned** **via decision webhook** and can be **queried via different API endpoints**. The results of the verification can also be viewed in the Veriff Customer Portal, under the **Verification** tab. To balance speed, conversion, and fraud mitigation during the identity verification process, the solution is available in both hybrid and full auto set-ups: - **Hybrid**: highly automated AI solution supported by trained verification specialists, designed for businesses that want to balance speed with accuracy, fraud prevention, and risk insights - **Full Auto**: fully automated AI solution, great for businesses that require the fastest speed and most cost-effective solution *→ See* [*Veriff Decision Engines: Full Auto & Hybrid*](https://help.veriff.com/en/articles/10657140-veriff-decision-engines-full-auto-hybrid) *in Knowledge Base for more info* > [!NOTE] > **Document + selfie IDV solution uses the decision webhook** to return decision and session related data. > > Do not concern yourself with Full Auto webhook, it is not used for document + selfie IDV solution. --- ## Prerequisites - You have an [**integration set up**](/v1/docs/how-to-create-an-integration) **with Veriff** - You have set up the [**decision webhook**](/v1/docs/decision-webhook) to get responses from Veriff (see the how-to in [Set up webhooks](https://devdocs.veriff.com/docs/webhooks-guide#set-up-webhooks) section) - If using the API: - Veriff **strongly recommends** you collect and send **additional device/session data** for improved fraud mitigation - Veriff **strongly recommends** that you **create and send** us the endUserId or vendorData --- ## Flow overview The flow is a bit different, depending on the method you are using to verify your end-users with Veriff. ### Use via SDKs 1. Generate a verification session using the `API keys` and the `baseURL` of your Doc + Selfie IDV integration (see the [API Documentation and API Reference](https://devdocs.veriff.com/apidocs) how to find these) 2. Capture end-user’s document and selfie images with Veriff’s SDKs 1. Send the end-user through the verification flow to capture the images (using the preferred [Veriff SDK](/v1/docs/sdk-guide)) 2. You need the session URL generated in step 1 to use the SDKs (found in response payload as `verification.url`) 3. Session will be submitted automatically once the end-user takes and submits necessary images 4. Receive the results from Veriff via [decision webhook](/v1/docs/decision-webhook) ### Use via API 1. Generate a verification session using the a `API keys` and the `baseURL` of your Doc + Selfie IDV integration (see the [API Documentation and API Reference](https://devdocs.veriff.com/apidocs) how to find these) 1. Veriff strongly recommends you create and send the `endUserId` or `vendorData` 2. Veriff strongly recommends you collect and send additional session/device data via [POST sessions/{sessionid}/collected-data](https://devdocs.veriff.com/apidocs/v1sessionsidcollected-data-1) for improved fraud detection 2. Use your image-capturing method, or prepare previously collected end-user selfie and document images 3. Upload the end-user's media via [POST /sessions/{sessionId}/media](https://devdocs.veriff.com/apidocs/v1sessionsidmedia-3) call 1. Specify the `image.context` as appropriate for the image (see [Context types (image, video)](/v1/docs/context-types-image-video-1) for more info about image context types) 4. Patch session status to `submitted` status using [PATCH /sessions/{sessionId}](https://devdocs.veriff.com/apidocs/v1sessionsid-2) call 5. Check the decision data and/or session related info from the [decision webhook](/v1/docs/decision-webhook) and/or query the data from the [GET /sessions/{sessionId}/decision](/v1-api/apidocs/v1sessionsiddecision-1) endpoint --- ## Find decision and/or session related info You can get the data from three sources: - Receive the decision webhook - Query the results via GET sessions/{sessionId}/decision - View the session in Veriff Customer Portal ### Webhook payload > [!NOTE] > Below are a **sample** and an **explanation** of a **decision webhook payload for a minimal document + selfie IDV**. > > Depending on your solution, the payload may contain additional parameters. To find more info about it, see the [decision webhook](/v1/docs/decision-webhook) documentation. #### Sample request ```json {    "status": "success",    "verification": {        "id": "12df6045-3846-3e45-946a-14fa6136d78b",        "attemptId": "6cab5b0-c506-47a6-922d-6ae3b72ca172",        "vendorData": "12345678",        "endUserId": "a1b2c35d-e8f7-6d5e-3cd2-a1b2c35db3d4",        "status": "approved",        "code": 9001,        "reason": null,        "reasonCode": null,        "decisionTime": "2019-11-06T07:18:36.916Z",        "acceptanceTime": "2019-11-06T07:15:27.000Z",        "person": {            "firstName": "SARAH",            "lastName": "MORGAN",            "dateOfBirth": "1967-03-30",            "gender": null,            "nationality": null,            "idNumber": null,            "yearOfBirth": "1967",            "placeOfBirth": "MADRID",            ...            "pepSanctionMatch": null,            "citizenship": null,        },        "document": {            "number": "MORGA753116SM9IJ",            "type": "DRIVERS_LICENSE",                        "country": "US",            "state": "NY",            ...            }        },        "additionalVerifiedData": [],        "comments": []    },        "highRisk": false,    "technicalData": {        "ip": "186.153.67.122"    }  } ``` #### Request properties explained *Always sent, irrespective of solution’s configuration - `status`: `string`* Status of the response - `verification`: `object`* Verification request decision object. `null` if decision is not available yet - `id`: `string`* UUID v4 which identifies the verification session - `attemptId`: `string`* UUID v4 of the attempt which received a status (as shown in `verification.status` field) - `vendorData`: `string | null`* The unique identifier that you created for your end-user. `null` if not specified - `endUserId`: `string | null`* The `UUID` that you created for your end-user. `null` if not specified - `status`: `string`* Verification status, one of `approved`, `declined`, `resubmission_requested`, `review`, `expired`,` abandoned` - `code`: `integer`* Verification session decision code, one of `9001`, `9102`, `9103`, `9104`, `9121`. For more info, see the [verification session decision codes](/v1/docs/verification-session-decision-codes-table) - `reason`: `string | null`* Reason why the verification failed - `reasonCode`: `integer | null`* Reason code of the failed verification. For more info, see the [possible codes for a failed verification](/v1/docs/verification-session-decision-codes-table) - `decisionTime`: `string | null`* Timestamp of the decision, represented as `UTC YYYY-MM-DDTHH:MM:SS.SSS+Timezone Offset` (ISO 8601) - `acceptanceTime`: `string`* Timestamp of the session generation, represented as `UTC YYYY-MM-DDTHH:MM:SS.SSS+Timezone Offset` (ISO 8601) - **`person` : `object`* Data about the verified person** - `firstName`: `string | null`* Person's first name as written on the document - `lastName`: `string | null`* Person's last name as written on the document - `dateOfBirth`: `string`* Person’s date of birth, represented as `YYYY-MM-DD` - `gender`: `string | null`* Person’s gender, represented as M or F, or `null` if not present - `nationality`: `string | null`* Person’s nationality, represented as ISO 3166 `alpha-2` or `alpha-3` number - `idNumber`: `string | null`* National identification number - `yearOfBirth`: `string | null`* Person’s year of birth, represented as `YYYY` - `placeOfBirth`: `string | null`* Person’s place of birth - … - **`document` : `object`* Data about the verified document** - `number`: `string | null`* Document number, `[a-zA-Z0-9]` characters only - `type`: `string | null`* Document type, one of `PASSPORT`, `ID_CARD`, `RESIDENCE_PERMIT`, `DRIVERS_LICENSE`, `VISA`, `OTHER`. For more info, see the [Supported document types for IDV](/v1/docs/supported-document-types-for-idv) article - `country`: `string | null`* Document issuing country, represented as ISO 3166 `alpha-2` code - `state`: `string | null`* Document issuing state, represented as ISO 3166 `alpha-2` or `alpha-3` code - … - `additionalVerifiedData`: `array` Data that has been optionally verified for the session, depending on the integration. Empty if no additional data was verified - `comments`: `array` *(Deprecated) Always returns empty []* - `highRisk`: `boolean` *(Deprecated) Marked if session was considered high risk or not* - `technicalData`: `object`* Technical data object - `ip`: `string | null` IP of the device from which the verification was made ### API call You can use the [GET /sessions/{sessionId}/decision](/v1-api/apidocs/v1sessionsiddecision-1) endpoint to get the decision data. > [!NOTE] > Below are a **sample** and an **explanation** of a **API call payload for a minimal document + selfie IDV**. > > Depending on your solution, the payload may contain additional parameters. To find more info about it, see the [GET /sessions/{sessionId}/decision](/v1-api/apidocs/v1sessionsiddecision-1) documentation. #### Sample response ```json {    "status": "success",    "verification": {        "id": "12df6045-3846-3e45-946a-14fa6136d78b",        "attemptId": "6cab5b0-c506-47a6-922d-6ae3b72ca172",        "vendorData": "12345678",        "endUserId": "a1b2c35d-e8f7-6d5e-3cd2-a1b2c35db3d4",        "status": "approved",        "code": 9001,        "reason": null,        "reasonCode": null,        "decisionTime": "2019-11-06T07:18:36.916Z",        "acceptanceTime": "2019-11-06T07:15:27.000Z",        "person": {            "firstName": "SARAH",            "lastName": "MORGAN",            "dateOfBirth": "1967-03-30",            "gender": null,            "nationality": null,            "idNumber": null,            "yearOfBirth": "1967",            "placeOfBirth": "MADRID",            ...            "pepSanctionMatch": null,            "citizenship": null,        },        "document": {            "number": "MORGA753116SM9IJ",            "type": "DRIVERS_LICENSE",                        "country": "US",            "state": "NY",            ...            }        },        "additionalVerifiedData": [],        "comments": []    },        "highRisk": false,    "technicalData": {        "ip": "186.153.67.122"    }  } ``` #### Response properties explained - `status`: `string` Status of the response - `verification`: `object` Verification request decision object. `null` if decision is not available yet - `id`: `string` UUID v4 which identifies the verification session - `attemptId`: `string` UUID v4 of the attempt which received a status (as shown in `verification.status` field) - `vendorData`: `string | null` The unique identifier that you created for your end-user. `null` if not specified - `endUserId`: `string | null` The `UUID` that you created for your end-user. `null` if not specified - `status`: `string` Verification status, one of `approved`, `declined`, `resubmission_requested`, `review`, `expired`,` abandoned` - `code`: `integer` Verification session decision code, one of `9001`, `9102`, `9103`, `9104`, `9121`. For more info, see the [verification session decision codes](/v1/docs/verification-session-decision-codes-table) - `reason`: `string | null` Reason why the verification failed - `reasonCode`: `integer | null` Reason code of the failed verification. For more info, see the [possible codes for a failed verification](/v1/docs/verification-session-decision-codes-table) - `decisionTime`: `string` Timestamp of the decision, represented as `UTC YYYY-MM-DDTHH:MM:SS.SSS+Timezone Offset` (ISO 8601) - `acceptanceTime`: `string` Timestamp of the session generation, represented as `UTC YYYY-MM-DDTHH:MM:SS.SSS+Timezone Offset` (ISO 8601) - **`person` : `object` Data about the verified person** - `firstName`: `string` | `null` Person's first name as written on the document - `lastName`: `string` | `null` Person's last name as written on the document - `dateOfBirth`: `string` Person’s date of birth, represented as `YYYY-MM-DD` - `gender`: `string` | `null` Person’s gender, represented as M or F, or `null` if not present - `nationality`: `string` | `null` Person’s nationality, represented as ISO 3166 `alpha-2` or `alpha-3` number - `idNumber`: `string` | `null` National identification number - `yearOfBirth`: `string` | `null` Person’s year of birth, represented as `YYYY` - `placeOfBirth`: `string` | `null` Person’s place of birth - … - **`document` : `object` Data about the verified document** - `number`: `string` | `null` Document number, `[a-zA-Z0-9]` characters only - `type`: `string` | `null` Document type, one of `PASSPORT`, `ID_CARD`, `RESIDENCE_PERMIT`, `DRIVERS_LICENSE`, `VISA`, `OTHER`. For more info, see the [Supported document types for IDV](/v1/docs/supported-document-types-for-idv) article - `country`: `string` | `null` Document issuing country, represented as ISO 3166 `alpha-2` code - `state`: `string` |` null` Document issuing state, represented as ISO 3166 `alpha-2` or `alpha-3` code - … - `additionalVerifiedData`: `array` Data that has been optionally verified for the session, depending on the integration. Empty if no additional data was verified - `comments`: `array` *(Deprecated) Always returns empty []* - `highRisk`: `boolean` *(Deprecated) Marked if session was considered high risk or not* - `technicalData`: `object` Technical data object - `ip`: `string | null` IP of the device from which the verification was made ### Veriff Customer Portal You can find the verification session related info, including the decision, in the Veriff Customer Portal, under the **Verifications** tab. → *See* [*Review verification in Veriff Customer Portal*](/v1/docs/how-to-review-verification-in-veriff-customer-portal) *about how to view the session info in the Veriff Customer portal* --- ## Status and reason codes For an `approved` session, see: - `verification.code` about verification session decision code, one of `9001`, `9102`, `9103`, `9104`, `9121` - `verification.status` about verification status, one of `approved`, `declined`, `resubmission_requested`, `review`, `expired`,` abandoned` If the session was `declined` or `resubmission_requested`, you can find additional information by checking: - `verification.reason` for the reason why the verification failed - `verification.reasonCode` for reason code of the failed verification and cross-reference it with [Granular reason codes (table)](/v1/docs/granular-reason-codes) #### The `review` status > [!NOTE] > Not available by default You need to make an **agreement with Veriff to enable** this option for you and **you agree to perform the review on your side**. Meaning that if Veriff’s system is unable to reach a conclusive decision, the session is set to review and sent to your decision-making flow. For more info about the codes you are seeing, refer to: - [Verification session status codes (table)](/v1/docs/verification-session-status-codes-table) - [Verification session decision codes (table)](/v1/docs/verification-session-decision-codes-table) - [Granular reason codes (table)](/v1/docs/granular-reason-codes) --- ## Session lifecycle flow diagram ![The diagram shows how a identity verification process moves from creation to completion or resubmission/review, with appropriate handling guides at different stages](https://cdn.document360.io/5c26138b-b1e9-404e-a2e4-c83a49245be7/Images/Documentation/session%20lifecycle%20diagram_basic.jpg?sv=2026-02-06&spr=https&st=2026-10-26T11%3A37%3A27Z&se=2026-10-26T12%3A37%3A27Z&sr=c&sp=r&sig=R%2BBg3G5W%2BxUaFkaZ8geyruxIni%2Fm5MPzOA%2FiTmLj2TY%3D) --- ## FAQ #### Where can I query the data related to the session and the end-user? 📖 session ID | attempt ID | mediaId The following endpoints can be used to query data related to the verification session and the end-user: - [GET /sessions/{sessionId}/attempts](https://devdocs.veriff.com/apidocs/v1sessionsidattempts-1) - allows querying the **id-s of different attempts** done during one verification session, using the `sessionId` - [GET /sessions/{sessionId}/decision](https://devdocs.veriff.com/apidocs/v1sessionsiddecision-1) - allows querying the **verification session decision data**, using the `sessionId` - [GET /sessions/{sessionId}/person](https://devdocs.veriff.com/apidocs/v1sessionsidperson-1) - allows querying the **data related to the person** verified in the session, using the `sessionId` - [GET /sessions/{sessionId}/media](https://devdocs.veriff.com/apidocs/v1sessionsidmedia-2) - allows querying **info about the media** uploaded during the session (using the `sessionId`) - [GET /attempts/{attemptId}/media](https://devdocs.veriff.com/apidocs/v1attemptsidmedia-1) - allows querying **info about the media** uploaded during a certain attempt (using the `attemptId`) - [GET /media/{mediaId}](https://devdocs.veriff.com/apidocs/v1mediaid-1) - allows querying the **media file** using the `mediaId` of a specific media file To find more info about the public API endpoints listed above, see the [API Documentation and API Reference](https://devdocs.veriff.com/apidocs). --- ## Changelog | Date | Description | | --- | --- | | Jul 18, 2025 | `decisionTime` field description updated, to indicate that it can also be `null` | | Jun 6, 2025 | Heading “Article versioning” changed to “Changelog” | | Apr 25, 2025 | Missing link added | | Mar 31, 2025 | Documentation published "Hybrid document + selfie IDV" and "Full Auto IDV" articles have been consolidated into this single article. To improve clarity, the content now focuses on the document + selfie IDV solution's features, setup process, and decision data without distinguishing between hybrid and full auto implementation types. | **User of Veriff customer's solution**, the person who goes through the verification flow (aka "end-user flow"). Veriff customer back-office, a dashboard where you can see your end-users' verification data. Depending on your setup, you may be required to access the environment via station.veriff.com or hub.veriff.com. Always **check your sign-up email** and make sure that you **log in via correct address**. A UUID-format unique identifier ([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}) created by you for your end-user to link an end-user to their session(s). Cannot be resolved outside your environment. Veriff stores it only for identity verification and returns it unchanged in webhooks/API responses or as `null` if not provided. Strongly recommended if you already use UUID identifiers. Works as an alternative to `vendorData` in Biometric Authentication solution. A custom unique identifier (max 1,000 characters) created by you, containing only non-semantic data that can't be resolved outside your systems. Veriff returns it unchanged in webhooks/API responses or as `null` if not provided. It's referred to as "unique identifier" in Customer Portal and cannot be changed once set. Required for Fraud solutions (Cross Links check and Velocity Abuse check) and serves as an alternative to `endUserId` in Biometric Authentication when using non-UUID identifiers. A session during which the end-user is verified. It starts when a session is created, it can contain several attempts (i.e. steps of uploading media, sending additional data etc.) and it ends when a conclusive decision (“approved”, “declined”, “expired”/”abandoned”) is granted. Each verification session receives an unique ID, aka the **session ID**, which can be added to the API URL when making API requests. An environment created according to customer's needs to carry out, manage and observe verifications. You can find the list of your integrations in **Veriff Customer Portal** > **All** **Integrations** page (you need to be logged in). This where the end-user is directed to go through the verification flow, and it is **unique for each verification session**. It is a combination of the `base URL` and the `sessionToken`, created as soon as a verification session is created. You can find its value in the response payload of your POST /sessions call, as `verification.url`. The data that you send when you make an API request, or that you receive when you get a response. A **unique identifier of a verification session**. It is automatically created as soon as you create a session. In the **API requests' context**, one verification session comprises many steps (uploading data, uploading images, getting a decision, etc.). You can call several endpoints using the same **session ID**, to get all kinds of different data from that specific session. You can find its value in the **response payload** of your **POST /sessions API request**, in the `verification.id` parameter. An **UUID v4** of a specific **attempt**, found in decision webhook as `attemptId` parameter, or in **GET /sessions/{sessionId}/attempts** response as `verification.id` parameter. An **"attempt" is one step inside a verification session**, e.g., uploading required data and getting a decision. An **"attempt" can be made several times** during a verification session. This means that calling the GET /sessions/{sessionId}/attempts can return several `verification` objects, each one with a unique `id` value. A **unique identifier** of a specific **media file**. To get the `mediaId` of a specific media file, request a list of media via GET attempts/{attemptId}/media or GET sessions/{sessionId}/media. ## Related - [Getting Started](/getting-started.md) - [Integrations](/how-to-create-an-integration.md) - [Create verification session](/how-to-generate-sessions-manually.md) - [Webhooks Guide](/webhooks-guide.md) - [Codes](/codes.md)