KYC Magic Link
Este caso de uso não utiliza o endpoint POST /v1/process da Unico nem o contrato API/TCA. A integração é com a Trully.ai (host api.trully.ai), com autenticação via x-api-key em vez de Bearer JWT, e um schema de resposta proprietário. Para outros países, use Onboarding (Global).
O que este caso de uso resolve
O KYC Magic Link endereça o desafio de executar o processo de identificação no México, coletando documentos de identidade nacional (INE) e biometria facial. Com uma jornada hospedada pela Unico, você elimina a fricção de desenvolvimento front-end por meio de um link enviado pelos seus próprios canais (WhatsApp, SMS, e-mail).
Use este caso de uso quando:
- Você opera no México e o documento de identidade utilizado é o INE (obrigatório).
Não use este caso de uso quando:
- O usuário está fora do México ou utiliza outros documentos → consulte os outros casos de uso de onboarding.
Capacidades envolvidas
Pipeline executado dentro de um único processo:
| Capacidade | Obrigatória | Papel no fluxo |
|---|---|---|
| Captura de Documento | Obrigatória | Captura a imagem do documento INE. O reuso de documento não está disponível neste caso de uso — cada sessão requer uma nova captura. |
| Liveness | Obrigatória | Verificação de vivacidade — selfie obrigatória que ancora o processo. |
| Classificação de Risco | Obrigatória | Cruza sinais comportamentais para sinalizar risco de fraude associado ao CPF. |
| Verificação de Identidade | Opcional (se contratada) | Verifica se o rosto da transação pertence ao titular do identificador governamental fornecido, usando a base de identidade da Unico e sinais adicionais. |
Pré-requisitos
- Chave de API — provisionada pelo seu Gerente de Projeto de Onboarding na Unico. Enviada no header
x-api-key. - Endpoint HTTPS público para receber webhooks (opcional, mas recomendado).
- Configuração de CORS — permita as origens
https://verification.unico.app(produção) ehttps://verification.uat.unico.app(sandbox) no servidor que recebe o webhook.
Implementação passo a passo
Diferentemente de outros casos de uso, o Magic Link não possui campo flow — a integração é direta com a API Trully. O endpoint cria um link de verificação único que você distribui ao usuário pelo seu próprio canal.
Endpoint: POST https://sandbox.trully.ai/v2/magic-link
Headers:
| Header | Obrigatório | Descrição |
|---|---|---|
x-api-key | Sim | Chave de API provisionada pelo seu Gerente de Projeto de Onboarding na Unico. |
Content-Type | Sim | application/json |
Body (application/json):
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
external_id | string | Não | Um identificador externo para a requisição, utilizado para fins de rastreamento e referência. |
metadata | object | Não | Container para parâmetros de configuração. |
metadata.phone | string | Não | Número de telefone do usuário no formato internacional (ex.: 521234567890). |
metadata.redirect_url | string | Não | URL para redirecionar o usuário após a conclusão do processo de KYC. |
metadata.webhook_url | string | Não | URL para enviar os dados do processo de KYC após sua conclusão. Este webhook será chamado no lado do cliente. Por razões de segurança, o endpoint deve usar HTTPS. O componente aguardará um minuto pela resposta do seu servidor de webhook — após isso, encerrará a comunicação. O processo não será afetado de forma alguma pela comunicação via webhook. Certifique-se de permitir https://verification.unico.app e https://verification.uat.unico.app na sua configuração de CORS para produção e sandbox, respectivamente. |
metadata.track_webhook_url | string | Não | URL para enviar cada etapa do KYC processada pelo usuário (veja os eventos de webhook abaixo). Este webhook será chamado no lado do cliente. Por razões de segurança, o endpoint deve usar HTTPS. O componente aguardará um minuto pela resposta do seu servidor de webhook — após isso, encerrará a comunicação. O processo não será afetado de forma alguma pela comunicação via webhook. Certifique-se de permitir https://verification.unico.app e https://verification.uat.unico.app na sua configuração de CORS para produção e sandbox, respectivamente. |
Valores possíveis para data.step (enviados para track_webhook_url):
| Etapa | Descrição |
|---|---|
form_start | O usuário está atualmente digitalizando o documento. |
form_document_front | O usuário já capturou a frente do INE. |
form_document_back | O usuário já capturou o verso do INE. |
form_document | O processo está atualmente na etapa de selfie. |
form_selfie | O usuário chegou à etapa final da operação. |
form_decision_maker | A operação retorna a resposta do sistema. |
Exemplo de requisição:
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"
}
}'
Campos da resposta:
| Campo | Tipo | Descrição |
|---|---|---|
data.external_id | string (nullable) | Um identificador externo para a requisição, utilizado para fins de rastreamento e referência. |
data.created_on | string (date-time) | A data em que o magic link foi criado. |
data.is_active | boolean | Se true, o magic link está ativo. |
data.token | string | O token do magic link que será usado para vincular os processos de KYC ao magic link. |
data.magic_link_url | string (URI) | A URL do magic link para iniciar o processo de KYC. |
data.metadata.redirect_url | string (nullable) | URL para redirecionar o usuário após a conclusão do processo de KYC. |
data.metadata.webhook_url | string (nullable) | URL para enviar os dados do processo de KYC após sua conclusão. Este webhook será chamado no lado do cliente. |
data.metadata.track_webhook_url | string (nullable) | URL para enviar cada etapa do KYC processada pelo usuário. Este webhook será chamado no lado do cliente. |
data.version | string | A versão do magic link. |
version | string | A versão da API que processou a requisição, útil para rastrear mudanças e compatibilidade. |
status | string | Representação textual do status da resposta, indicando sucesso ou falha da operação. |
status_code | integer | O código de status HTTP da resposta, fornecendo um indicador padronizado do resultado da requisição. |
request_date | string (date-time) | A data e hora em que a requisição foi feita, no formato ISO 8601. |
request.metadata.redirect_url | string (nullable) | URL para redirecionar o usuário após a conclusão do processo de KYC (eco da requisição). |
request.metadata.webhook_url | string (nullable) | URL para enviar os dados do processo de KYC após a conclusão (eco da requisição). |
request.metadata.track_webhook_url | string (nullable) | URL para enviar cada etapa do KYC processada pelo usuário (eco da requisição). |
Exemplo de resposta:
{
"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
}
}
}
Respostas de erro — POST /v2/magic-link
| Código | Mensagem | Descrição |
|---|---|---|
400 Bad Request | data provided in the field is invalid | Estrutura de dados inválida ou valores de campo inválidos no payload da requisição. Verifique os campos obrigatórios e os formatos. |
403 Forbidden | Forbidden | Chave de API ausente, expirada ou sem permissão. Verifique o header x-api-key. |
500 Internal Server Error | internal server error | Falha de processamento no servidor. Tente novamente com backoff exponencial. Se persistir, reporte ao suporte. |
Exemplo de resposta 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
}
}
Envie via WhatsApp, SMS, e-mail ou incorpore. O usuário acessa o link em seu próprio dispositivo e conclui a jornada hospedada.
- Polling via GET (obrigatório) — chame
GET /v2/history/request?magic_link_token={token}periodicamente até queunico.resultseja preenchido. Veja Polling via GET abaixo. - Webhook (opcional) — configure com seu PM de Onboarding para receber eventos automaticamente. Veja Webhook abaixo.
Polling via GET
Endpoint: GET https://sandbox.trully.ai/v2/history/request
Parâmetros de query:
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
magic_link_token | string | Sim | Token retornado quando o Magic Link foi criado. |
Headers:
| Header | Obrigatório | Descrição |
|---|---|---|
x-api-key | Sim | Chave de API provisionada pelo seu Gerente de Projeto de Onboarding na Unico. |
Exemplo de requisição:
curl "https://sandbox.trully.ai/v2/history/request?magic_link_token=$TOKEN" \
-H "x-api-key: $TRULLY_API_KEY"
Exemplo de resposta:
{
"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,
"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"
}
Campos da resposta:
Nível raiz:
| Campo | Tipo | Descrição |
|---|---|---|
status | string | Representação textual do status da resposta. |
status_code | integer | Código de status HTTP. |
request_date | string (date-time) | A data e hora em que a requisição foi feita. |
version | string | Versão da API que processou a requisição. |
data.user_id | string | O ID do usuário definido na requisição original. |
data.images — Imagens capturadas em Base64:
| Campo | Tipo | Descrição |
|---|---|---|
data.images.document_image | string | Imagem codificada em Base64 da frente do documento. |
data.images.document_image_back | string | Imagem codificada em Base64 do verso do documento. |
data.images.selfie | string | Imagem de selfie codificada em Base64 capturada durante a verificação. |
data.response.unico — Veredicto consolidado:
| Campo | Tipo | Descrição |
|---|---|---|
data.response.unico.process_id | string (UUID) | Identificador interno relacionado ao processo de verificação. |
data.response.unico.result | string | Resultado do processo. Valores possíveis descritos abaixo. |
Valores possíveis para data.response.unico.result:
O valor do resultado codifica uma das três dimensões de avaliação:
- Avaliação de identidade — se o rosto capturado pertence ao titular do documento (
PROCESS_RESULT_VERIFIED,PROCESS_RESULT_NOT_APPROVED). - Comportamento de fraude — se sinais comportamentais ou de rede indicam risco de fraude (
PROCESS_RESULT_LIVE,PROCESS_RESULT_HIGH_RISK,PROCESS_RESULT_CRITICAL_RISK,PROCESS_RESULT_NOT_APPROVED). - Liveness — se um rosto ao vivo foi detectado no momento da captura (
PROCESS_RESULT_NOT_LIVE).
| Resultado | Recomendação | Significado | Sinal |
|---|---|---|---|
PROCESS_RESULT_ERROR | Rejeitar | O processo terminou com erro. | Sistema |
PROCESS_RESULT_VERIFIED | Aceitar | O usuário estava ativo no momento da captura; é o rosto do titular do documento e não foram encontradas evidências de fraude. | Identidade: confirmada |
PROCESS_RESULT_LIVE | Revisar / Aceitar | O usuário estava ativo no momento da captura; não encontramos evidências suficientes para garantir que é o titular do documento e não há evidências de fraude. | Identidade: inconclusiva · Fraude: nenhuma |
PROCESS_RESULT_HIGH_RISK | Recomenda rejeição | Encontramos pelo menos uma evidência forte de fraude. A decisão final é sua. | Comportamento de fraude: 1 sinal forte |
PROCESS_RESULT_CRITICAL_RISK | Recomenda rejeição | Encontramos pelo menos 2 evidências fortes de fraude. A decisão final é sua. | Comportamento de fraude: 2+ sinais fortes |
PROCESS_RESULT_NOT_APPROVED | Rejeitar | Rejeição recomendada pois múltiplas indicações de fraude foram detectadas. | Identidade: rejeitada · Comportamento de fraude: múltiplos sinais |
PROCESS_RESULT_NOT_LIVE | Permitir até 2 tentativas | O usuário não estava ao vivo no momento da captura, embora não tenham sido encontradas outras indicações de fraude. | Liveness: face não está ao vivo |
PROCESS_RESULT_VERIFIED requer ativação. Por padrão, este resultado não está ativo — alinhe com seu Gerente de Projeto da Unico se desejar habilitá-lo.
Sinais auxiliares para sua decisão:
Para casos LIVE, HIGH_RISK ou CRITICAL_RISK, complemente sua decisão com estes campos:
| Campo | Tipo | Significado |
|---|---|---|
face_match | boolean | Status de correspondência facial entre o documento e a selfie. |
document.front.face_analysis.match_fraud_flag | boolean | Se o rosto do documento foi associado a atividade fraudulenta. |
selfie.match_fraud_flag | boolean | Se o rosto da selfie foi associado a atividade fraudulenta. |
warnings.external_id | string | Aviso indicando que o rosto do usuário está associado a múltiplos IDs externos. |
data.response — Sinais de resultado de alto nível:
| Campo | Tipo | Descrição |
|---|---|---|
data.response.face_match | boolean | Se o rosto da selfie corresponde ao rosto do documento. |
data.response.label | string (nullable) | Reservado para resultados de sub-processos específicos; null se não aplicável. |
data.response.reason | string (nullable) | Razões para o rótulo atribuído. |
data.response.request_id | string | Identificador único para a requisição da API. |
data.response.curp — Validação do CURP contra o RENAPO:
| Campo | Tipo | Descrição |
|---|---|---|
curp | string | A string do CURP sendo analisada. |
government_valid | boolean | Se o CURP é válido de acordo com o RENAPO. |
government_name | string | Nome completo associado ao CURP no banco de dados oficial. |
name_to_CURP_valid | boolean | Se o nome fornecido é consistente com o CURP. |
is_mexican | boolean | Se o CURP corresponde a um cidadão mexicano. |
deceased | boolean | Se o CURP está marcado como falecido no banco de dados oficial. |
date_of_birth | string | Data de nascimento decodificada do CURP (DD/MM/YYYY). |
age | integer | Idade calculada do usuário. |
gender | string | Gênero decodificado do CURP (M ou F). |
state_of_birth | string | Estado de nascimento decodificado do CURP. |
state_iso | string | Código ISO 3166-2 para o estado de nascimento. |
data.response.document.details — Detecção e análise forense do documento:
| Campo | Tipo | Descrição |
|---|---|---|
detected | boolean | Se um documento foi detectado com sucesso na imagem. |
document_id | integer | Identificador único para o documento processado. |
forensics.is_valid | string | Resultado da análise forense: yes, no ou inconclusive. |
data.response.document.front.information — Campos extraídos por OCR da frente do INE. Cada campo contém text (valor extraído) e valid (se pôde ser estruturalmente validado):
| Campo | Descrição |
|---|---|
name | Primeiro(s) nome(s). |
last_name | Sobrenome paterno. |
mother_last_name | Sobrenome materno. |
complete_name | Nome completo. |
birthdate | Data de nascimento (DD/MM/YYYY). |
sex | Sexo/gênero (H ou M). |
curp | CURP extraído do documento. |
electoral_key | Chave eleitoral. |
address | Endereço. |
registration_year | Ano em que o documento foi registrado. |
valid_thru | Ano de vencimento do documento. |
data.response.document.front.face_analysis — Análise do rosto encontrado no INE:
| Campo | Tipo | Descrição |
|---|---|---|
face_id | integer | Identificador único para esta instância de rosto. |
face_id_v2 | integer | Identificador único (versão 2). |
unique_face_id_v2 | integer | Identificador persistente para este rosto físico em todas as consultas. |
first_seen | string | Timestamp da primeira vez que este rosto foi visto no sistema. |
last_seen | string | Timestamp da vez mais recente em que este rosto foi visto na rede. |
last_seen_by_your_company | string | Última vez em que este rosto foi visto em uma consulta pela sua empresa. |
inquiry_date | string | Timestamp da consulta de verificação atual. |
match | boolean | Se este rosto é uma correspondência potencial com outros rostos no banco de dados. |
match_fraud_flag | boolean | Se este rosto foi associado a atividade fraudulenta. |
seen_by_your_company | boolean | Se este rosto foi visto anteriormente pela sua empresa. |
seen_different_companies | integer | Número de outras empresas na rede que viram este rosto. |
times_seen_by_your_company | integer | Total de vezes que este rosto foi visto em consultas pela sua empresa. |
times_seen_last_month | integer | Número de vezes visto no último mês em toda a rede. |
warnings.external_id | string | Aviso se o rosto do usuário está associado a múltiplos IDs externos. |
data.response.document.back — Dados MRZ do verso do INE:
| Campo | Tipo | Descrição |
|---|---|---|
mrz | string | String completa da Zona de Leitura por Máquina (MRZ). |
cic | string | Número CIC extraído do MRZ. |
citizen_id | string | Número de identificação do cidadão do MRZ. |
data.response.selfie — Análise da selfie capturada:
| Campo | Tipo | Descrição |
|---|---|---|
face_id | integer | Identificador único para a instância de rosto da selfie. |
face_id_v2 | integer | Identificador único (versão 2). |
unique_face_id_v2 | integer | Identificador persistente para este rosto físico em todas as consultas. |
first_seen | string | Primeira vez que o rosto desta selfie foi visto no sistema. |
first_seen_image | boolean | Se esta é a primeira vez que esta imagem exata foi vista. |
last_seen | string | Vez mais recente em que este rosto foi visto na rede. |
last_seen_by_your_company | string | Vez mais recente em que este rosto foi visto pela sua empresa. |
inquiry_date | string | Timestamp da consulta de verificação atual. |
match | boolean | Se o rosto da selfie corresponde a outros rostos no banco de dados. |
match_fraud_flag | boolean | Se o rosto da selfie está associado a atividade fraudulenta. |
seen_by_your_company | boolean | Se este rosto foi visto anteriormente pela sua empresa. |
seen_different_companies | integer | Número de outras empresas na rede que viram este rosto. |
times_seen_by_your_company | integer | Total de vezes que este rosto foi visto em consultas pela sua empresa. |
times_seen_last_month | integer | Número de vezes visto no último mês em toda a rede. |
warnings | object | Avisos específicos relacionados à análise da selfie (mesma estrutura do face_analysis do documento). |
Use polling com backoff exponencial — não chame em loop contínuo.
Respostas de erro — GET /v2/history/request
| Código | Mensagem | Descrição |
|---|---|---|
400 Bad Request | Input should be a valid UUID, invalid group length... | O parâmetro magic_link_token está malformado ou não é um formato UUID válido. |
404 Not Found | This magic link have no requests associated | O token fornecido existe, mas não há processos de KYC concluídos vinculados a ele. O usuário pode não ter finalizado a jornada ainda. |
500 Internal Server Error | internal server error | Falha de processamento no servidor. Tente novamente com backoff exponencial. Se persistir, reporte ao suporte. |
Exemplo de resposta 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"
}
Exemplo de resposta 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"
}
Exemplo de resposta 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
Três eventos de webhook estão disponíveis. Para ativá-los, solicite a configuração ao seu Gerente de Projeto de Onboarding, fornecendo: URL do endpoint (HTTPS obrigatório), tipo de autenticação (basic_auth, api_key, oauth2 ou NoAuth), configuração de autenticação, número máximo de tentativas, intervalo de reenvio (s) e timeout (s).
Este evento é enviado ao final do fluxo, quando o Decision Maker terminou de processar as informações enviadas.
{
"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"
}
Esses eventos são recebidos quando o usuário concluiu uma ação. Por exemplo, form_start será recebido quando o usuário estiver fotografando o documento, o que significa que o usuário clicou e completou a primeira tela.
{
"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"
}
| Campo | Tipo | Descrição |
|---|---|---|
data.step | string | Nome da etapa concluída. |
data.user_id | string (nullable) | ID externo definido no magic link. |
data.started_on | datetime | Horário de início da etapa no fuso horário UTC. |
data.completed_on | datetime | Horário de conclusão da etapa no fuso horário UTC. |
event | string | Identificador do tipo de evento. |
magic_link_token | uuid | Token único do magic link. |
user_id | string (nullable) | Identificador externo. |
date | datetime | Timestamp do evento. |
Etapas suportadas:
| Etapa | Descrição |
|---|---|
form_start | Usuário clicou no botão inicial do magic link. |
form_document_front | Usuário completou a captura da frente do INE. |
form_document_back | Usuário completou a captura do verso do INE. |
form_document | Usuário completou os processos da frente e do verso. |
form_selfie | Usuário completou o processo de liveness. |
form_decision_maker | Usuário completou todo o fluxo. |
Este evento é enviado quando uma recaptura de documento é necessária, seja durante o processo da frente ou do verso. Indica que dados críticos do INE não puderam ser lidos.
{
"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"
}
| Campo | Tipo | Descrição |
|---|---|---|
data.document_type | string | Lado do documento: ine_front ou ine_back. |
data.invalid_document | boolean | true se a imagem capturada não é um INE válido (qualquer lado). |
data.invalid_curp | boolean | true se o CURP não pôde ser lido (apenas ine_front). |
data.invalid_back_ocr | boolean | true se o código MRZ não pôde ser lido (apenas ine_back). |
event | string | Identificador do tipo de evento. |
magic_link_token | uuid | Token único do magic link. |
user_id | string (nullable) | Identificador externo. |
date | datetime | Timestamp do evento. |
O payload é projetado para que apenas um erro (true) seja recebido para cada lado do documento.
Cenários de falha — frente do INE:
- Documento inválido → apenas
invalid_document: true - Falha na leitura do CURP → apenas
invalid_curp: true
Cenários de falha — verso do INE:
- Documento inválido → apenas
invalid_document: true - Falha na leitura do MRZ → apenas
invalid_back_ocr: true
Se você ainda envia webhook_url no metadata da requisição (Webhook V1), essa configuração tem precedência sobre o V2 global. Para migrar, remova webhook_url do metadata e configure o V2 com seu PM de Onboarding.
Personalizações
A página hospedada do Magic Link não suporta personalização visual pelo cliente — segue a identidade visual padrão da Unico/Trully. Para personalizar a jornada (logotipo, cores, textos), utilize Onboarding (Global) com SDK ou Web.
Disponibilidade: México · Endpoint: POST https://api.trully.ai/v2/magic-link · Documento: INE · Autenticação: x-api-key (Trully)