KYC Magic Link
Ce cas d'usage n'utilise pas l'endpoint Unico POST /v1/process ni le contrat API/TCA. L'intégration se fait avec Trully.ai (host api.trully.ai), avec authentification via x-api-key au lieu de Bearer JWT, et un schéma de réponse propriétaire. Pour les autres pays, utilisez Onboarding (Global).
Ce que ce cas d'usage résout
KYC Magic Link répond au défi d'exécuter le processus d'identification au Mexique, en collectant les documents d'identité nationaux (INE) et les données biométriques faciales. Avec un parcours hébergé par Unico, vous éliminez la friction de développement front-end grâce à un lien envoyé via vos propres canaux (WhatsApp, SMS, e-mail).
Utilisez ce cas d'usage lorsque :
- Vous opérez au Mexique et le document d'identité utilisé est l'INE (obligatoire).
N'utilisez pas ce cas d'usage lorsque :
- L'utilisateur est en dehors du Mexique ou utilise d'autres documents → consultez les autres cas d'usage d'onboarding.
Capacités impliquées
Pipeline exécuté au sein d'un seul processus :
| Capacité | Obligatoire | Rôle dans le flux |
|---|---|---|
| Capture de document | Obligatoire | Capture l'image du document INE. La réutilisation de document n'est pas disponible dans ce cas d'usage — chaque session nécessite une nouvelle capture. |
| Liveness | Obligatoire | Vérification de vivacité — selfie obligatoire qui ancre le processus. |
| Classification des risques | Obligatoire | Croise les signaux comportementaux pour signaler le risque de fraude associé au CPF. |
| Vérification d'identité | Optionnel (si contracté) | Vérifie si le visage de la transaction appartient au titulaire de l'identifiant gouvernemental fourni, en utilisant la base d'identité d'Unico et des signaux supplémentaires. |
Prérequis
- Clé API — provisionnée par votre Chef de projet Onboarding chez Unico. Envoyée dans l'en-tête
x-api-key. - Endpoint HTTPS public pour recevoir les webhooks (optionnel, mais recommandé).
- Configuration CORS — autoriser les origines
https://verification.unico.app(production) ethttps://verification.uat.unico.app(sandbox) sur le serveur qui reçoit le webhook.
Implémentation étape par étape
Contrairement aux autres cas d'usage, Magic Link ne possède pas de champ flow — l'intégration se fait directement avec l'API Trully. L'endpoint crée un lien de vérification unique que vous distribuez à l'utilisateur via votre propre canal.
Endpoint : POST https://sandbox.trully.ai/v2/magic-link
En-têtes :
| En-tête | Obligatoire | Description |
|---|---|---|
x-api-key | Oui | Clé API provisionnée par votre Chef de projet Onboarding chez Unico. |
Content-Type | Oui | application/json |
Corps (application/json) :
| Champ | Type | Obligatoire | Description |
|---|---|---|---|
external_id | string | Non | Identifiant externe pour la requête, utilisé à des fins de suivi et de référence. |
metadata | object | Non | Conteneur pour les paramètres de configuration. |
metadata.phone | string | Non | Numéro de téléphone de l'utilisateur au format international (ex. : 521234567890). |
metadata.redirect_url | string | Non | URL de redirection de l'utilisateur une fois le processus KYC terminé. |
metadata.webhook_url | string | Non | URL pour envoyer les données du processus KYC une fois terminé. Ce webhook sera appelé côté client. Pour des raisons de sécurité, l'endpoint doit utiliser HTTPS. Le composant attendra une minute que votre serveur webhook réponde — après quoi, il abandonnera la communication. Le processus ne sera en aucun cas affecté par la communication webhook. Assurez-vous d'autoriser https://verification.unico.app et https://verification.uat.unico.app dans votre configuration CORS pour la production et le sandbox respectivement. |
metadata.track_webhook_url | string | Non | URL pour envoyer chaque étape KYC traitée par l'utilisateur (voir les événements webhook ci-dessous). Ce webhook sera appelé côté client. Pour des raisons de sécurité, l'endpoint doit utiliser HTTPS. Le composant attendra une minute que votre serveur webhook réponde — après quoi, il abandonnera la communication. Le processus ne sera en aucun cas affecté par la communication webhook. Assurez-vous d'autoriser https://verification.unico.app et https://verification.uat.unico.app dans votre configuration CORS pour la production et le sandbox respectivement. |
Valeurs possibles pour data.step (envoyées à track_webhook_url) :
| Étape | Description |
|---|---|
form_start | L'utilisateur est en train de scanner le document. |
form_document_front | L'utilisateur a déjà capturé le recto de l'INE. |
form_document_back | L'utilisateur a déjà capturé le verso de l'INE. |
form_document | Le processus est actuellement à l'étape du selfie. |
form_selfie | L'utilisateur a atteint l'étape finale de l'opération. |
form_decision_maker | L'opération retourne la réponse du système. |
Exemple de requête :
curl -X POST https://sandbox.trully.ai/v2/magic-link \
-H "x-api-key: $TRULLY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"external_id": "user-mx-12345",
"metadata": {
"phone": "521234567890",
"redirect_url": "https://app.client.com.mx/kyc-done",
"webhook_url": "https://app.client.com.mx/webhook/result",
"track_webhook_url": "https://app.client.com.mx/webhook/track"
}
}'
Champs de la réponse :
| Champ | Type | Description |
|---|---|---|
data.external_id | string (nullable) | Identifiant externe pour la requête, utilisé à des fins de suivi et de référence. |
data.created_on | string (date-time) | Date de création du magic link. |
data.is_active | boolean | Si true, le magic link est actif. |
data.token | string | Token du magic link qui sera utilisé pour associer les processus KYC au magic link. |
data.magic_link_url | string (URI) | L'URL du magic link pour démarrer le processus KYC. |
data.metadata.redirect_url | string (nullable) | URL de redirection de l'utilisateur une fois le processus KYC terminé. |
data.metadata.webhook_url | string (nullable) | URL pour envoyer les données du processus KYC une fois terminé. Ce webhook sera appelé côté client. |
data.metadata.track_webhook_url | string (nullable) | URL pour envoyer chaque étape KYC traitée par l'utilisateur. Ce webhook sera appelé côté client. |
data.version | string | Version du magic link. |
version | string | Version de l'API qui a traité la requête, utile pour le suivi des modifications et la compatibilité. |
status | string | Représentation textuelle du statut de la réponse, indiquant le succès ou l'échec de l'opération. |
status_code | integer | Code de statut HTTP de la réponse, fournissant un indicateur standardisé du résultat de la requête. |
request_date | string (date-time) | Date et heure de la requête, au format ISO 8601. |
request.metadata.redirect_url | string (nullable) | URL de redirection de l'utilisateur une fois le processus KYC terminé (écho de la requête). |
request.metadata.webhook_url | string (nullable) | URL pour envoyer les données du processus KYC après complétion (écho de la requête). |
request.metadata.track_webhook_url | string (nullable) | URL pour envoyer chaque étape KYC traitée par l'utilisateur (écho de la requête). |
Exemple de réponse :
{
"data": {
"external_id": null,
"created_on": "2025-07-28T18:11:54.430048399Z",
"is_active": true,
"token": "3f6dbcc1-49ba-4935-be90-dd8dd59b5530",
"magic_link_url": "https://verification.uat.unico.app/link/v2/3f6dbcc1-49ba-4935-be90-dd8dd59b5530",
"metadata": {
"redirect_url": null,
"webhook_url": null,
"track_webhook_url": null
},
"version": "v2"
},
"version": "v1.4.2",
"status": "ok",
"status_code": 200,
"request_date": "2025-07-28T18:11:54+0000",
"request": {
"metadata": {
"redirect_url": null,
"webhook_url": null,
"track_webhook_url": null
}
}
}
Réponses d'erreur — POST /v2/magic-link
| Code | Message | Description |
|---|---|---|
400 Bad Request | data provided in the field is invalid | Structure de données ou valeurs de champ invalides dans la charge utile de la requête. Vérifiez les champs obligatoires et les formats. |
403 Forbidden | Forbidden | Clé API manquante, expirée ou sans permission. Vérifiez l'en-tête x-api-key. |
500 Internal Server Error | internal server error | Échec de traitement côté serveur. Réessayez avec un backoff exponentiel. Si le problème persiste, contactez le support. |
Exemple de réponse 400 :
{
"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
}
}
Envoyez via WhatsApp, SMS, e-mail ou intégrez dans votre interface. L'utilisateur accède au lien depuis son propre appareil et complète le parcours hébergé.
- Polling via GET (obligatoire) — appelez
GET /v2/history/request?magic_link_token={token}périodiquement jusqu'à ce queunico.resultsoit renseigné. Voir Polling via GET ci-dessous. - Webhook (optionnel) — configurez avec votre Chef de projet Onboarding pour recevoir les événements automatiquement. Voir Webhook ci-dessous.
Polling via GET
Endpoint : GET https://sandbox.trully.ai/v2/history/request
Paramètres de requête :
| Paramètre | Type | Obligatoire | Description |
|---|---|---|---|
magic_link_token | string | Oui | Token retourné lors de la création du Magic Link. |
En-têtes :
| En-tête | Obligatoire | Description |
|---|---|---|
x-api-key | Oui | Clé API provisionnée par votre Chef de projet Onboarding chez Unico. |
Exemple de requête :
curl "https://sandbox.trully.ai/v2/history/request?magic_link_token=$TOKEN" \
-H "x-api-key: $TRULLY_API_KEY"
Exemple de réponse :
{
"data": {
"images": {
"document_image": "/9j/4ASu7bmV[...]fyPjOKfgif//Z",
"document_image_back": "/9j/4ASu7bmV[...]fyPjOKfgif//Z",
"selfie": "/9j/4ASu7bmV[...]fyPjOKfgif//Z"
},
"response": {
"curp": {
"age": 58,
"curp": "GOCJ850627HDFRRL09",
"date_of_birth": "14/11/1956",
"deceased": false,
"gender": "M",
"government_name": "LUKE SKYWALKER",
"government_valid": true,
"is_mexican": true,
"name_to_CURP_valid": true,
"state_iso": "MX-NLE",
"state_of_birth": "Nuevo León"
},
"document": {
"back": {
"cic": "237457894",
"citizen_id": "237457894",
"mrz": "IDMEX999999999999<9 VADER<SKYWALKER<<LUKE"
},
"details": {
"detected": true,
"document_id": 229928,
"forensics": { "is_valid": "no" }
},
"front": {
"face_analysis": {
"face_id": 237437,
"face_id_v2": 199068,
"first_seen": "12/22/2022, 18:54:09",
"inquiry_date": "07/28/2025, 20:53:12",
"last_seen": "07/28/2025, 18:47:46",
"last_seen_by_your_company": "07/24/2025, 21:38:21",
"match": true,
"match_fraud_flag": true,
"seen_by_your_company": true,
"seen_different_companies": 46,
"times_seen_by_your_company": 3,
"times_seen_last_month": 111,
"unique_face_id_v2": 126880,
"warnings": {
"external_id": "User found in the company with other external_ids: ['abc-123']"
}
},
"information": {
"address": { "text": "DOMICILIO/ADDRESS, HARLINGEN, TX 78552", "valid": false },
"birthdate": { "text": "14/11/1956", "valid": true },
"complete_name": { "text": "LUKE SKYWALKER", "valid": true },
"curp": { "text": "GOCJ850627HDFRRL09", "valid": true },
"electoral_key": { "text": "GRCRSN82031007M500", "valid": true },
"last_name": { "text": "SKYWALKER", "valid": true },
"mother_last_name": { "text": "ORGANA", "valid": true },
"name": { "text": "LUKE", "valid": true },
"registration_year": { "text": "1998", "valid": true },
"sex": { "text": "H", "valid": true },
"valid_thru": { "text": "2027", "valid": true }
}
}
},
"face_match": false,
"label": null,
"reason": null,
"request_id": "d1kxp9ah8f0s71uv9zx0",
"selfie": {
"face_id": 237436,
"face_id_v2": 4378,
"first_seen": "02/05/2025, 02:36:19",
"first_seen_image": true,
"inquiry_date": "07/28/2025, 20:52:49",
"last_seen": "07/28/2025, 20:52:51",
"last_seen_by_your_company": "07/23/2025, 18:14:27",
"match": true,
"match_fraud_flag": true,
"seen_by_your_company": true,
"seen_different_companies": 2,
"times_seen_by_your_company": 2,
"times_seen_last_month": 7,
"unique_face_id_v2": 494,
"warnings": {}
},
"unico": {
"process_id": "d333dfac-9ddb-4066-8e2c-44eaf4c86b4a",
"result": "PROCESS_RESULT_LIVE"
}
},
"user_id": ""
},
"request_date": "2025-07-28T20:53:38",
"status": "Request fulfilled, document follows",
"status_code": 200,
"version": "v3.6.0"
}
Champs de la réponse :
Niveau racine :
| Champ | Type | Description |
|---|---|---|
status | string | Représentation textuelle du statut de la réponse. |
status_code | integer | Code de statut HTTP. |
request_date | string (date-time) | Date et heure de la requête. |
version | string | Version de l'API qui a traité la requête. |
data.user_id | string | ID utilisateur défini dans la requête originale. |
data.images — Images capturées encodées en Base64 :
| Champ | Type | Description |
|---|---|---|
data.images.document_image | string | Image encodée en Base64 du recto du document. |
data.images.document_image_back | string | Image encodée en Base64 du verso du document. |
data.images.selfie | string | Image de selfie encodée en Base64 capturée lors de la vérification. |
data.response.unico — Verdict consolidé :
| Champ | Type | Description |
|---|---|---|
data.response.unico.process_id | string (UUID) | Identifiant interne lié au processus de vérification. |
data.response.unico.result | string | Résultat du processus. Valeurs possibles décrites ci-dessous. |
Valeurs possibles pour data.response.unico.result :
La valeur de résultat encode l'une des trois dimensions d'évaluation :
- Évaluation de l'identité — si le visage capturé appartient au titulaire du document (
PROCESS_RESULT_VERIFIED,PROCESS_RESULT_NOT_APPROVED). - Comportement frauduleux — si des signaux comportementaux ou réseau indiquent un risque de fraude (
PROCESS_RESULT_LIVE,PROCESS_RESULT_HIGH_RISK,PROCESS_RESULT_CRITICAL_RISK,PROCESS_RESULT_NOT_APPROVED). - Liveness — si un visage vivant a été détecté au moment de la capture (
PROCESS_RESULT_NOT_LIVE).
| Résultat | Recommandation | Signification | Signal |
|---|---|---|---|
PROCESS_RESULT_ERROR | Rejeter | Le processus s'est terminé avec une erreur. | Système |
PROCESS_RESULT_VERIFIED | Accepter | L'utilisateur était actif au moment de la capture ; c'est le visage du titulaire de la pièce d'identité et aucune preuve de fraude n'a été trouvée. | Identité : confirmée |
PROCESS_RESULT_LIVE | Réviser / Accepter | L'utilisateur était actif au moment de la capture ; nous n'avons pas trouvé de preuves suffisantes pour garantir qu'il est le titulaire de la pièce d'identité et aucune preuve de fraude. | Identité : non concluante · Fraude : aucune |
PROCESS_RESULT_HIGH_RISK | Recommander le rejet | Nous avons trouvé au moins une preuve solide de fraude. La décision finale vous appartient. | Comportement frauduleux : 1 signal fort |
PROCESS_RESULT_CRITICAL_RISK | Recommander le rejet | Nous avons trouvé au moins 2 preuves solides de fraude. La décision finale vous appartient. | Comportement frauduleux : 2+ signaux forts |
PROCESS_RESULT_NOT_APPROVED | Rejeter | Rejet recommandé car de multiples indications de fraude ont été détectées. | Identité : rejetée · Comportement frauduleux : signaux multiples |
PROCESS_RESULT_NOT_LIVE | Autoriser jusqu'à 2 tentatives | L'utilisateur n'était pas en vie au moment de la capture, bien qu'aucune autre indication de fraude n'ait été trouvée. | Liveness : visage non vivant |
PROCESS_RESULT_VERIFIED nécessite une activation. Par défaut, ce résultat n'est pas actif — consultez votre Chef de projet Unico si vous souhaitez l'activer.
Signaux auxiliaires pour votre décision :
Pour les cas LIVE, HIGH_RISK ou CRITICAL_RISK, complétez votre décision avec ces champs :
| Champ | Type | Signification |
|---|---|---|
face_match | boolean | Statut de correspondance faciale entre le document et le selfie. |
document.front.face_analysis.match_fraud_flag | boolean | Si le visage du document a été associé à une activité frauduleuse. |
selfie.match_fraud_flag | boolean | Si le visage du selfie a été associé à une activité frauduleuse. |
warnings.external_id | string | Avertissement indiquant que le visage de l'utilisateur est associé à plusieurs identifiants externes. |
data.response — Signaux de résultat de niveau supérieur :
| Champ | Type | Description |
|---|---|---|
data.response.face_match | boolean | Si le visage du selfie correspond au visage du document. |
data.response.label | string (nullable) | Réservé aux résultats de sous-processus spécifiques ; null si non applicable. |
data.response.reason | string (nullable) | Raisons du label attribué. |
data.response.request_id | string | Identifiant unique de la requête API. |
data.response.curp — Validation CURP contre RENAPO :
| Champ | Type | Description |
|---|---|---|
curp | string | La chaîne CURP analysée. |
government_valid | boolean | Si le CURP est valide selon RENAPO. |
government_name | string | Nom complet associé au CURP dans la base de données officielle. |
name_to_CURP_valid | boolean | Si le nom fourni est cohérent avec le CURP. |
is_mexican | boolean | Si le CURP correspond à un citoyen mexicain. |
deceased | boolean | Si le CURP est marqué comme décédé dans la base de données officielle. |
date_of_birth | string | Date de naissance décodée depuis le CURP (JJ/MM/AAAA). |
age | integer | Âge calculé de l'utilisateur. |
gender | string | Genre décodé depuis le CURP (M ou F). |
state_of_birth | string | État de naissance décodé depuis le CURP. |
state_iso | string | Code ISO 3166-2 de l'état de naissance. |
data.response.document.details — Détection de document et analyse forensique :
| Champ | Type | Description |
|---|---|---|
detected | boolean | Si un document a été détecté avec succès dans l'image. |
document_id | integer | Identifiant unique du document traité. |
forensics.is_valid | string | Résultat de l'analyse forensique : yes, no ou inconclusive. |
data.response.document.front.information — Champs extraits par OCR du recto de l'INE. Chaque champ contient text (valeur extraite) et valid (si une validation structurelle a pu être effectuée) :
| Champ | Description |
|---|---|
name | Prénom(s). |
last_name | Nom de famille paternel. |
mother_last_name | Nom de famille maternel. |
complete_name | Nom complet. |
birthdate | Date de naissance (JJ/MM/AAAA). |
sex | Sexe/genre (H ou M). |
curp | CURP extrait du document. |
electoral_key | Clé électorale. |
address | Adresse. |
registration_year | Année d'enregistrement du document. |
valid_thru | Année d'expiration du document. |
data.response.document.front.face_analysis — Analyse du visage trouvé sur l'INE :
| Champ | Type | Description |
|---|---|---|
face_id | integer | Identifiant unique pour cette instance de visage. |
face_id_v2 | integer | Identifiant unique (version 2). |
unique_face_id_v2 | integer | Identifiant persistant pour ce visage physique dans toutes les demandes. |
first_seen | string | Horodatage de la première fois que ce visage a été vu dans le système. |
last_seen | string | Horodatage de la dernière fois que ce visage a été vu dans le réseau. |
last_seen_by_your_company | string | Dernière fois que ce visage a été vu dans une demande de votre entreprise. |
inquiry_date | string | Horodatage de la demande de vérification actuelle. |
match | boolean | Si ce visage est une correspondance potentielle avec d'autres visages dans la base de données. |
match_fraud_flag | boolean | Si ce visage a été associé à une activité frauduleuse. |
seen_by_your_company | boolean | Si ce visage a déjà été vu par votre entreprise. |
seen_different_companies | integer | Nombre d'autres entreprises dans le réseau ayant vu ce visage. |
times_seen_by_your_company | integer | Nombre total de fois où ce visage a été vu dans les demandes de votre entreprise. |
times_seen_last_month | integer | Nombre de fois vu le mois dernier dans le réseau. |
warnings.external_id | string | Avertissement si le visage de l'utilisateur est associé à plusieurs identifiants externes. |
data.response.document.back — Données MRZ du verso de l'INE :
| Champ | Type | Description |
|---|---|---|
mrz | string | Chaîne complète de la Zone de Lecture Automatique (MRZ). |
cic | string | Numéro CIC extrait du MRZ. |
citizen_id | string | Numéro d'identification du citoyen extrait du MRZ. |
data.response.selfie — Analyse du selfie capturé :
| Champ | Type | Description |
|---|---|---|
face_id | integer | Identifiant unique pour l'instance du visage du selfie. |
face_id_v2 | integer | Identifiant unique (version 2). |
unique_face_id_v2 | integer | Identifiant persistant pour ce visage physique dans toutes les demandes. |
first_seen | string | Première fois que le visage de ce selfie a été vu dans le système. |
first_seen_image | boolean | Si c'est la première fois que cette image exacte est vue. |
last_seen | string | Dernière fois que ce visage a été vu dans le réseau. |
last_seen_by_your_company | string | Dernière fois que ce visage a été vu par votre entreprise. |
inquiry_date | string | Horodatage de la demande de vérification actuelle. |
match | boolean | Si le visage du selfie correspond à d'autres visages dans la base de données. |
match_fraud_flag | boolean | Si le visage du selfie est associé à une activité frauduleuse. |
seen_by_your_company | boolean | Si ce visage a déjà été vu par votre entreprise. |
seen_different_companies | integer | Nombre d'autres entreprises dans le réseau ayant vu ce visage. |
times_seen_by_your_company | integer | Nombre total de fois où ce visage a été vu dans les demandes de votre entreprise. |
times_seen_last_month | integer | Nombre de fois vu le mois dernier dans le réseau. |
warnings | object | Avertissements spécifiques liés à l'analyse du selfie (même structure que document face_analysis). |
Utilisez le polling avec un backoff exponentiel — n'appelez pas en boucle serrée.
Réponses d'erreur — GET /v2/history/request
| Code | Message | Description |
|---|---|---|
400 Bad Request | Input should be a valid UUID, invalid group length... | Le paramètre magic_link_token est mal formé ou n'est pas un format UUID valide. |
404 Not Found | This magic link have no requests associated | Le token fourni existe mais n'a aucun processus KYC complété associé. L'utilisateur n'a peut-être pas encore terminé le parcours. |
500 Internal Server Error | internal server error | Échec de traitement côté serveur. Réessayez avec un backoff exponentiel. Si le problème persiste, contactez le support. |
Exemple de réponse 400 :
{
"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"
}
Exemple de réponse 404 :
{
"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"
}
Exemple de réponse 500 :
{
"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
}
}
Webhook
Trois événements webhook sont disponibles. Pour les activer, demandez la configuration à votre Chef de projet Onboarding en fournissant : URL de l'endpoint (HTTPS obligatoire), type d'authentification (basic_auth, api_key, oauth2 ou NoAuth), configuration d'authentification, nombre maximum de tentatives, intervalle de tentative (s) et délai d'attente (s).
Cet événement est envoyé à la fin du flux, lorsque le Decision Maker a terminé le traitement des informations envoyées.
{
"data": {
"images": {
"document_image": "base64str",
"document_image_back": "base64str",
"selfie": "base64str"
},
"response": {
"document": {
"details": {
"detected": true,
"forensics": {
"is_valid": "yes"
},
"document_id": 123
},
"front": {
"information": {
"birthdate": { "text": "14/11/1956", "valid": true },
"sex": { "text": "H", "valid": true },
"registration_year": { "text": "1998", "valid": true },
"name": { "text": "LUKE", "valid": true },
"mother_last_name": { "text": "ORGANA", "valid": true },
"last_name": { "text": "SKYWALKER", "valid": true },
"electoral_key": { "text": "GRCRSN82031007M500", "valid": true },
"curp": { "text": "GOCJ850627HDFRRL09", "valid": true },
"address": { "text": "DOMICILIO/ADDRESS, HARLINGEN, TX 78552", "valid": false },
"complete_name": { "text": "LUKE SKYWALKER", "valid": true },
"valid_thru": { "text": "2027", "valid": true }
},
"face_analysis": {
"face_id": 237437,
"first_seen": "12/22/2022, 18:54:09",
"unique_face_id_v2": 126880,
"face_id_v2": 199068,
"inquiry_date": "07/28/2025, 20:53:12",
"last_seen": "07/28/2025, 18:47:46",
"last_seen_by_your_company": "07/24/2025, 21:38:21",
"match": true,
"match_fraud_flag": true,
"seen_by_your_company": true,
"seen_different_companies": 46,
"times_seen_by_your_company": 3,
"times_seen_last_month": 111,
"warnings": {
"external_id": "User found in the company with other external_ids: ['abc-123']"
}
}
},
"back": {
"mrz": "IDMEX999999999999<9 VADER<SKYWALKER<<LUKE",
"cic": "237457894"
}
},
"selfie": {
"face_id": 237436,
"first_seen": "02/05/2025, 02:36:19",
"unique_face_id_v2": 494,
"face_id_v2": 4378,
"inquiry_date": "07/28/2025, 20:52:49",
"last_seen": "07/28/2025, 20:52:51",
"last_seen_by_your_company": "07/23/2025, 18:14:27",
"match": true,
"match_fraud_flag": true,
"seen_by_your_company": true,
"seen_different_companies": 2,
"times_seen_by_your_company": 2,
"times_seen_last_month": 7,
"warnings": {
"external_id": "User found in the company with other external_ids: ['abc-123']"
},
"first_seen_image": true
},
"face_match": false,
"curp": {
"curp": "GOCJ850627HDFRRL09",
"state_of_birth": "Nuevo León",
"state_iso": "MX-NLE",
"date_of_birth": "14/11/1956",
"age": 58,
"gender": "M",
"is_mexican": true,
"name_to_CURP_valid": true,
"government_valid": true,
"government_name": "LUKE SKYWALKER",
"deceased": false
},
"unico": {
"process_id": "d333dfac-9ddb-4066-8e2c-44eaf4c86b4a",
"result": "PROCESS_RESULT_LIVE"
},
"label": null,
"reason": null,
"request_id": "d1kxp9ah8f0s71uv9zx0"
},
"user_id": null
},
"event": "MAGIC_LINK_RESULTS",
"magic_link_token": "3f6dbcc1-49ba-4935-be90-dd8dd59b5530",
"user_id": null,
"date": "2025-10-03T21:15:41.299815"
}
Ces événements sont reçus lorsque l'utilisateur a complété une action. Par exemple, form_start sera reçu lorsque l'utilisateur capture le recto du document, ce qui signifie qu'il a cliqué et complété le premier écran.
{
"data": {
"completed_on": "Fri, 03 Oct 2025 21:15:35 GMT",
"started_on": "Fri, 03 Oct 2025 21:15:30 GMT",
"step": "form_start",
"user_id": null
},
"event": "MAGIC_LINK_TRACK",
"magic_link_token": "3f6dbcc1-49ba-4935-be90-dd8dd59b5530",
"user_id": null,
"date": "2025-10-03T21:15:41.299815"
}
| Champ | Type | Description |
|---|---|---|
data.step | string | Nom de l'étape complétée. |
data.user_id | string (nullable) | Identifiant externe défini dans le magic link. |
data.started_on | datetime | Heure de début de l'étape (fuseau UTC). |
data.completed_on | datetime | Heure de fin de l'étape (fuseau UTC). |
event | string | Identifiant du type d'événement. |
magic_link_token | uuid | Token unique du magic link. |
user_id | string (nullable) | Identifiant externe. |
date | datetime | Horodatage de l'événement. |
Étapes supportées :
| Étape | Description |
|---|---|
form_start | L'utilisateur a cliqué sur le bouton initial du magic link. |
form_document_front | L'utilisateur a complété la capture du recto de l'INE. |
form_document_back | L'utilisateur a complété la capture du verso de l'INE. |
form_document | L'utilisateur a complété les processus recto et verso. |
form_selfie | L'utilisateur a complété le processus de liveness. |
form_decision_maker | L'utilisateur a complété l'intégralité du flux. |
Cet événement est envoyé lorsqu'une nouvelle capture de document est requise, soit lors du processus recto, soit lors du processus verso. Il indique que des données critiques de l'INE n'ont pas pu être lues.
{
"data": {
"document_type": "ine_front",
"invalid_back_ocr": false,
"invalid_curp": false,
"invalid_document": true
},
"event": "MAGIC_LINK_DOCUMENT_RETAKE_REASONS",
"magic_link_token": "3f6dbcc1-49ba-4935-be90-dd8dd59b5530",
"user_id": null,
"date": "2025-10-03T21:12:00.000Z"
}
| Champ | Type | Description |
|---|---|---|
data.document_type | string | Côté du document : ine_front ou ine_back. |
data.invalid_document | boolean | true si l'image capturée n'est pas un INE valide (recto ou verso). |
data.invalid_curp | boolean | true si le CURP n'a pas pu être lu (ine_front uniquement). |
data.invalid_back_ocr | boolean | true si le code MRZ n'a pas pu être lu (ine_back uniquement). |
event | string | Identifiant du type d'événement. |
magic_link_token | uuid | Token unique du magic link. |
user_id | string (nullable) | Identifiant externe. |
date | datetime | Horodatage de l'événement. |
La charge utile est conçue de sorte qu'une seule erreur (true) soit reçue pour chaque côté du document.
Scénarios d'échec — recto INE :
- Document invalide → uniquement
invalid_document: true - Échec de lecture du CURP → uniquement
invalid_curp: true
Scénarios d'échec — verso INE :
- Document invalide → uniquement
invalid_document: true - Échec de lecture du MRZ → uniquement
invalid_back_ocr: true
Si vous envoyez encore webhook_url dans les metadata de la requête (Webhook V1), cette configuration prend la priorité sur la V2 globale. Pour migrer, supprimez webhook_url des metadata et configurez la V2 avec votre Chef de projet Onboarding.
Personnalisations
La page Magic Link hébergée ne prend pas en charge la personnalisation visuelle par le client — elle suit l'identité visuelle Unico/Trully par défaut. Pour personnaliser le parcours (logo, couleurs, textes), utilisez Onboarding (Global) avec SDK ou Web.
Disponibilité : Mexique · Endpoint : POST https://api.trully.ai/v2/magic-link · Document : INE · Auth : x-api-key (Trully)