# KYC

### Getting started <a href="#getting-started" id="getting-started"></a>

Creates a magic link to start a KYC web process hosted by Unico.\
After the user finished the process, the user magic link will be inactivated and the user will not be able to use it again.\
You will need to create a new magic link for the user to start a new KYC process.

{% hint style="info" %}
**Base URL**:

* Sandbox: <mark style="color:blue;">`https://sandbox.trully.ai`</mark>;
* Production: <mark style="color:blue;">`https://api.trully.ai`</mark>.
  {% endhint %}

## Create a Magic Link

> Endpoint to create a new KYC process in Magic Link integration.

```json
{"openapi":"3.0.3","info":{"title":"Trully API - Magic Link","version":"1.0"},"servers":[{"url":"https://sandbox.trully.ai"}],"security":[{"ApiKeyAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"x-api-key"}}},"paths":{"/v2/magic-link":{"post":{"summary":"Create a Magic Link","description":"Endpoint to create a new KYC process in Magic Link integration.","operationId":"generateMagicLink","tags":["Magic Link"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"external_id":{"type":"string","description":"An external identifier for the request, used for tracking and reference purposes."},"metadata":{"type":"object","properties":{"redirect_url":{"type":"string","nullable":true,"description":"URL to redirect the user after the KYC process is completed."},"webhook_url":{"type":"string","nullable":true,"description":"**URL to send the KYC process data after the KYC process is completed. This webhook will be called in the client side.** WARNING: For security reasons the endpoint should be using the HTTPS protocol; The component will wait for one minute for your webhook server to respond. After that, it will drop the communication. Process won't be affected inany way by webhook communication; Make sure to allow the urls https://verification.unico.app and https://verification.uat.unico.app inyour CORS configuration for production and sandbox environment respectively."},"track_webhook_url":{"type":"string","nullable":true,"description":"**URL to send each KYC step processed by the user. This webhook will be called in the client side. See the enum described below.** WARNING: For security reasons the endpoint should be using the HTTPS protocol; The component will wait for one minute for your webhook server to respond. After that, it will drop the communication. Process won't be affected inany way by webhook communication; Make sure to allow the urls https://verification.unico.app and https://verification.uat.unico.app inyour CORS configuration for production and sandbox environment respectively."}}}}}}}},"responses":{"200":{"description":"Magic link successfully created","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"external_id":{"type":"string","nullable":true,"description":"An external identifier for the request, used for tracking and reference purposes."},"created_on":{"type":"string","format":"date-time","description":"The date when the magic link was created."},"is_active":{"type":"boolean","description":"If true, the magic link is active."},"token":{"type":"string","description":"The token of the magic link which will be used to link the KYC processes to the magic link"},"magic_link_url":{"type":"string","format":"uri","description":"The magic URL link to start the KYC process."},"metadata":{"type":"object","description":"Configuration parameters for magic link.","properties":{"redirect_url":{"type":"string","nullable":true,"description":"URL to redirect the user after the KYC process is completed."},"webhook_url":{"type":"string","nullable":true,"description":"URL to send the KYC process data after the KYC process is completed. This webhook will be called in the client side."},"track_webhook_url":{"type":"string","nullable":true,"description":"URL to send each KYC step processed by the user. This webhook will be called in the client side."}}},"version":{"type":"string","description":"The version of the magic link."}}},"version":{"type":"string","description":"The version of the API that processed the request, useful for tracking changes and compatibility."},"status":{"type":"string","description":"A textual representation of the response status, indicating success or failure of the operation."},"status_code":{"type":"integer","description":"The HTTP status code of the response, providing a standardized indicator of the request's outcome."},"request_date":{"type":"string","format":"date-time","description":"The date and time when the request was made, in ISO 8601 format."},"request":{"type":"object","description":"Details of the request made to the API, potentially including method, parameters, and headers.","properties":{"metadata":{"type":"object","description":"Configuration parameters for magic link.","properties":{"redirect_url":{"type":"string","nullable":true,"description":"URL to redirect the user after the KYC process is completed."},"webhook_url":{"type":"string","nullable":true,"description":"URL to send the KYC process data after the KYC process is completed. This webhook will be called in the client side."},"track_webhook_url":{"type":"string","description":"URL to send each KYC step processed by the user. This webhook will be called in the client side.","nullable":true}}}}}}}}}}}}}}}
```

<details>

<summary>Enum <strong>track_webhook_url</strong></summary>

| Key           | Description                                 |
| ------------- | ------------------------------------------- |
| step          | Name of the previous completed step.        |
| user\_id      | The external\_id you set in the magic link. |
| started\_on   | UTC timezone. Step starting time.           |
| completed\_on | UTC timezone. Step completion time.         |

\
**Steps Table**

| Name                  | Description                                  |
| --------------------- | -------------------------------------------- |
| form\_start           | User is currently scanning the document.     |
| form document\_front  | The user has already captured the INE Front. |
| form document\_back   | The user has already captured the INE Back.  |
| form\_document        | Process is currently in the selfie step.     |
| form\_selfie          | User reach the final step of the operation.  |
| form\_decision\_maker | The operation returns the system response.   |

Tracking process is a silent operation which means there is no UI to represent it. This process will succeed or fail without any interaction with the user.

</details>

{% hint style="warning" %}
**Webhook V1 Requirements**

* **HTTPS protocol**: For security reasons, your webhook endpoint must use the HTTPS protocol;
* **Response time**: The system will wait up to **one minute** for a response from your webhook server. After this period, the connection will be dropped. This will **not** impact the main process execution in any way;
  {% endhint %}

#### **Errors responses**

{% tabs %}
{% tab title="Click on the side to see more" %}

{% endtab %}

{% tab title="400 Bad Request" %}
{% code overflow="wrap" %}

```json
{
    "data": {
        "error": "data provided in the field is invalid"
    },
    "version": "v1.4.2",
    "status": "bad request",
    "status_code": 400,
    "request_date": "2025-07-28T20:22:29+0000",
    "request": {
        "metadata": null
    }
}
```

{% endcode %}
{% endtab %}

{% tab title="403 Forbidden" %}
{% code overflow="wrap" %}

```json
{
    "message": "Forbidden"
}
```

{% endcode %}
{% endtab %}

{% tab title="500 Internal Server Error" %}
{% code overflow="wrap" %}

```json
{
    "data": {
        "error": "internal server error"
    },
    "version": "v1.4.2",
    "status": "bad request",
    "status_code": 400,
    "request_date": "2025-07-28T20:22:29+0000",
    "request": {
        "metadata": null
    }
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

## Get Result

> Endpoint to get the result of a process in Magic Link.

```json
{"openapi":"3.0.3","info":{"title":"Retrieve Magic Link Request History","version":"1.0.0"},"servers":[{"url":"https://sandbox.trully.ai"}],"security":[{"ApiKeyAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"x-api-key"}}},"paths":{"/v2/history/request":{"get":{"summary":"Get Result","description":"Endpoint to get the result of a process in Magic Link.","parameters":[{"name":"magic_link_token","in":"query","required":true,"schema":{"type":"string"},"description":"Token returned when the Magic Link was created."}],"responses":{"200":{"description":"Successful response containing identity data and images.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","description":"Wrapper object with result data.","properties":{"images":{"type":"object","description":"Images used during the identification process.","properties":{"document_image":{"type":"string","description":"Base64-encoded image of the front of the document."},"document_image_back":{"type":"string","description":"Base64-encoded image of the back of the document."},"selfie":{"type":"string","description":"Base64-encoded selfie image captured during verification."}}},"response":{"type":"object","description":"Main result object of the verification process. See more details on the enum section.","properties":{"curp":{"type":"object","description":"CURP document details. This object provides a detailed breakdown and validation of the user's CURP against official government records.","properties":{"age":{"type":"integer","description":"The calculated age of the user."},"curp":{"type":"string","description":"The CURP string being analyzed."},"date_of_birth":{"type":"string","description":"The user's date of birth as decoded from the CURP (DD/MM/YYYY)."},"deceased":{"type":"boolean","description":"Indicates if the person associated with the CURP is marked as deceased."},"gender":{"type":"string","description":"The user's gender as decoded from the CURP (\"M\" or \"F\")."},"government_name":{"type":"string","description":"The full name associated with the CURP in the official government database."},"government_valid":{"type":"boolean","description":"Indicates if the CURP is valid according to official government databases (RENAPO)."},"is_mexican":{"type":"boolean","description":"Indicates if the CURP corresponds to a Mexican citizen."},"name_to_CURP_valid":{"type":"boolean","description":"Indicates if the name provided in the request is consistent with the name associated with the CURP."},"state_iso":{"type":"string","description":"The ISO 3166-2 code for the state of birth."},"state_of_birth":{"type":"string","description":"The user's state of birth as decoded from the CURP."}}},"document":{"type":"object","description":"This object encapsulates all data extracted and analyzed from the user's identification document.","properties":{"back":{"type":"object","description":"This object contains information extracted from the Machine-Readable Zone (MRZ) on the back of the document.","properties":{"cic":{"type":"string","description":"The \"CIC\" number extracted from the MRZ."},"citizen_id":{"type":"string","description":"The citizen identification number from the MRZ."},"mrz":{"type":"string","description":"The full Machine-Readable Zone string."}}},"details":{"type":"object","properties":{"detected":{"type":"boolean","description":"Indicates if a document was successfully detected in the image."},"document_id":{"type":"integer","description":"A unique identifier for the processed document."},"forensics":{"type":"object","properties":{"is_valid":{"type":"string","enum":["yes","no","inconclusive"],"description":"Contains results from forensic analysis of the document."}}}}},"front":{"type":"object","description":"This object contains the information extracted from the front of the ID and the facial analysis results for the document photo.","properties":{"face_analysis":{"type":"object","description":"This object contains the analysis of the face found on the ID document.","properties":{"face_id":{"type":"integer","description":"A unique identifier for this specific face instance."},"face_id_v2":{"type":"integer","description":"Another unique identifier for the face instance (version 2)."},"first_seen":{"type":"string","description":"Timestamp of the first time this face was ever seen in the system."},"inquiry_date":{"type":"string","description":"Timestamp of the current verification inquiry."},"last_seen":{"type":"string","description":"Timestamp of the most recent time this face was seen anywhere in the network."},"last_seen_by_your_company":{"type":"string","description":"Timestamp of the most recent time this face was seen in an inquiry by your company."},"match":{"type":"boolean","description":"Indicates if this face is a potential match with other faces in the database."},"match_fraud_flag":{"type":"boolean","description":"Indicates if this face has been associated with fraudulent activity."},"seen_by_your_company":{"type":"boolean","description":"Indicates if this face has been previously seen in an inquiry by your company."},"seen_different_companies":{"type":"integer","description":"The number of other companies in the network that have seen this face."},"times_seen_by_your_company":{"type":"integer","description":"The total number of times this face has been seen in inquiries by your company."},"times_seen_last_month":{"type":"integer","description":"The number of times this face has been seen in the last month across the network."},"unique_face_id_v2":{"type":"integer","description":"A persistent and unique identifier for this physical face across all inquiries (version 2)."},"warnings":{"type":"object","description":"Contains specific warnings related to the face analysis.","properties":{"external_id":{"type":"string","description":"A warning message indicating that the user's face is associated with multiple different external IDs."}}}}},"information":{"type":"object","description":"Extracted document information from OCR. Each field in this object contains a text value (the extracted string) and a valid boolean.","properties":{"address":{"type":"object","description":"The user's address.","properties":{"text":{"type":"string","description":"Address text"},"valid":{"type":"boolean","description":"Whether the address is valid"}}},"birthdate":{"type":"object","description":"User's date of birth.","properties":{"text":{"type":"string","description":"Birthdate text"},"valid":{"type":"boolean","description":"Validity of birthdate"}}},"complete_name":{"type":"object","description":"The user's full name.","properties":{"text":{"type":"string","description":"Full name"},"valid":{"type":"boolean","description":"Validity of the name"}}},"curp":{"type":"object","description":"The CURP extracted from the document.","properties":{"text":{"type":"string","description":"CURP text"},"valid":{"type":"boolean","description":"CURP validity"}}},"electoral_key":{"type":"object","description":"The electoral key from the document.","properties":{"text":{"type":"string","description":"Electoral key"},"valid":{"type":"boolean","description":"Electoral key validity"}}},"last_name":{"type":"object","description":"User's paternal last name.","properties":{"text":{"type":"string","description":"Last name"},"valid":{"type":"boolean","description":"Validity of last name"}}},"mother_last_name":{"type":"object","description":"User's maternal last name.","properties":{"text":{"type":"string","description":"Mother's last name"},"valid":{"type":"boolean","description":"Validity of mother's last name"}}},"name":{"type":"object","description":"User's first name(s).","properties":{"text":{"type":"string","description":"Name"},"valid":{"type":"boolean","description":"Name validity"}}},"registration_year":{"type":"object","description":"Year the document was registered.","properties":{"text":{"type":"string","description":"Registration year"},"valid":{"type":"boolean","description":"Validity of the year"}}},"sex":{"type":"object","description":"User's sex/gender.","properties":{"text":{"type":"string","description":"Sex (e.g., \"H\" for Male/Hombre)"},"valid":{"type":"boolean","description":"Validity of sex field"}}},"valid_thru":{"type":"object","description":"The document's expiration year.","properties":{"text":{"type":"string","description":"Document validity year"},"valid":{"type":"boolean","description":"Validity of expiration date"}}}}}}}}},"face_match":{"type":"boolean","description":"Indicates whether the face from the selfie successfully matches the face on the document. true if they match."},"label":{"type":"string","nullable":true,"description":"A field reserved for results from specific sub-processes; null if not applicable."},"reason":{"type":"string","nullable":true,"description":"An array of strings detailing the reasons for the assigned label."},"request_id":{"type":"string","description":"A unique identifier for this specific API request."},"selfie":{"type":"object","description":"Selfie metadata and result","properties":{"face_id":{"type":"integer","description":"A unique identifier for this specific selfie instance."},"face_id_v2":{"type":"integer","description":"Another unique identifier for the face instance (version 2)."},"first_seen":{"type":"string","description":"Timestamp of the first time this selfie's face was ever seen in the system."},"first_seen_image":{"type":"boolean","description":"Indicates if this is the first time this exact image has been seen."},"inquiry_date":{"type":"string","description":"Timestamp of the current verification inquiry."},"last_seen":{"type":"string","description":"Timestamp of the most recent time this face was seen anywhere in the network."},"last_seen_by_your_company":{"type":"string","description":"Timestamp of the most recent time this face was seen in an inquiry by your company."},"match":{"type":"boolean","description":"Indicates if this face is a potential match with other faces in the database."},"match_fraud_flag":{"type":"boolean","description":"Indicates if this face has been associated with fraudulent activity."},"seen_by_your_company":{"type":"boolean","description":"Indicates if this face has been previously seen in an inquiry by your company."},"seen_different_companies":{"type":"integer","description":"The number of other companies in the network that have seen this face."},"times_seen_by_your_company":{"type":"integer","description":"The total number of times this face has been seen in inquiries by your company."},"times_seen_last_month":{"type":"integer","description":"The number of times this face has been seen in the last month across the network."},"unique_face_id_v2":{"type":"integer","description":"A persistent and unique identifier for this physical face across all inquiries (version 2)."},"warnings":{"type":"object","description":"Contains specific warnings related to the selfie analysis.","properties":{}}}},"unico":{"type":"object","description":"UNICO process metadata","properties":{"process_id":{"type":"string","description":"This object contains internal identifiers related to the verification process."},"result":{"type":"string","enum":["PROCESS_RESULT_UNSPECIFIED","PROCESS_RESULT_ERROR","PROCESS_RESULT_VERIFIED","PROCESS_RESULT_LIVE","PROCESS_RESULT_HIGH_RISK","PROCESS_RESULT_CRITICAL_RISK","PROCESS_RESULT_NOT_APPROVED","PROCESS_RESULT_NOT_LIVE"],"description":"Process result. Possible values: **'PROCESS_RESULT_UNSPECIFIED'** - the process has not yet finished; **'PROCESS_RESULT_ERROR'** - process finished with error; **'PROCESS_RESULT_VERIFIED'** - the user was active at the time of capture; it is the face of the ID holder and no evidence related to fraud was found; **'PROCESS_RESULT_LIVE'** - the user was active at the time of the capture; we did not find sufficient evidence to guarantee that they are the ID holder and no evidence of fraud; **'PROCESS_RESULT_HIGH_RISK'** - we recommend rejection, but the decision remains yours. High Risk indicates that we found at least one strong evidence of fraud; **'PROCESS_RESULT_CRITICAL_RISK'** - we recommend rejection, but leave it open for you to decide. Critical Risk indicates that we found at least 2 strong evidences of fraud; **'PROCESS_RESULT_NOT_APPROVED'** - rejection recommended as multiple indications of fraud were detected; **'PROCESS_RESULT_NOT_LIVE'** - the user was not live at the time of capture, although we found no other indications of fraud."}}}}},"user_id":{"type":"string","description":"The user id that was set in the request."}}},"request_date":{"type":"string","format":"date-time","description":"The date and time when the request was made, in ISO 8601 format."},"status":{"type":"string","description":"A textual representation of the response status, indicating success or failure of the operation."},"status_code":{"type":"integer","description":"The HTTP status code of the response, providing a standardized indicator of the request's outcome."},"version":{"type":"string","description":"The version of the API that processed the request, useful for tracking changes and compatibility."}}}}}}}}}}}
```

{% hint style="warning" %}

* The `valid` field is used to indicate that the OCR texts could be extracted and structurally validated; it does not necessarily indicate that the data actually exists.
* The `address` field, due to its lack of a generalized structure and because in some cases people have the option of not providing their address to the INE (National Institute of Statistics), the "valid" field is not taken into account for validating the structure.
  {% endhint %}

#### **Errors responses**

{% tabs %}
{% tab title="Click on the side to see more" %}

{% endtab %}

{% tab title="400 Bad Request" %}
{% code overflow="wrap" %}

```json
{
    "data": {
        "error": [
            {
                "attribute": [
                    "magic_link_token"
                ],
                "message": "Input should be a valid UUID, invalid group length in group 4: expected 12, found 11",
                "type": "uuid_parsing"
            }
        ]
    },
    "request_date": "2025-07-28T20:43:34",
    "status": "There are some errors in the request",
    "status_code": 400,
    "version": "v3.6.0"
}
```

{% endcode %}

| Name                 | Type             | Description                                                                                                   |
| -------------------- | ---------------- | ------------------------------------------------------------------------------------------------------------- |
| data                 | object           | Defines an error structure for API responses, encapsulating error messages resulting from request processing. |
| data.error           | string           | A detailed description of the error encountered during the processing of the request.                         |
| data.error.atributte | array of strings | The list of attributes causing the error.                                                                     |
| data.error.message   | string           | A detailed message explaining the error.                                                                      |
| data.error.type      | string           | The type of error encountered.                                                                                |
| request\_date        | string           | The date and time when the request was made, in ISO 8601 format.                                              |
| status               | string           | A textual representation of the response status, indicating success or failure of the operation.              |
| status\_code         | integer          | The HTTP status code of the response, providing a standardized indicator of the request's outcome.            |
| version              | string           | The version of the API that processed the request, useful for tracking changes and compatibility.             |
| {% endtab %}         |                  |                                                                                                               |

{% tab title="404 Not Found" %}

```json
{
    "data": {
        "error": "This magic link have no requests associated"
    },
    "request_date": "2025-07-28T20:40:50",
    "status": "Nothing matches the given URI",
    "status_code": 404,
    "version": "v3.6.0"
}
```

{% endtab %}

{% tab title="500 Internal Serve Error" %}

```json
    "data": {
        "error": "internal server error"
    },
    "version": "v1.4.2",
    "status": "bad request",
    "status_code": 400,
    "request_date": "2025-07-28T20:22:29+0000",
    "request": {
        "metadata": null
    }
}
```

{% endtab %}
{% endtabs %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://devcenter.unico.io/trust-en/integrations/integration-magic-link/api-reference/kyc.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
