> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mangopay.com/llms.txt
> Use this file to discover all available pages before exploring further.

# KYC/KYB integration

> Integrate Mangopay's hosted KYC/KYB verification solution

This guide explains how to integrate Mangopay's hosted KYC/KYB verification solution, which you to redirect your users to a secure, Mangopay-hosted web experience where they can complete all the necessary steps.

## Prerequisites

Before launching a session for a Natural User or Legal User in Production, ensure the following prerequisites are met.

### User category must be Owner

To request identity verification, a User must have the `UserCategory` of `OWNER`. The `OWNER` category requires the user to provide additional basic information and [enroll in Mangopay's SCA](/guides/sca/users#enrollment-in-the-user-lifecycle) (in Sandbox, you can bypass SCA by including the word `accept` in the `Email` or `LegalRepresentative.Email`).

The hosted IDV solution is available for the following User types:

* Natural User
* Legal Business
* Legal Soletrader
* Legal Organization

The hosted solution is not available for the Legal Partnership type, which is only relevant for a specific legal entity (GbR) Germany ([read more](/guides/users/verification/requirements/kyb-local#de-partnership)). If you're integrating the hosted solution and you work with Partnership users, contact Mangopay via the Dashboard.

### User data must match ID

The hosted IDV session verifies that the ID document used during the liveness check is for the registered user (and not someone else).

Therefore, the following data points must match the ID that will be used.

For a **Natural User**:

* `FirstName`
* `LastName`

For a **Legal Soletrader** and **Legal Organization**:

* `LegalRepresentative.FirstName`
* `LegalRepresentative.LastName`

For these user types, ensure you retrieve the user object data using [GET View a User (SCA)](/api-reference/users/view-user-sca) and ask the user to verify that it matches their identity document.

For **Legal Business**, the individual completing the liveness check does not have to be the pre-declared `LegalRepresentative`, but they do have to feature on the national registry of directors.

### Documents must conform to requirements

The documents used or uploaded through the IDV session must conform to Mangopay's requirements:

* **ID proof** – For Natural Users and individuals performing liveness checks, the identity document used must correspond to the forms of [ID accepted by Mangopay](/guides/users/verification/requirements/id-accepted).
* **KYB documents** – For Legal Soletrader, Business, and Organization, the Registration Proof and (if applicable) the Articles of Association must correspond to those listed in the [KYB local reference](/guides/users/verification/requirements/kyb-local), and translations must also be submitted where necessary.

The session provides links to these pages, but for legal users especially we recommend that you guide users in preparing their documents before initiating the session.

## Testing

For the hosted IDV experience in Sandbox, Mangopay provides a simulator that lets you replicate:

* The checks performed by Mangopay and their outcomes
* The user's liveness check

To use it, call the [POST Create an IDV Session](/api-reference/idv-sessions/create-idv-session) endpoint and follow the `HostedUrl` returned.

The guidance screens shown to the user are also included in Sandbox to give you the fullest picture of the experience without sensitive steps, and to understand the possible pathways.

In Sandbox, the simulation of checks performed retain their conditional logic, so some are only available depending on your previous selection.

For all users:

* `IDV_NAME_MATCH_CHECK` and `IDV_AGE_CHECK` are only performed if `IDENTITY_DOCUMENT_VERIFICATION` is validated

For a [Soletrader](/guides/users/verification/hosted/soletrader):

* `BUSINESS_NAME_MATCH` is only performed if `BUSINESS_VERIFICATION` is validated

For a [Business](/guides/users/verification/hosted/business):

* `BUSINESS_INSIGHTS_MATCH` is only performed if `BUSINESS_VERIFICATION` is validated

To simulate a `REVIEW` session for a Business or Soletrader, validate the IDV checks except any of:

* `BUSINESS_VERIFICATION`
* `BUSINESS_NAME_MATCH`
* `BUSINESS_INSIGHTS_MATCH`

Mangopay's [Postman collection](/postman) contains the endpoints you need <a href="https://www.postman.com/mgp-productstars/mangopay-sandbox/folder/15344095-8d9c5396-634f-46dc-9d13-8b8162850e25" target="_blank">create a User</a> and <a href="https://www.postman.com/mgp-productstars/mangopay-sandbox/request/pgy06wj/create-an-idv-session" target="_blank">launch their KYC/KYB session</a>.

## Sequence diagram

The following diagram gives an overview of the integration flow:

<div className="block dark:hidden">
  ```mermaid theme={null}
  %%{
    init: {
      'theme': 'base',
      'themeVariables': {
        'primaryColor': '#FFFFFF',
        'primaryTextColor': '#2D0F37',
        'primaryBorderColor': '#2D0F37',
        'lineColor': '#2D0F37',
        'secondaryColor': '#FFFFFF',
        'tertiaryColor': '#FFFFFF',
        'fontSize': '32px',
        'fontFamily': 'Inter',
        'noteBorderColor': "#f3f2ff",
        'noteBkgColor': "#F3F2FF",
        'noteTextColor': '#2D0F37'
      }
    }
  }%%
  sequenceDiagram
      participant U as User
      participant P as Your platform
      participant M as Mangopay API
      P->>M: POST Create IDV Session
      M-->>P: HostedUrl, Status: PENDING
      P->>U: Redirect to HostedUrl
      rect rgb(243, 242, 255)
          Note over U: Hosted KYC/KYB experience
          U->>U: If Legal User, enter data <br/>and submit KYB documents
          U->>U: Perform ID liveness <br/>check with smartphone
          U-->>M: Process data
      end
      U->>P: Redirect to ReturnUrl
      M-->>P: Webhook: IDV_VALIDATED / INCONCLUSIVE / FAILED
      P->>M: GET View an IDV Session
      M-->>P: Return Status, Checks, and (verified) Data
      alt Status: VALIDATED
          P->>U: Success pathway
      else Status: REFUSED
          P->>U: Check reasons and retry
      end
  ```
</div>

<div className="hidden dark:block">
  ```mermaid theme={null}
  %%{
    init: {
      'theme': 'base',
      'themeVariables': {
        'primaryColor': "#090d0d",
        'primaryTextColor': "#FFFFFF",
        'primaryBorderColor': "#FFFFFF",
        'secondaryColor': "#090D0D",
        'lineColor': "#FFFFFF",
        'tertiaryColor': "#FFFFFF",
        'fontSize': '32px',
        'fontFamily': 'Inter',
        'noteBorderColor': "#4f4f6e",
        'noteBkgColor': "#4f4f6e",
        'noteTextColor': "#FFFFFF"
      }
    }
  }%%
  sequenceDiagram
      participant U as User
      participant P as Your platform
      participant M as Mangopay API
      P->>M: POST Create IDV Session
      M-->>P: HostedUrl, Status: PENDING
      P->>U: Redirect to HostedUrl
      rect rgb(64, 65, 89)
          Note over U: Hosted KYC/KYB experience
          U->>U: If Legal User, enter data <br/>and submit KYB documents
          U->>U: Perform ID liveness <br/>check with smartphone
          U-->>M: Process data
      end
      U->>P: Redirect to ReturnUrl
      M-->>P: Webhook: IDV_VALIDATED / INCONCLUSIVE / FAILED
      P->>M: GET View an IDV Session
      M-->>P: Return Status, Checks, and (verified) Data
      alt Status: VALIDATED
          P->>U: Success pathway
      else Status: REFUSED
          P->>U: Check reasons and retry
      end
  ```
</div>

## Integration flow

<Steps>
  <Step title="Initiate the hosted session">
    Call the [POST Create an IDV Session](/api-reference/idv-sessions/create-idv-session) endpoint with the `UserId` to initiate a hosted KYC/KYB verification session.

    You must include a `ReturnUrl` to which the session redirects once it is completed, before the outcome is known.

    In the API response:

    * The `HostedUrl` value is the URL for the unique session, with your `ReturnUrl` encoded and appended.
    * The `Status` is `PENDING`, indicating that the session is available via the `HostedUrl` value, and the user has not successfully completed all the necessary steps.

    The `PENDING` status emits the `IDENTITY_VERIFICATION_PENDING` webhook event type with the session `Id` (read more about [setting up webhooks](/webhooks)).
  </Step>

  <Step title="Redirect the user to the hosted session">
    Redirect the user to the `HostedUrl` value received in the response.

    The unique session can be submitted within 7 days, after which the `Status` changes to `EXPIRED`.

    The object `Status` remains `PENDING` regardless of whether the session has been started or not. On your side you can track whether the `HostedUrl` was accessed by the user.
  </Step>

  <Step title="Let the user complete the session">
    On the `HostedUrl`, the experience guides them through all the required steps for KYC/KYB verification.

    For Natural Users, this involves only the ID liveness check using their smartphone. If the session is opened on desktop then a QR code is displayed for the user to scan.

    For the Legal User types, there are additional steps to confirm or enter data and upload KYB documents.

    For more details, see the dedicated guides on the user steps and validation checks:

    * [Natural](/guides/users/verification/hosted/natural)
    * [Soletrader](/guides/users/verification/hosted/soletrader)
    * [Business](/guides/users/verification/hosted/business)
    * [Organization](/guides/users/verification/hosted/organization)
  </Step>

  <Step title="Receive receive the user after completion">
    Once the session is completed, the `HostedUrl` redirects to the `ReturnUrl`.

    In all cases, the outcome of the session is not returned immediately, even in the case of automatic processing for Natural Users.
  </Step>

  <Step title="Listen to webhooks">
    When the outcome of the session is known, the `Status` is updated from `PENDING` and a [webhook notification](/webhooks) is emitted.

    For both Natural and Legal Users, the `PENDING` value can change directly to one of:

    | `Status`    | Webhook event type                | Description                                                                                                     |
    | :---------- | :-------------------------------- | :-------------------------------------------------------------------------------------------------------------- |
    | `VALIDATED` | `IDENTITY_VERIFICATION_VALIDATED` | The User became KYC/KYB verified: `KYCLevel` changed to `REGULAR` and verified data updated in the User object. |
    | `REFUSED`   | `IDENTITY_VERIFICATION_FAILED`    | User was not KYC/KYB verified and a new session must be created for them to retry.                              |

    For all Legal User types, the session may also pass to a temporary state before the final outcome:

    | `Status` | Webhook event type                   | Description                                             |
    | :------- | :----------------------------------- | :------------------------------------------------------ |
    | `REVIEW` | `IDENTITY_VERIFICATION_INCONCLUSIVE` | The session is under manual review by Mangopay’s teams. |
  </Step>

  <Step title="Handle outcomes">
    Once you receive a webhook, call [GET View an IDV Session](/api-reference/idv-sessions/view-idv-session) for more details about the session.

    In a successful case, this endpoint returns the verified data points that are updated in the User object.

    For `REFUSED` cases, the endpoint returns information about which `Checks` failed and for what reasons.

    To see key details about all the sessions attempted for a user, call [GET List IDV Session for a User](/api-reference/idv-sessions/list-idv-sessions-user).
  </Step>
</Steps>

## State machine

The following diagram shows the statuses of the [IDV Session](/api-reference/idv-sessions/idv-session-object) object:

<div className="block dark:hidden">
  ```mermaid theme={null}
  %%{
    init: {
      'theme': 'base',
      'themeVariables': {
        'primaryColor': '#FFFFFF',
        'primaryTextColor': '#2D0F37',
        'primaryBorderColor': '#2D0F37',
        'lineColor': '#2D0F37',
        'secondaryColor': '#FFFFFF',
        'tertiaryColor': '#FFFFFF',
        'fontSize': '32px',
        'fontFamily': 'Inter'
      }
    }
  }%%
  flowchart LR
      Start(["POST&nbsp;Create&nbsp;IDV&nbsp;Session"]) ==> PENDING
      PENDING == All automated checks pass ==> VALIDATED
      PENDING == Only possible if Legal User ==> REVIEW
      REVIEW == Manual review fails ==> REFUSED
      REVIEW == Manual review passes ==> VALIDATED
      PENDING ==> REFUSED
      VALIDATED == Downgrade / renewal ==> OUT_OF_DATE
      style Start stroke-width:3.5px
      style PENDING stroke-width:3.5px
      style REVIEW stroke-width:3.5px
      style VALIDATED stroke-width:3.5px
      style REFUSED stroke-width:3.5px
      style OUT_OF_DATE stroke-width:3.5px
  ```
</div>

<div className="hidden dark:block">
  ```mermaid theme={null}
  %%{
    init: {
      'theme': 'base',
      'themeVariables': {
        'primaryColor': "#090D0D",
        'primaryTextColor': "#FFFFFF",
        'primaryBorderColor': "#FFFFFF",
        'lineColor': "#FFFFFF",
        'secondaryColor': "#090D0D",
        'tertiaryColor': "#090D0D",
        'fontSize': '32px',
        'fontFamily': 'Inter'
      }
    }
  }%%
  flowchart LR
      Start(["POST&nbsp;Create&nbsp;IDV&nbsp;Session"]) ==> PENDING
      PENDING == All automated checks pass ==> VALIDATED
      PENDING == Only possible if Legal User ==> REVIEW
      REVIEW == Manual review fails ==> REFUSED
      REVIEW == Manual review passes ==> VALIDATED
      PENDING ==> REFUSED
      VALIDATED == Downgrade / renewal ==> OUT_OF_DATE
      style Start stroke-width:3.5px
      style PENDING stroke-width:3.5px
      style REVIEW stroke-width:3.5px
      style VALIDATED stroke-width:3.5px
      style REFUSED stroke-width:3.5px
      style OUT_OF_DATE stroke-width:3.5px
  ```
</div>

<ResponseField name="Status" type="string">
  The status of the overall IDV Session:

  * `PENDING` – The unique `HostedUrl` for the session has not yet been submitted by the user. This temporary state can transition to `VALIDATED`, `REFUSED`, `REVIEW`, or `EXPIRED`.
  * `REVIEW` – One or more automated checks was neither successful nor refused, so the session was sent for manual review by Mangopay’s teams. This temporary state is only applicable to Legal users and can transition to `REFUSED` or `VALIDATED`.
  * `VALIDATED` – - The session was validated and the User became KYC/KYB verified (indicated by the User object’s `KYCLevel`). When the `Status` changes to `VALIDATED`, the [verified data](/guides/users/verification/hosted#verified-data) in `Checks.Data` is used to replace existing data in the User object.
  * `REFUSED` – The session was refused and the User is not KYC/KYB verified. The `Checks.CheckStatus` shows which checks were `REFUSED` and the `Checks.Reasons` shows the [refused reason types](/guides/users/verification/hosted#refusals) and comment (which is custom text in the case of manual review for Legal users).
  * `EXPIRED` – The session was not submitted within 7 days of the `CreationDate` and no longer can be. Note however that the `HostedUrl` link remains accessible.
  * `OUT_OF_DATE` – The session is not valid because the user’s KYC/KYB verification status was [downgraded](/guides/users/verification/downgrade) by Mangopay.
</ResponseField>

## Webhooks

In all cases, the hosted KYC/KYB verification feature takes time for the user to complete.

You are strongly recommended to implement all 4 webhooks for IDV Sessions and rely on them in your integration.

Once you receive a [webhook notification](/webhooks), call [GET View an IDV Session](/api-reference/idv-sessions/view-idv-session) for more details.

The following [event types](/webhooks/event-types) are available:

* `IDENTITY_VERIFICATION_PENDING` – The IDV Session’s `Status` is `PENDING`. The `HostedUrl` link is valid for completion and must be submitted within 7 days. The session may or may not have been started.
* `IDENTITY_VERIFICATION_VALIDATED` – The IDV Session’s `Status` changed to `VALIDATED` and the User became KYC/KYB verified.
* `IDENTITY_VERIFICATION_FAILED` – The IDV Session’s `Status` changed to `REFUSED` and the User was not KYC/KYB verified. A new session is needed for them to retry.
* `IDENTITY_VERIFICATION_INCONCLUSIVE` – The IDV Session’s `Status` changed to `REVIEW` and the session is under manual review by Mangopay’s teams before an outcome can be given.
* `IDENTITY_VERIFICATION_OUTDATED` – The IDV Session’s `Status` changed to `OUT_OF_DATE` indicating that the user’s KYC/KYB verification status was downgraded. To regain KYC/KYB verified status, the user must complete a new IDV Session successfully.

Note that there is not yet a webhook notifying you when the session expires after 7 days from the `CreationDate`, so you need to track this on your side.

## Status and outcomes

The `Status` value of the IDV Session object indicates the outcome.

To see the outcomes applicable to each user type, see the flow guides:

* [Natural](/guides/users/verification/hosted/natural)
* [Soletrader](/guides/users/verification/hosted/soletrader)
* [Business](/guides/users/verification/hosted/business)
* [Organization](/guides/users/verification/hosted/organization)

### Automated validation

If all the checks could be validated automatically, then the `Status` becomes `VALIDATED`.

When the `VALIDATED` status is returned automatically:

* [Verified data](#verified-data) from the session is overwritten in the User object:
* The user’s KYC/KYB verification status is updated (user object’s `KYCLevel` becomes `REGULAR`)

### Automated refusal

If the `IDENTITY_DOCUMENT_VERIFICATION`, `IDV_NAME_MATCH_CHECK`, or `IDV_AGE_CHECK` check are refused automatically then the session is automatically refused and the `Status` becomes `REFUSED`.

When the `REFUSED` value is returned automatically:

* [Verified data](#verified-data) may be returned but no action is taken with it
* The user’s KYC/KYB verification status is not updated (user object’s `KYCLevel` remains `LIGHT`)
* The `Checks.CheckStatus` shows which checks were `REFUSED` and the `Checks.Reasons` shows the [refusal reasons](/guides/users/verification/hosted/refusals) (`Type` and preset `Value`)

### Manual review

Manual review is only possible for Legal users.

If the `BUSINESS_VERIFICATION` returned no match or a partial match or the `BUSINESS_INSIGHTS_MATCH` (Business) or `BUSINESS_NAME_CHECK` (Soletrader) was not validated automatically, then the session must be reviewed manually by Mangopay and the `Status` becomes `REVIEW`.

When the `REVIEW` status is returned:

* The `Checks.CheckStatus` shows which checks were `REFUSED` and triggered the manual review
* Automatically validated checks are returned, including [Verified data](#verified-data), but the user object data is only overwritten if the session is validated

### Validation after review

If the manual review is successful, then the status changes to `VALIDATED`.

When the `VALIDATED` status is returned following manual review:

* [Verified data](#verified-data) from the session is overwritten in the User object
* The user’s KYC/KYB verification status is updated (user object’s `KYCLevel` becomes `REGULAR`)
* The `Checks.CheckStatus` and `Checks.Reasons` are **not updated**, so they may still show as `REFUSED`

### Refusal after review

If the manual review is unsuccessful, then the status changes to `REFUSED`.

When the `REFUSED` status is returned following manual review:

* [Verified data](#verified-data) may be returned but no action is taken with it
* The user’s KYC/KYB verification status is not updated (user object’s `KYCLevel` remains `LIGHT`)
* The `Checks.CheckStatus` and `Checks.Reasons` are updated to provide the `Type` and a custom message in the `Value`

A refused session must be retried in full even if some of the `Checks` were successful. For example for businesses, if the session was refused due to the PSC data, registration proof or articles of association, then the entire session must be retried even if the `IDENTITY_DOCUMENT_VERIFICATION` check was validated.

### Downgrade

Finally, the `Status` may also change to `OUT_OF_DATE`, which indicates that the user’s KYC/KYB verification status was downgraded. The **user** object’s `KYCLevel` was changed from `REGULAR` to `LIGHT`. For more information about this mechanism, see [KYC/KYB downgrade](/guides/users/verification/downgrade).

In this case, you need to create another IDV Session object for the user to go through the verification process again.

## Verified data

The hosted KYC/KYB session gathers user data which is then verified as part of the process. This data, which is verified during automated checks, is returned in the session’s `Checks.Data`. You can retrieve it using the [GET View an IDV Session](/api-reference/idv-sessions/view-idv-session) endpoint.

These data points are overwritten if the session `Status` is `VALIDATED`, but the `Data` may be returned if the status is `REFUSED` or `REVIEW`.

As part of the `IDENTITY_DOCUMENT_VERIFICATION`, the data in the next table is extracted from the ID document. If this check fails, the session `Status` is `REFUSED` and no data is overwritten.

Note that in the case of a Business user, the data below is overwritten even if the individual who completed the session’s ID check is not the one previously entered in the `LegalRepresentative` of the user object.

<table>
  <thead>
    <tr>
      <th class="header">`Data.Type` value extracted from ID</th>
      <th class="header">User object property overwritten if `Status` is `VALIDATED`</th>
    </tr>
  </thead>

  <tbody>
    <tr><td class="table-content">`FIRST_NAME`</td><td class="table-content">`FirstName`</td></tr>
    <tr><td class="table-content">`LAST_NAME`</td><td class="table-content">`LastName`</td></tr>
    <tr><td class="table-content">`BIRTHDATE`</td><td class="table-content">`Birthday`</td></tr>
    <tr><td class="table-content">`LEGAL_REPRESENTATIVE_FIRST_NAME`</td><td class="table-content">`LegalRepresentative.FirstName`</td></tr>
    <tr><td class="table-content">`LEGAL_REPRESENTATIVE_LAST_NAME`</td><td class="table-content">`LegalRepresentative.LastName`</td></tr>
    <tr><td class="table-content">`LEGAL_REPRESENTATIVE_BIRTHDATE`</td><td class="table-content">`LegalRepresentative.Birthday`</td></tr>
  </tbody>
</table>

As part of the `BUSINESS_VERIFICATION`, the data in the next table is entered by the user and then validated against the national registry. If this check fails, then the session goes for manual review. If the session `Status` is ultimately `VALIDATED`, then the data entered is considered validated and overwritten in the user object. If the session outcome is `REFUSED`, no data is overwritten.

<table>
  <thead>
    <tr>
      <th class="header">`Data.Type` value entered by user</th>
      <th class="header">User object property overwritten if `Status` is `VALIDATED`</th>
    </tr>
  </thead>

  <tbody>
    <tr>
      <td class="table-content">`COMPANY_NAME`</td>
      <td class="table-content">`Name`</td>
    </tr>

    <tr>
      <td class="table-content">`COMPANY_NUMBER`</td>
      <td class="table-content">`CompanyNumber`</td>
    </tr>
  </tbody>
</table>

## Sending additional documents

The hosted solution allows the user to complete all the necessary steps to be verified, including the ID liveness check and, where relevant, declaring Persons of Significant Control (also known as beneficial owners).

However, in the event that additional documents are requested by Mangopay, these must be submitted via the API in the form of a legacy [KYC Document](/api-reference/kyc-documents/kyc-document-object) object.

There are two `Types` of object that you may need to use:

* `IDENTITY_PROOF` - For any additional ID documents requested
* `ADDRESS_PROOF` - For any other additional documents requested that aren't ID proofs (i.e. even if it's not an address proof either)

Note that for the `ADDRESS_PROOF` document, the `Status` will become `VALIDATED` automatically. Please contact Mangopay to request that the document be reviewed.

For more guidance on integrating these endpoints, see information about [document submission](/guides/users/verification/documents/submission) guide and [how to submit a KYC document](/guides/users/verification/documents/submission/how-to).

For platforms using the hosted experience, integration of the [UBO Declaration](/api-reference/ubo-declarations/ubo-declaration-object) endpoints is not necessary, as these individuals can be declared by the user through the frontend session.
