# Fourthline KYC

This guide describes the integration process of the Fourthline KYC method as a **stand-alone** solution, including key concepts, the mandatory information you must collect from your customers, and the necessary endpoints and webhooks you must integrate into your solution.

## Introduction

### Product overview

[Fourthline](https://fourthline.com/) is a semi-automated KYC for identifying your customers according to KYC guidelines. It combines taking a selfie, scanning an ID document, and collecting metadata, such as geolocation. Solaris offers this solution through mobile and web SDKs and a simple set of API calls. Additionally, you can integrate Fourthline as a standard KYC method or combine it with a QES (Qualified Electronic Signature) to enable your customers to securely sign contracts.

### Eligibility

You can use Fourthline as a KYC method for any of Solaris' products, including high-risk banking products, such as a full bank account. However, Fourthline **cannot be used** as a KYC method for customers in **Germany**.

Additionally, depending on the branch and your use case, it might be mandatory to combine Fourthline with a QES (Qualified Electronic Signature). The Solaris team will help you choose the KYC method suitable for your banking use case.

### User journey

Customers can identify themselves via Fourthline in three simple steps. The following steps explain the KYC flow the customer will go through with Fourthline:

**1. Data collection**

1. The customer enters the required personal data (name, address, mobile number, nationality, and birth date).
2. Solaris sends an SMS OTP to the customer's mobile number, and the customer must enter this OTP to verify their number.


**2. ID document scan**

The customer scans their ID document. During the process, Fourthline performs:

- Automatic data extraction from the machine-readable zone
- Verification of holograms and other security features
- Tampering and counterfeit detection
- Real-time feedback to the customer to improve photo quality


**3. Selfie**

The customer takes a selfie according to the instructions from Fourthline. During the process, Fourthline performs:

- Fraud detection and face checks with alert lists
- Real-time feedback to the customer to improve photo quality


**4. Qualified Electronic Signature (optional)** The customer reviews and approves any documents to be electronically signed by receiving and confirming a one-time password (OTP) via SMS. During the process:

- The customer reviews any documents to be signed.
- The customer requests an SMS OTP to be sent to their verified mobile number.
- The customer enters the SMS OTP to sign the relevant documents.
- The customer downloads or receives via email the signed documents.


## System prerequisites

Before starting the Fourthline identification process, you must implement the following requirements:

**1. Technical setup**

Set up your environment and get your authentication keys. For instructions, see the [Technical setup guide](/guides/get-started/technical-setup).

**2. Legal and compliance screens**

Build the necessary legal and compliance screens in your sign-up flow to collect your customers' consent to the necessary legal and compliance requirements. The [Legal and compliance screens guide](/guides/get-started/onboarding-requirements/1-legal-compliance-screens) explains how to create these screens and lists their mandatory contents.

Record the customer's consent on each screen as a UTC timestamp (e.g., `2019-01-01T00:00:00Z`). Pass each timestamp in its respective field to Solaris.

* Collect the customer's consent to Solaris' Terms and Conditions and store the timestamp in the `terms_conditions_signed_at` field.
* Collect the customer's consent to data processing and store the timestamp in the `data_terms_signed_at` field.


These fields belong to the `person` resource, which stores all customer data points.

## Webhooks

Solaris recommends subscribing to the following webhook events to better automate your processes. For detailed instructions on implementing Solaris webhooks, check the [webhooks documentation](/api-reference/webhooks/).

- [IDENTIFICATION](/api-reference/onboarding/webhooks/webhook-events/paths/identification/post)
- [PERSON_CHANGED](/api-reference/onboarding/webhooks/webhook-events/paths/person_changed/post)
- [PERSON_DELETED](/api-reference/onboarding/webhooks/webhook-events/paths/person_deleted/post)
- [PERSON_MOBILE_NUMBER_CREATED](/api-reference/onboarding/webhooks/webhook-events/paths/person_mobile_number_created/post)
- [PERSON_MOBILE_NUMBER_DELETED](/api-reference/onboarding/webhooks/webhook-events/paths/person_mobile_number_deleted/post)


## Integration overview

The following sequence diagram gives an overview of the integration flow for the Fourthline solution:


```mermaid
sequenceDiagram
    autonumber
    actor Customer
    box "Partner Integration" #FFFFFF
        participant FE as Frontend/App
        participant BE as Backend
    end
    box "Solaris Ecosystem" #F9F9F9
        participant Sol as Solaris
        participant FL as Fourthline
        participant QES as QES Provider
    end

    %% Phase 1: Registration
    rect rgb(242, 242, 242)
        note right of Customer: Step 1: Registration
        Customer->>FE: Provide mandatory data
        Customer->>FE: Accept Solaris T&Cs
        FE->>BE: Submit Data (w/ Timestamps)
        BE->>Sol: POST /persons (Create Person)
        Sol-->>BE: 201 Created (person_id)
        
        note right of Customer: Step 2: Mobile Verification
        BE->>Sol: POST /mobile_number
        Sol-->>BE: 201 Created
        BE->>Sol: POST /authorize
        Sol->>Customer: Send SMS OTP
        Customer->>FE: Enter OTP
        FE->>BE: Submit OTP
        BE->>Sol: POST /confirm
        Sol-->>BE: 200 OK (verified)
    end

    %% Phase 2: Identification Resource
    rect rgb(240, 248, 255)
        note right of Customer: Step 3: Create & Request ID
        BE->>Sol: POST /identifications
        Sol-->>BE: 201 Created (status: created)
        BE->>Sol: PATCH /request (Trigger Process)
        Sol-->>BE: 200 OK (status: pending)
    end

    %% Phase 3: Fourthline SDK
    rect rgb(255, 250, 240)
        note right of Customer: Step 4: Invoke SDK
        BE->>FE: Pass config
        FE->>FL: Initialize SDK
        Customer->>FL: Scan ID, Selfie, Location
        FL-->>FE: Return KYC Data (Zip/Payload)
        FE->>BE: Upload KYC Data
    end

    %% Phase 4: Submission
    rect rgb(240, 255, 240)
        note right of Customer: Step 5: Upload Data
        BE->>Sol: POST /zip (Upload KYC Data)
        Sol-->>BE: 201 Created
    end

    %% Phase 5: QES (Optional)
    rect rgb(255, 240, 245)
        note right of Customer: Step 6: QES (Optional)
        Sol-)BE: Webhook: IDENTIFICATION (authorization_required)
        
        note right of Customer: Document Review & T&Cs
        BE->>FE: Prompt Namirial T&Cs
        Customer->>FE: Accept T&Cs
        BE->>Customer: Send Documents (Email/App)
        Customer->>FE: Review & Approve Documents

        note right of Customer: Signing
        Customer->>FE: Request OTP
        FE->>BE: Trigger QES
        BE->>Sol: PATCH /authorize
        Sol->>FL: Start QES Flow
        FL->>QES: Trigger SMS
        QES->>Customer: Send SMS OTP
        
        Sol-)BE: Webhook: IDENTIFICATION (confirmation_required)
        
        Customer->>FE: Enter OTP
        FE->>BE: Submit Token
        BE->>Sol: PATCH /confirm (token)
        Sol-->>BE: 200 OK (confirmed)
        
        Sol-)BE: Webhook: IDENTIFICATION (successful)
        
        BE->>Sol: GET /identifications/{id}
        Sol-->>BE: 200 OK (Signed Documents)
    end
```

You can integrate Solaris' Fourthline product by completing the 7 steps explained in the following sections. Here's an overview of these steps:

**Customer registration**

In this phase of the integration process, you must collect all the relevant data points from your customer and create the required resources on Solaris' side by doing the following:

1. Collect the mandatory customer data and consent to the legal and regulatory requirements in your sign-up flow, and create a person resource for your customer by completing [Step 1](#step-1-collect-customer-data-and-create-person-resource).
2. Create and verify the customer's mobile number by completing [Step 2](#step-2-create-and-verify-mobile-number).


**Customer identification resource**

In this phase of the integration process, you must create and request identification with Fourthline for the customer by doing the following:

1. Create an identification resource for the customer on Solaris' side using [POST Create identification](#post-create-identification).
2. Request an identification for the customer using [PATCH Request an identification](#patch-request-person-identification).


**Fourthline identification flow** In this phase, you must integrate Fourthline SDK in your solution and set up the identification flow by doing the following:

1. [Integrate Fourthline SDK](#1-integrate-fourthline-sdk).
2. [Set up and initialize the identification flow](#2-set-fourthline-flow-parameters).
3. [Initiate the Fourthline identification flow on the customer's device](#3-initiate-fourthline-identification-flow).
4. [Store the identification output](#4-fourthline-flow-output).


**Identification data upload**

1. After the customer successfully completes the identification flow with Fourthline, you must upload the collected KYC data as a `.zip` file to Solaris by completing [Step 5](#step-5-upload-the-kyc-data).


**Qualified Electronic Signature** (optional)

In this phase, if you need to collect a QES from the customer, you must do the following (see [Step 6](#step-6-request-qualified-electronic-signature-optional)):

1. Prompt the customer to accept the terms and conditions of the QES provider (Namirial).
2. Send all documents to be signed to the customer via app or email prior to the QES process.
3. Request an SMS OTP to be sent to the customer's mobile number using [PATCH Start QES process](#patch-start-qes-process).
4. After the customer enters the SMS OTP on your app, confirm the QES process using [PATCH Confirm QES](#patch-confirm-qes).


The QES step may be mandatory for customer identification depending on jurisdictions and your identification use case.

**Identification outcome**

Track status changes of the identification resource in your backend to see the results of the flow by doing the following:

1. Register a webhook listener for `IDENTIFICATION` event to be informed about any identification status changes.
2. Integrate all the relevant endpoints in [Step 7](#step-7-check-the-identification-status-and-outcome) to retrieve the identification outcome.
3. Check the results of the identification to determine next steps:


- If the identification is successful, continue with the onboarding of your customer.
- If the identification has failed, check the failure reason and type. Depending on the failure reason, you can either allow the customer to retry the identification flow (e.g., advise the customer use better lighting if the identification failed due to poor image quality), or abort the onboarding process for the customer in case of suspected fraud.


You can find detailed descriptions of these steps and their related endpoints in the following sections.

If you want to use Fourthline as the KYC method in another integration flow of any of Solaris' products (e.g., there's an existing `person` resource and verified mobile number for the customer), you can jump to [Step 3](#step-3-create-the-identification-resource).

## Step 1: Collect customer data and create person resource

In this step, you must collect the mandatory data points from the customer in your sign-up flow, including all the timestamps of the customer's consent to the [legal and compliance screens](#system-prerequisites). Afterward, pass all the data points to Solaris by creating a person resource.

**API reference**

For a complete list of endpoints, properties, and examples related to the `person` resource, visit the following links:

- [Person resource API reference](/api-reference/onboarding/persons/#tag/Persons)
  - [POST Create person](/api-reference/onboarding/persons/#tag/Persons/paths/~1v1~1persons/post)
  - [GET Retrieve a person](/api-reference/onboarding/persons/#tag/Persons/paths/~1v1~1persons~1%7Bid%7D/get)
  - [PATCH Update person](/api-reference/onboarding/persons/#tag/Persons/paths/~1v1~1persons~1%7Bid%7D/patch)


**Related webhook events**

- [`PERSON_CHANGED`](/api-reference/onboarding/webhooks/webhook-events/paths/person_changed/post)
- [`PERSON_DELETED`](/api-reference/onboarding/webhooks/webhook-events/paths/person_deleted/post)


Important points about data collection
- Review the special requirements in the [Onboarding requirements guide](/guides/get-started/onboarding-requirements/2-data-collection/#important-considerations-for-data-collection).
- Submit information exactly as it appears in official documents.
- **Sandbox Testing:** Ensure that each person you create has unique values for `first_name`, `last_name`, `birth_city`, and `birth_date`. If you create over 1000 identical person resources, the API will return a `400` error.
- **Privacy:** Do not use real personal data when testing in Sandbox.


#### POST Create person

This endpoint creates a person resource for your customer. You must collect the mandatory data points from your customer in the sign-up flow and pass them to Solaris in the request body of this endpoint.

- `salutation`
- `first_name` (including all middle names as printed on the ID document)
- `last_name` (including all name parts as printed on the ID document)
- `birth_date`
- `nationality` (Use [ISO 3166-1 alpha-2 codes](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2))
- `mobile_number`
- `address` (Street, Number, City, Post Code, Country, State)
- `data_terms_signed_at` (UTC timestamp)
- `terms_conditions_signed_at` (UTC timestamp)


**Request URL**


```shell
POST /v1/persons
```

**Request example**


```json
{
  "salutation": "Mr",
  "first_name": "Marc",
  "last_name": "O'Polo",
  "birth_date": "1999-01-01",
  "nationality": "DE",
  "mobile_number": "+4917612345678",
  "address": {
    "line_1": "Solaris street",
    "line_2": "1",
    "postal_code": "10119",
    "city": "Berlin",
    "country": "DE"
  },
  "tax_information": {
    "tax_assessment_country": "DE"
  },
  "terms_conditions_signed_at": "2021-01-01T00:00:00Z",
  "data_terms_signed_at": "2021-01-01T00:00:00Z"
}
```

**Response**

The API returns a person object with a unique ID for the person (i.e., the `id`). You will need this `id` to append the person resource with additional information in the remaining steps of this guide.


```json
{
  "id": "dc1a6812a14f6cc338cd084208535bcdcper",
  "salutation": "Mr",
  "first_name": "Marc",
  "last_name": "O'Polo",
  "birth_date": "1999-01-01",
  "nationality": "DE",
  "mobile_number": "+4917612345678",
  ...
}
```

[Click here to view the full API reference](/api-reference/onboarding/persons/#tag/Persons/paths/~1v1~1persons/post)

#### PATCH Update person

This endpoint updates one or more properties on a `person` resource. You can only update the following properties using this endpoint:

- `title`
- `salutation`
- `address` (`line_1`, `line_2`, `postal_code`, `city`,  `state`, `country`)
- `contact_address` (`line_1`, `line_2`, `postal_code`, `city`,  `state`, `country`)
- `employment_status`
- `job_title`
- `email`
- `tax_information` (`tax_assessment`, `marital_status`)
- `fatca_relevant`
- `fatca_crs_confirmed_at`
- `business_purpose`
- `industry`
- `industry_key`
- `own_economic_interest_signed_at`
- `aml_confirmed_on` (only with today or tomorrow's date)
- `expected_monthly_revenue_cents`
- `vat_number`
- `website_social_media`
- `business_trading_name`
- `nace_code`
- `business_address_line_1`
- `business_address_line_2`
- `business_postal_code`
- `business_city`
- `business_country`
- `annual_income_range`
- `data_terms_signed_at`
- `branch`
- `birth_province`
- `birth_post_code`
- `socioprofessional_category`
- `purpose_of_account_opening`
- `main_income_source`
- `work_country`
- `work_province`
- `self_declared_as_pep`
- `international_operativity_expectation`
- `registration_number`


Important
**Restricted Updates:**

* Fields not mentioned in this list can only be updated via Customer Support.


**Freelancer & Self-Employed Requirements (B2C):**

* If a customer changes their `employment_status` to `FREELANCER` or `SELF_EMPLOYED`, you must include **one** of the following in the request to avoid an error:
  1. The customer's `nace_code` (Recommended for data quality).
  2. Set `industry` and `industry_key` to `null`.


**Request URL**


```shell
PATCH /v1/persons/{id}
```

**Request example**

* [API Reference: Update person](/api-reference/onboarding/persons/#tag/Persons/paths/~1v1~1persons~1%7Bid%7D/patch)


## Step 2: Create and verify mobile number

In this step, you must collect the customer's mobile number in your sign-up flow and then create a mobile number resource and verify it by sending an SMS OTP to the customer's mobile number. Afterward, the customer enters the received OTP in your frontend to verify their number.

### Mobile number resource

Creating and verifying a mobile number for your customer is a crucial step in the customer onboarding process. With a verified mobile number, customers can use SMS OTPs to complete two-factor authentication (2FA) challenges, which is a requirement for Strong Customer Authentication (SCA).

Info
In some use cases (e.g., stand-alone integrations), the mobile number is verified during the identification process.

### API reference

Visit the following link to find all the endpoints related to the mobile number resource, including related properties and examples.

- [Mobile number resource API reference](/api-reference/onboarding/persons/#tag/Person-mobile-numbers)


**Related webhook events**

- [PERSON_MOBILE_NUMBER_CREATED](/api-reference/onboarding/webhooks/webhook-events/paths/person_mobile_number_created/post)
- [PERSON_MOBILE_NUMBER_DELETED](/api-reference/onboarding/webhooks/webhook-events/paths/person_mobile_number_deleted/post)


Testing static values
To test the following endpoints on Sandbox, you can use the following static values:

- Mobile number: `+15550101`
- SMS OTP: `212212`


#### POST Create mobile number

Collect the customer's mobile number and pass it to Solaris using the following API call. You must include the customer's `person_id` in the request URL.

**Request URL**


```shell
POST /v1/persons/{person_id}/mobile_number
```

**Request example**


```json
{
  "number": "+15550101"
}
```

**Response example**

The API returns a `mobile_number` resource with a unique `id` and attaches it to the `person` resource.


```json
{
    "id": "91e4d939d781b8eb30d1ee86809761c2cmno",
    "number": "+15550101",
    "verified": false
}
```

[Click here to view the full API reference.](/api-reference/onboarding/persons/#tag/Person-mobile-numbers/paths/~1v1~1persons~1%7Bperson_id%7D~1mobile_number/post)

#### POST Authorize mobile number

Use the following endpoint to verify the ownership of the provided mobile phone number. The endpoint initiates a one-time-password (OTP) flow: Solaris sends a six-digit OTP to the customer's number, and then they must enter it in your UI.

**Request URL**


```shell
POST /v1/persons/{person_id}/mobile_number/authorize
```

**Request example**


```json
{
  "number": "+15550101"
}
```

**Response example**


```json
{
    "id": "91e4d939d781b8eb30d1ee86809761c2cmno",
    "number": "+15550101",
    "verified": false
}
```

[Click here to view the full API reference.](/api-reference/onboarding/persons/#tag/Person-mobile-numbers/paths/~1v1~1persons~1%7Bperson_id%7D~1mobile_number~1authorize/post).

#### POST Confirm mobile number

Use this endpoint to submit the SMS OTP the customer received on their mobile number to finalize the mobile number authorization process. You must add the customer's `number` and `token` (i.e., the SMS OTP) in the request body. Afterward, the mobile number will be `verified` and can be used in the context of Strong Customer Authentication (SCA).

**Request URL**


```shell
POST /v1/persons/{person_id}/mobile_number/confirm
```

**Request example**


```json
{
  "number": "+15550101",
  "token": "212212"
}
```

**Response example**


```json
{
    "id": "91e4d939d781b8eb30d1ee86809761c2cmno",
    "number": "+15550101",
    "verified": true
}
```

[Click here to view the full API reference.](/api-reference/onboarding/persons/#tag/Person-mobile-numbers/paths/~1v1~1persons~1%7Bperson_id%7D~1mobile_number~1confirm/post)

For more information about how to manage mobile numbers (e.g., changing or deleting a number), check the related [mobile number management guide](/guides/digital-banking/mobile-number-management).

## Step 3: Create the identification resource

In this step, you must create an identification resource for your customer on Solaris' side.

**API reference**

Visit the following link to find all the endpoints related to the different customer identification methods (KYC), including related properties and examples.

- [Customer identification (KYC) API reference](/api-reference/onboarding/persons/#tag/Persons)


The previous link includes all endpoints for different KYC methods. This section includes the relevant endpoints required for identification with Fourthline.

### POST Create identification

This endpoint creates an identification resource for the person specified in the request URL. Specify the following properties in the request body:

- `method`: The identification method to use. If you want to use the standard Fourthline KYC flow, set the value of this field to `fourthline`. If you want to use Fourthline combined with a QES, set the value to `fourthline_signing`.


This endpoint does not send a request to the identification provider to start the identification process. The actual identification process is triggered when you call [PATCH Request person identification](#patch-request-person-identification).

**Request example**


```json
POST /v1/persons/{person_id}/identifications
{
  "method": "fourthline"
}
```

**Response example**

The API call returns an identification object with a unique `id`, the `identification_id`, as well as the identification `status`, set initially to `created`.

For a list of possible values for the field `status` and their descriptions, check the [appendix](#identification-status).


```json
{
    "id": "a7a57dadfcc83117b5c3b72f4113be25cidt",
    "reference": null,
    "url": null,
    "status": "created",
    "completed_at": null,
    "method": "fourthline",
    "proof_of_address_type": null,
    "proof_of_address_issued_at": null,
    "iban": null,
    "terms_and_conditions_signed_at": null,
    "authorization_expires_at": null,
    "confirmation_expires_at": null
}
```

[Click here to view the full API reference](/api-reference/identity/identifications/#tag/Person-identifications/paths/~1v1~1persons~1%7Bperson_id%7D~1identifications/post).

### GET List supported documents for a person identification

Prior to starting the identification process, you can fetch the supported documents to share it with the customer beforehand.

This endpoint returns an array of document types that a customer may use to identify themselves along with a list of allowed issuing countries. The `issuing_countries` are provided as ISO country codes (ISO-3166-1 alpha 2). If the customer does not provide a supported document type in the identification process, then their identification will eventually fail.

**Request URL**


```shell
GET /v1/persons/{person_id}/identifications/{id}/supported_documents
```

**Response example**


```json
[
  {
    "type": "Passport",
    "issuing_countries": [
      "ES"
    ]
  }
]
```

[Click here to view the full API reference](/api-reference/identity/identifications/#tag/Person-identifications/paths/~1v1~1persons~1%7Bperson_id%7D~1identifications~1%7Bid%7D~1supported_documents/get)

### PATCH Request person identification

This endpoint requests the identification for the specific customer.

The status of the identification will change to `pending` after calling this endpoint. Once the identification process finishes, you will receive a notification from the `IDENTIFICATION` webhook and the status will change to `successful` or `failed` depending on the outcome.

**Request URL**


```shell
PATCH /v1/persons/{person_id}/identifications/{id}/request
```

**Response example**

The API call returns the identification object with the status `pending`.


```json
{
    "id": "a7a57dadfcc83117b5c3b72f4113be25cidt",
    "reference": null,
    "url": null,
    "status": "pending",
    "completed_at": null,
    "method": "fourthline",
    "proof_of_address_type": null,
    "proof_of_address_issued_at": null,
    "iban": null,
    "terms_and_conditions_signed_at": null,
    "authorization_expires_at": null,
    "confirmation_expires_at": null,
    "estimated_waiting_time": null
}
```

[Click here to view the full API reference](/api-reference/identity/identifications/#tag/Person-identifications/paths/~1v1~1persons~1%7Bperson_id%7D~1identifications~1%7Bid%7D~1request/patch).

## Step 4: Invoke Fourthline SDK

In this step, you must integrate Fourthline SDK into your environment and trigger the identification flow on the customer's device to collect and process the KYC data from the customer.

### 1. Integrate Fourthline SDK

Fourthline offers native SDKs for iOS and Android. For step-by-step instructions on how to integrate the SDKs, refer to [Fourthline's documentation](https://dx.fourthline.com/docs/mobile-sdk-):

- [iOS](https://github.com/Fourthline-com/FourthlineSDK-iOS)
- [Android](https://github.com/Fourthline-com/FourthlineSDK-Android)


You need specific credentials and set-up to access Fourthline documentation and the Github repository. The Solaris team will share these credentials with you.

### 2. Set Fourthline flow parameters

After integrating the Fourthline SDK, you must create a `KycInfo` object, which will be populated by the KYC data during the identification flow.

For more information about the `KycInfo` object, check the relevant documentation:

- [iOS](https://github.com/Fourthline-com/FourthlineSDK-iOS#kycinfo)
- [Android](https://github.com/Fourthline-com/FourthlineSDK-Android#kycinfo)


**How to create the `KycInfo` object?**

When creating the `KycInfo` object, you must add the following input parameters:

- `<PersonId>` = The ID of the person resource you created for the customer on Solaris' side in [Step 1](#step-1-collect-customer-data-and-create-person-resource).
- `<ProviderName>` = Your dedicated static provider name, which the Solaris team will share with you.



```swift iOS (Swift)
  let provider = Provider()
  provider.clientNumber = "<PersonId>"
  provider.name = "<ProviderName>"

  let kycInfo = KYCInfo()
  kycInfo.provider = provider
  
  // Initiate FL KYC flow with kycInfo object
  ...
```


```kotlin Android (Kotlin)
  val provider = Provider()
  provider.clientNumber = "<PersonId>"
  provider.name = "<ProviderName>"

  val kycInfo = KycInfo()
  kycInfo.provider = provider
  
  // Initiate FL KYC flow with kycInfo object
  ...
```

### 3. Initiate Fourthline identification flow

Now, you must initiate and display the Fourthline identification flow to the customer.

Fourthline provides two options for the identification flow depending on your integration needs:

- ["Drop-in" solution](https://dx.fourthline.com/docs/drop-in-solution): A ready-made UI that is easy to integrate and provides a complete user experience for the customer.
- ["White-label SDK"](https://dx.fourthline.com/docs/white-label): A customizable set of modules, which you can fully design and define each part of the user experience.


Solaris recommends using Fourthline's "Drop-in" solution as a complete and consistent integration. However, we also support custom Fourthline integrations. This guide explains the process with the Drop-in solution.

#### Add the Proof of Address document

In addition to the data and documents collected during Fourthline's identification flow, you must submit a secondary document that provides proof of the customer's address with the KYC data.

You can submit this Proof of Address (PoA) document in one of two ways:

1. **Device-side:** If the PoA document is available on the customer's device, you can add it to the `KYCInfo` object described in the previous section. The code samples below show how to add the PoA document from the customer's device:



```swift iOS (Swift)
  // ...
  var kycInfo = ...
    
  // Create DocumentAttachment containing the actual PoA document (image)
  let proofOfAddressImage = DocumentAttachment()
  proofOfAddressImage.image = UIImage(...)
  proofOfAddressImage.fileSide = .front
  proofOfAddressImage.isAngled = false
     
  // Create SecondaryDocument with PoA image
  let proofOfAddressDocument = SecondaryDocument()
  proofOfAddressDocument.type = .proofOfAddress
  proofOfAddressDocument.images = [proofOfAddressImage]
   
  // Add PoA document to kycInfo
  kycInfo.secondaryDocuments = [proofOfAddressDocument]
```


```kotlin Android (Kotlin)
// ...
    val kycInfo = …
    
    // Create Attachment Document containing the actual PoA document (image as Bitmap)
    val proofOfAddressImage: Bitmap = …
    val proofOfAddressAttachment = Attachment.Document(image = proofOfAddressImage, fileSide = DocumentFileSide.FRONT, isAngled = false)
    
    // Create SecondaryDocument with PoA image attachment
    val proofOfAddressDocument = SecondaryDocument(type = DocumentType.PROOF_OF_ADDRESS, images = listOf(proofOfAddressAttachment))
    
    // Add PoA document to kycInfo
    kycInfo.secondaryDocuments = listOf(proofOfAddressDocument)
```

1. **Backend:** If the customer's PoA document is available on your backend, you can submit it by modifying the KYC XML file received from Fourthline and the .zip archive. To do so, add an `IdentificationDocument` node to the `Documents` list with its `DocumentType` set to "Proof of Residence".



```xml
  ...
  <Documents>

    <IdentificationDocument>
      ...
    </IdentificationDocument>
    ...
    <IdentificationDocument>
      <DocumentType>Proof of Residence</DocumentType>
      <Files>
        <File>
          <FileLocation>Documents\2CE74...0D73.jpg</FileLocation>
          <Side>Front</Side>
          <FileType>JPG</FileType>
        </File>
      </Files>
    </IdentificationDocument>

  </Documents>
```

Please note that you must zip the set of KYC files again prior to the next step. Make sure that no additional files are added during the zipping process.

For more information, please refer to Fourthline's online documentation regarding [KYC file structure](https://dx.fourthline.com/reference/zip-file-structure) and the [KYC XML file format](https://dx.fourthline.com/reference/xml-file-format-1).

#### Build the data source

Now, you must create the Fourthline "data source", which will be used to store the identification data. Use the previously retrieved information of [supported identification documents](#get-list-supported-documents-for-a-person-identification) to build the "data source". However, please note that the data structure received from the Solaris API can not be used directly as input for the Fourthline data source as it needs to be slightly transformed.

For instructions on how to build the "data source", check the relevant documentation:

- [iOS](https://github.com/Fourthline-com/FourthlineSDK-iOS#creating-the-data-source)
- [Android](https://github.com/Fourthline-com/FourthlineSDK-Android#creating-the-data-source)


#### Initiate Fourthline flow

Configure Fourthline's identification flow to collect the following information from the customer:

- Scanned ID document (`documentFlow`)
- Selfie (`selfieFlow`)
- Device location data (`locationFlow`)


See the below examples on how to configure and initiate Fourthline's Drop-in flow to retrieve this data.


```swift iOS (Swift)
var kycInfo = ... // kycInfo previously set up
var dataSource = ... // dataSource previously set up

Orca.builder
  .withCustomFlow()
  .addLocationFlow()
  .addDocumentFlow()
  .addSelfieFlow()
  .noMoreFlows()
  .addDataSource(dataSource)
  .addKycInfo(info)
  .present { completionReason in
    switch completionReason {
      case .completed(let kycInfo):
        // Process flow output
        // ...
      // ...
  }
```


```kotlin Android (Kotlin)
val kycInfo: KycInfo // kycInfo previously set up
val dataSource: DataSource // dataSource previously set up

Orca.Builder(requireContext())
    .withCustomFlow()
    .addLocationFlow()
    .addDocumentFlow()
    .addSelfieFlow()
    .noMoreFlows()
    .addDataSource(dataSource)
    .present { finishReason ->
      if (finishReason is OrcaFinishReason.Completed) {
        // Process flow output
        // ...
      }
      // ...
    }
```

### 4. Fourthline flow output

After the customer has completed the identification flow, you must create a .zip file containing the collected KYC data on the customer's device and upload it to your backend.

For instructions on how to create the .zip file, check the relevant documentation:

- [iOS](https://github.com/Fourthline-com/FourthlineSDK-iOS#zipper)
- [Android](https://github.com/Fourthline-com/FourthlineSDK-Android#zipper)


## Step 5: Upload the KYC data

After the customer completes the identification process via Fourthline, you must upload the .zip file containing the identification data to Solaris.

### POST Upload zip file

This endpoint uploads a .zip file containing the identification data to the person identification specified in the request URL. The identification must have already been completed.

**How to create the zip file?** If you intend to construct the Fourthline KYC data file within your system instead of relying on the provided Fourthline capabilities, please consider the following XML conventions when creating the .zip file:

- `Provider`: Solaris' identifier on Fourthline.
- `ClientNumberProvider`: The person ID of the customer on Solaris' system.
- `ModifiedDateTime`: Always select the current date. Must not be older than 7 days.
- `DocumentNumber` = Must be unique. It's not possible to successfully identify with the same document number twice.


This also applies when creating KYC data files manually during testing.

**Request example**


```shell
POST /v1/persons/{person_id}/identifications/{id}/zip
document=<file handle>
```

**Response example**


```json
201 Created
{
  "id": "ec59766a28316783c6aab1004c43b640cdoc",
  "name": "RackMultipart20220518-8-12uqxum.zip",
  "content_type": "application/zip",
  "document_type": "OTHER",
  "size": 35349788,
  "customer_accessible": false,
  "created_at": "2022-05-18T15:15:27.000Z",
  "partner_accessible": true
}
```

[Click here to view the full API reference](/api-reference/identity/identifications/#tag/Person-identifications/paths/~1v1~1persons~1%7Bperson_id%7D~1identifications~1%7Bid%7D~1zip/post)

## Step 6: Request Qualified Electronic Signature (optional)

In this step, you will initiate a QES flow to collect your customer's Qualified Electronic Signature on the relevant contracts and documents. The contracts could be a simple KYC report or contracts related to the product the customer is being identified for, such as a loan contract. Please note the following:

- You must first show a screen to the customer to explain the QES process.
- The customer must be able to review the documents before the QES process starts.
- After the customer reviews the documents, they must request an SMS OTP to sign the documents.
- The customer will receive an SMS OTP on their verified mobile number, which they must enter in your app.
- After successful signing, you must send the signed documents to your customer via email or enable them to download the documents on your app.


The step could be optional depending on the use case and the branch. However, please note that QES is **mandatory** for onboarding customers in **Italy** and **France**.

### POST Upload QES document

Before initiating the QES flow, you must upload each document that requires a signature by calling the [POST Create a document for a person](/api-reference/onboarding/persons/#tag/Person-documents/paths/~1v1~1persons~1%7Bperson_id%7D~1documents/post) endpoint. In each request, set the value of `document_type` to `QES_DOCUMENT`.

**Request URL:**


```
POST /v1/persons/{person_id}/documents
```

**Example request:**


```
curl -i -X POST \
  '[https://api.solaris-sandbox.de/v1/persons/](https://api.solaris-sandbox.de/v1/persons/){person_id}/documents' \
  -H 'Content-Type: multipart/form-data' \
  -F file=id_photo.png \
  -F document_type=QES_DOCUMENT
```

[Click here to view the full API reference.](/api-reference/onboarding/persons/#tag/Person-documents/paths/~1v1~1persons~1%7Bperson_id%7D~1documents/post)

### PATCH Start QES process

This method begins the QES process for a person identification via Fourthline. When called, it prompts Fourthline via their QES provider to send an SMS OTP to the registered mobile phone number of the customer.

The OTP expires after five minutes. During this five-minute window, any newly requested OTPs will not be valid. Therefore, Solaris recommends waiting five minutes before reissuing an OTP.

**Request example**


```shell
PATCH /v1/persons/{person_id}/identifications/{id}/authorize
```

**Response example**

The customer must enter the OTP within the validity period. The status of the identification changes to `confirmation_required` until you confirm the QES.


```json
{
    "id": "a7a57dadfcc83117b5c3b72f4113be25cidt",
    "reference": null,
    "url": null,
    "status": "confirmation_required",
    "completed_at": null,
    "method": "fourthline",
    "proof_of_address_type": null,
    "proof_of_address_issued_at": null,
    "iban": null,
    "terms_and_conditions_signed_at": "2020-07-07T11:36:29.000Z",
    "authorization_expires_at": "2022-08-11T08:38:21.000Z",
    "confirmation_expires_at": "2022-08-11T08:37:23.000Z",
    "current_reference_token": "1234-5678",
    "estimated_waiting_time": null
}
```

[Click here to view the full API reference](/api-reference/identity/identifications/#tag/Person-identifications/paths/~1v1~1persons~1%7Bperson_id%7D~1identifications~1%7Bid%7D~1authorize/patch)

### PATCH Confirm QES

After the customer enters the SMS OTP, use this endpoint to confirm the QES. Call this endpoint when the person identification reaches the status `confirmation_required`.

**Request example**


```json
PATCH /v1/persons/{person_id}/identifications/{id}/confirm
{
    "token": "1234"
}
```

**Response example**


```json
{
    "id": "a7a57dadfcc83117b5c3b72f4113be25cidt",
    "reference": null,
    "url": null,,
    "status": "confirmed",
    "completed_at": null,
    "method": "fourthline",
    "proof_of_address_type": null,
    "proof_of_address_issued_at": null,
    "iban": null,
    "terms_and_conditions_signed_at": "2020-07-07T11:36:29.000Z",
    "authorization_expires_at": "2022-08-11T08:38:21.000Z",
    "confirmation_expires_at": "2022-08-11T08:37:23.000Z",
    "current_reference_token": "1234-5678"
}
```

[Click here to view the full API reference](/api-reference/identity/identifications/#tag/Person-identifications/paths/~1v1~1persons~1%7Bperson_id%7D~1identifications~1%7Bid%7D~1confirm/patch).

## Step 7: Check the identification status and outcome

Make sure you subscribe to the webhook event [IDENTIFICATION](/api-reference/onboarding/webhooks/webhook-events/paths/identification/post) to receive notifications whenever the status of an identification changes.

You can use the following endpoint to retrieve the status of the identification:

### GET Retrieve person identification

This endpoint returns a person identification.

To download any of the documents submitted during the identification process, you can use the document's unique `id` and download the files using the [document resource endpoints](/api-reference/onboarding/persons/#tag/Person-documents).

**Request example**


```json
GET /v1/persons/{person_id}/identifications/{id}
```

**Response example (successful identification)**

The following example shows a successfully completed Fourthline QES identification:


```json
{
    "id": "a7a57dadfcc83117b5c3b72f4113be25cidt",
    "reference": null,
    "url": null,
    "status": "successful",
    "completed_at": "2022-08-11T08:29:43.000Z",
    "method": "fourthline_signing",
    "proof_of_address_type": null,
    "proof_of_address_issued_at": null,
    "address": null,
    "documents": [
        {
            "id": "a6585ea2b053a69fb705a0eb963084cfcdoc",
            "name": "a7a57dadfcc83117b5c3b72f4113be25cidt_prepared_for_signing_kyc_report.pdf",
            "content_type": "application/pdf",
            "document_type": "QES_DOCUMENT",
            "size": 88139,
            "customer_accessible": false,
            "created_at": "2022-08-11T08:25:11.000Z"
        },
        {
            "id": "4d1aa91e091e375e30e94de4ab1cf0f4cdoc",
            "name": "SIGNED_a7a57dadfcc83117b5c3b72f4113be25cidt_prepared_for_signing_kyc_report.pdf",
            "content_type": "application/pdf",
            "document_type": "SIGNED_QES_DOCUMENT",
            "size": 88139,
            "customer_accessible": false,
            "created_at": "2022-08-11T08:29:43.000Z"
        }
    ],
    "iban": null,
    "terms_and_conditions_signed_at": null,
    "authorization_expires_at": null,
    "confirmation_expires_at": null,
    "current_reference_token": null
}
```

**Response example (failed identification)**

The following example shows a failed Fourthline QES identification:


```json
{
    "id": "7fb9659e1102d83983ce1f003bf78856cidt",
    "reference": "253029ae-a95b-493a-b420-b16d035a5126",
    "url": null,
    "status": "failed",
    "completed_at": "2022-08-30T11:28:09.000Z",
    "method": "fourthline",
    "proof_of_address_type": null,
    "proof_of_address_issued_at": null,
    "address": null,
    "failure_reason": "inconsistent_data",
    "iban": null,
    "terms_and_conditions_signed_at": null,
    "authorization_expires_at": null,
    "confirmation_expires_at": null,
    "provider_status_code": "3101"
}
```

[Click here to view the full API reference](/api-reference/identity/identifications/#tag/Person-identifications/paths/~1v1~1persons~1%7Bperson_id%7D~1identifications~1%7Bid%7D/get).

Refer to the [full list of Fourthline's verification status codes](https://dx.fourthline.com/reference/verification-status) to understand the failure reasons and how to proceed in each case.

### POST Whitelist a person identification

Fourthline has a duplication check that prevents customers from identifying several times for the same partner. This endpoint enables you to whitelist a person identification so that the customer can identify again for you. However, please note the following restrictions and use cases for this endpoint:

- You can only use this endpoint if a person has been previously identified successfully for one of your services with Fourthline and there's a need to identify again. For example, a customer has been previously onboarded for one of your services and then terminated the business relationship and now wishes to become your customer again. In this case, you can use this endpoint to whitelist the person before a new identification can take place.
- However, you cannot use this endpoint to whitelist a failed identification.
- This endpoint must be called while the identification resource is in status `pending` or `processed`.


**Request URL**


```shell
POST /v1/persons/{person_id}/identifications/{id}/whitelist
```

[Click here to view the full API reference](/api-reference/identity/identifications/#tag/Person-identifications/paths/~1v1~1persons~1%7Bperson_id%7D~1identifications~1%7Bid%7D~1whitelist/post).

## Testing

You can simulate different outcomes of the Fourthline verification when testing on Sandbox environment. Use the following endpoint to provide a valid Fourthline verification status code as the `provider_status_code` in the request body. Please note that the following prerequisites before calling this endpoint:

- You must submit a valid KYC zip file as explained in [Step 5](#step-5-upload-the-kyc-data).
- The status of Solaris identification resource must be `processed`.


Examples:

- `10`: Verification successful (low risk)
- `3202`: Verification failed (blurry snapshot of ID document)
- `5100`: Verification failed (ID tampering detected)


For a list of all status codes available for testing, check the [appendix](#appendix-ii-fourthline-status-codes-for-testing).

### POST Update Fourthline identification status

**Request URL**


```json
POST /v1/persons/{person_id}/identifications/{id}/identify_with_status
{
    "provider_status_code": "10"
}
```

[Click here to view the full API reference](/api-reference/identity/identifications/#tag/Person-identifications/paths/~1v1~1persons~1%7Bperson_id%7D~1identifications~1%7Bid%7D~1identify_with_status/post).

### POST Assign outcome of a Fourthline identification

This endpoint sets the outcome of a Fourthline identification once it reaches a specified status. When you call this endpoint, it forwards the received payload to Fourthline's "Register a Verification Outcome" endpoint.

For a full description and specification of the request parameters see [Fourthline's online documentation](https://dx.fourthline.com/password?redirect=/reference/assign-verification-outcome-v2). (password-protected)

[Click here to view the full API reference](/api-reference/identity/identifications/#tag/Person-identifications/paths/~1v1~1persons~1%7Bperson_id%7D~1identifications~1%7Bid%7D~1register_verification_outcome/post).

## What's next?

Congratulations! You've successfully integrated Solaris' Fourthline solution.

Check the following appendices section for additional information on enums and testing data.

For an overview of other KYC methods, check the [customer KYC products overview](/guides/kyc/).

### Useful resources

Check the following links for additional related guides and API reference documentation:

- [Customer identification (KYC) API reference](/api-reference/onboarding/persons/#tag/Persons)
- [Person Documents API reference](/api-reference/onboarding/persons/#tag/Person-documents)


## Appendix I: Enums

### Identification documents

1. List of accepted passports for video identification via IDnow: [here](https://go.idnow.de/bafin2017/documents)
2. List of accepted passports for postIdent: [here](//assets.ctfassets.net/8zxfdz0ps59a/3MjoXQpeatxH4C2rfiDUc3/f89f426b11539d21d4f680f20d37c607/dp-postident-ausweisliste-filiale.pdf)
3. Search for an identification document: [here](https://www.consilium.europa.eu/prado/en/search-by-document-country.html)


#### List of passports with address

The following table lists all ID types that include the bearer's address, which you can use to perform identification without having to provide a proof of address document.

| Document | Issuer Country | Type (ID/PP) |
|  --- | --- | --- |
| BGR-AO-01005 | Bulgaria | Passport |
| CHN-AO-04003 | China | Passport |
| HRV-BO-02001 | Croatia | ID |
| HRV-AO-02001 | Croatia | Passport |
| CZE-BO-04001 | Czech Republic | ID |
| CZE-BO-04002 | Czech Republic | ID |
| FRA-BO-02002 | France | ID |
| FRA-AO-03001-03003 | France | Passport |
| DEU-BO-01003 | Germany | ID |
| DEU-BO-02001 | Germany | ID |
| IND-AO-01001 | India | Passport |
| ITA-BO-04003 | Italy | ID |
| ITA-BO-03004 | Italy | ID |
| ITA-BO-03002 | Italy | ID |
| ITA-BO-03001 | Italy | ID |
| ITA-BO-03003 | Italy | ID |
| MLT-BO-02001 | Malta | ID |
| MLT-BO-03001 | Malta | ID |
| MAR-AO-02001 | Morocco | Passport |
| POL-BO-02001-02003 | Poland | ID |
| SGP-BO-01001-A | Singapore | ID |
| SGP-BO-01001 | Singapore | ID |
| SVK-BO-02001 | Slovakia | ID |
| SVK-BO-05001 | Slovakia | ID |
| SVK-BO-04001 | Slovakia | ID |
| SVN-AO-02001-02003 | Slovenia | Passport |
| SVN-AO-02004 | Slovenia | Passport |
| SVN-BO-02001 | Slovenia | ID |
| SVN-AO-01004 | Slovenia | Passport |
| ESP-BO-03001 | Spain | ID |
| ESP-BO-05001 | Spain | ID |


### Identification status

The following table includes the possible values for the identification `status` using Fourthline and their descriptions.

| Status | Description |
|  --- | --- |
| `created` | The identification resource has been created for a customer. |
| `pending` | The identification process has been initiated for the customer. |
| `processed` | The KYC data has been successfully received and structurally checked. |
| `authorization_required` | You must now initiate the QES process when the identification reaches this status by calling [PATCH Start e-signing process](/api-reference/identity/identifications/#tag/Person-identifications/paths/~1v1~1persons~1%7Bperson_id%7D~1identifications~1%7Bid%7D~1authorize/patch) to send an SMS OTP to the customer's mobile number. |
| `confirmation_required` | The customer received an SMS OTP for the QES on their verified mobile number and they must enter it on your UI. After the customer enters the OTP, you must call [PATCH Confirm QES e-signing process](/api-reference/identity/identifications/#tag/Person-identifications/paths/~1v1~1persons~1%7Bperson_id%7D~1identifications~1%7Bid%7D~1confirm/patch) to complete the QES process. |
| `successful` | The identification process was successful. |
| `failed` | The identification process failed. This could be for different reasons. Check the [appendix](#appendix-ii-fourthline-status-codes-for-testing) for possible scenarios. |
| `expired` | The identification resource expired. This happens 90 days after the last status transition if the identification isn't in a final state. |


## Appendix II: Fourthline status codes for testing

The following Fourthline status codes are available for testing:

| Type | Possible status codes |
|  --- | --- |
| Success | Risk values: `10`, `20`, `30` |
| Inconsistent data | `2001`, `2002`, `2003`, `3001`, `3002`, `3003`, `3005`, `3100`, `3101` `3102`, `3103`, `3104`, `3105`, `3200`, `3201`, `3202`, `3203`, `3204`, `3205`, `3300`, `3304`, `3305`, `3306`, `3307`, `3400`, `3401`, `3402`, `3403`, `3404`, `3405`, `3406` |
| Unacceptable (Rejected) | `4110`, `4120`, `4140` |
| Unacceptable (Fraud) | `5100`, `5200`, `5300`, `5400` |


For a full list of all possible Fourthline verification status codes, refer to [Fourthline's online documentation](https://dx.fourthline.com/reference/verification-status) (password-protected).