KYC Magic Link
이 사용 사례는 Unico의 POST /v1/process 엔드포인트나 API/TCA 계약을 사용하지 않습니다. 통합은 Trully.ai(호스트 api.trully.ai)와 이루어지며, Bearer JWT 대신 x-api-key를 통한 인증과 독자적인 응답 스키마를 사용합니다. 다른 국가의 경우 온보딩(글로벌)을 사용하십시오.
이 사용 사례가 해결하는 문제
KYC Magic Link는 멕시코에서 신원 확인 프로세스를 실행하고, 국가 신분증(INE)과 얼굴 생체 정보를 수집하는 문제를 해결합니다. Unico가 호스팅하는 여정을 통해 WhatsApp, SMS, 이메일 등 자체 채널로 전송하는 링크로 프론트엔드 개발 부담을 없앱니다.
이 사용 사례를 사용하는 경우:
- 멕시코에서 운영하며 신분증이 **INE(필수)**인 경우.
이 사용 사례를 사용하지 않는 경우:
- 사용자가 멕시코 외부에 있거나 다른 문서를 사용하는 경우 → 다른 온보딩 사용 사례를 참조하십시오.
관련 기능
단일 프로세스 내에서 실행되는 파이프라인:
| 기능 | 필수 여부 | 흐름에서의 역할 |
|---|---|---|
| 문서 캡처 | 필수 | INE 문서 이미지를 캡처합니다. 이 사용 사례에서는 문서 재사용이 불가합니다 — 매 세션마다 새로운 캡처가 필요합니다. |
| Liveness | 필수 | 생체 인증 확인 — 프로세스를 고정하는 필수 셀피입니다. |
| 위험 분류 | 필수 | 행동 신호를 교차 참조하여 CPF와 관련된 사기 위험을 표시합니다. |
| 신원 확인 | 선택(계약 시) | 트랜잭션 얼굴이 제공된 정부 식별자의 소유자에게 속하는지를 Unico의 신원 데이터베이스와 추가 신호를 활용하여 확인합니다. |
사전 요구 사항
- API 키 — Unico의 온보딩 프로젝트 매니저가 프로비저닝합니다.
x-api-key헤더로 전송됩니다. - 웹훅을 수신할 공개 HTTPS 엔드포인트 (선택 사항, 권장).
- CORS 구성 — 웹훅을 수신하는 서버에서
https://verification.unico.app(운영) 및https://verification.uat.unico.app(샌드박스) 출처를 허용합니다.
단계별 구현
다른 사용 사례와 달리, Magic Link에는 flow 필드가 없습니다 — Trully API와 직접 통합됩니다. 이 엔드포인트는 자체 채널을 통해 사용자에게 배포하는 고유한 검증 링크를 생성합니다.
엔드포인트: POST https://sandbox.trully.ai/v2/magic-link
헤더:
| 헤더 | 필수 여부 | 설명 |
|---|---|---|
x-api-key | 예 | Unico의 온보딩 프로젝트 매니저가 프로비저닝한 API 키. |
Content-Type | 예 | application/json |
본문(application/json):
| 필드 | 유형 | 필수 여부 | 설명 |
|---|---|---|---|
external_id | string | 아니오 | 추적 및 참조 목적으로 사용되는 요청의 외부 식별자. |
metadata | object | 아니오 | 구성 매개변수의 컨테이너. |
metadata.phone | string | 아니오 | 국제 형식의 사용자 전화번호(예: 521234567890). |
metadata.redirect_url | string | 아니오 | KYC 프로세스 완료 후 사용자를 리디렉션할 URL. |
metadata.webhook_url | string | 아니오 | KYC 프로세스 완료 후 KYC 프로세스 데이터를 전송할 URL. 이 웹훅은 클라이언트 측에서 호출됩니다. 보안상의 이유로 엔드포인트는 HTTPS를 사용해야 합니다. 컴포넌트는 웹훅 서버의 응답을 1분간 기다리며, 이후 통신을 중단합니다. 웹훅 통신에 의해 프로세스는 어떠한 영향도 받지 않습니다. CORS 구성에서 운영 환경은 https://verification.unico.app, 샌드박스 환경은 https://verification.uat.unico.app을 허용해야 합니다. |
metadata.track_webhook_url | string | 아니오 | 사용자가 처리한 각 KYC 단계를 전송할 URL(아래 웹훅 이벤트 참조). 이 웹훅은 클라이언트 측에서 호출됩니다. 보안상의 이유로 엔드포인트는 HTTPS를 사용해야 합니다. 컴포넌트는 웹훅 서버의 응답을 1분간 기다리며, 이후 통신을 중단합니다. 웹훅 통신에 의해 프로세스는 어떠한 영향도 받지 않습니다. CORS 구성에서 운영 환경은 https://verification.unico.app, 샌드박스 환경은 https://verification.uat.unico.app을 허용해야 합니다. |
track_webhook_url로 전송되는 data.step의 가능한 값:
| 단계 | 설명 |
|---|---|
form_start | 사용자가 현재 문서를 스캔 중입니다. |
form_document_front | 사용자가 INE 앞면을 이미 캡처했습니다. |
form_document_back | 사용자가 INE 뒷면을 이미 캡처했습니다. |
form_document | 프로세스가 현재 셀피 단계에 있습니다. |
form_selfie | 사용자가 작업의 마지막 단계에 도달했습니다. |
form_decision_maker | 작업이 시스템 응답을 반환합니다. |
요청 예시:
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"
}
}'
응답 필드:
| 필드 | 유형 | 설명 |
|---|---|---|
data.external_id | string (nullable) | 추적 및 참조 목적으로 사용되는 요청의 외부 식별자. |
data.created_on | string (date-time) | magic link가 생성된 날짜. |
data.is_active | boolean | true이면 magic link가 활성 상태입니다. |
data.token | string | KYC 프로세스를 magic link에 연결하는 데 사용되는 magic link의 토큰. |
data.magic_link_url | string (URI) | KYC 프로세스를 시작하기 위한 magic URL 링크. |
data.metadata.redirect_url | string (nullable) | KYC 프로세스 완료 후 사용자를 리디렉션할 URL. |
data.metadata.webhook_url | string (nullable) | KYC 프로세스 완료 후 KYC 프로세스 데이터를 전송할 URL. 이 웹훅은 클라이언트 측에서 호출됩니다. |
data.metadata.track_webhook_url | string (nullable) | 사용자가 처리한 각 KYC 단계를 전송할 URL. 이 웹훅은 클라이언트 측에서 호출됩니다. |
data.version | string | magic link의 버전. |
version | string | 요청을 처리한 API 버전으로, 변경 사항 추적 및 호환성 확인에 유용합니다. |
status | string | 작업의 성공 또는 실패를 나타내는 응답 상태의 텍스트 표현. |
status_code | integer | 요청 결과의 표준화된 지표를 제공하는 응답의 HTTP 상태 코드. |
request_date | string (date-time) | ISO 8601 형식으로 요청이 이루어진 날짜 및 시간. |
request.metadata.redirect_url | string (nullable) | KYC 프로세스 완료 후 사용자를 리디렉션할 URL(요청의 에코). |
request.metadata.webhook_url | string (nullable) | 완료 후 KYC 프로세스 데이터를 전송할 URL(요청의 에코). |
request.metadata.track_webhook_url | string (nullable) | 사용자가 처리한 각 KYC 단계를 전송할 URL(요청의 에코). |
응답 예시:
{
"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
}
}
}
오류 응답 — POST /v2/magic-link
| 코드 | 메시지 | 설명 |
|---|---|---|
400 Bad Request | data provided in the field is invalid | 요청 페이로드의 잘못된 데이터 구조 또는 필드 값. 필수 필드와 형식을 확인하십시오. |
403 Forbidden | Forbidden | API 키가 없거나 만료되었거나 권한이 없습니다. x-api-key 헤더를 확인하십시오. |
500 Internal Server Error | internal server error | 서버 측 처리 실패. 지수 백오프로 재시도하십시오. 지속되면 지원팀에 보고하십시오. |
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
}
}
WhatsApp, SMS, 이메일을 통해 전송하거나 임베드합니다. 사용자는 자신의 디바이스에서 링크에 접근하여 호스팅된 여정을 완료합니다.
- GET을 통한 폴링(필수) —
unico.result가 채워질 때까지GET /v2/history/request?magic_link_token={token}을 주기적으로 호출합니다. 아래 GET을 통한 폴링을 참조하십시오. - 웹훅(선택 사항) — 온보딩 PM과 함께 구성하여 이벤트를 자동으로 수신합니다. 아래 웹훅을 참조하십시오.
GET을 통한 폴링
엔드포인트: GET https://sandbox.trully.ai/v2/history/request
쿼리 매개변수:
| 매개변수 | 유형 | 필수 여부 | 설명 |
|---|---|---|---|
magic_link_token | string | 예 | Magic Link 생성 시 반환된 토큰. |
헤더:
| 헤더 | 필수 여부 | 설명 |
|---|---|---|
x-api-key | 예 | Unico의 온보딩 프로젝트 매니저가 프로비저닝한 API 키. |
요청 예시:
curl "https://sandbox.trully.ai/v2/history/request?magic_link_token=$TOKEN" \
-H "x-api-key: $TRULLY_API_KEY"
응답 예시:
{
"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"
}
응답 필드:
루트 레벨:
| 필드 | 유형 | 설명 |
|---|---|---|
status | string | 응답 상태의 텍스트 표현. |
status_code | integer | HTTP 상태 코드. |
request_date | string (date-time) | 요청이 이루어진 날짜 및 시간. |
version | string | 요청을 처리한 API 버전. |
data.user_id | string | 원래 요청에 설정된 사용자 ID. |
data.images — Base64 인코딩된 캡처 이미지:
| 필드 | 유형 | 설명 |
|---|---|---|
data.images.document_image | string | 문서 앞면의 Base64 인코딩 이미지. |
data.images.document_image_back | string | 문서 뒷면의 Base64 인코딩 이미지. |
data.images.selfie | string | 검증 중 캡처된 Base64 인코딩 셀피 이미지. |
data.response.unico — 종합 판정:
| 필드 | 유형 | 설명 |
|---|---|---|
data.response.unico.process_id | string (UUID) | 검증 프로세스와 관련된 내부 식별자. |
data.response.unico.result | string | 프로세스 결과. 가능한 값은 아래에 설명됩니다. |
data.response.unico.result의 가능한 값:
결과 값은 세 가지 평가 차원 중 하나를 인코딩합니다:
- 신원 평가 — 촬영된 얼굴이 문서 소지자에게 속하는지 여부(
PROCESS_RESULT_VERIFIED,PROCESS_RESULT_NOT_APPROVED). - 사기 행동 — 행동 또는 네트워크 신호가 사기 위험을 나타내는지 여부(
PROCESS_RESULT_LIVE,PROCESS_RESULT_HIGH_RISK,PROCESS_RESULT_CRITICAL_RISK,PROCESS_RESULT_NOT_APPROVED). - Liveness — 촬영 시 실제 얼굴이 감지되었는지 여부(
PROCESS_RESULT_NOT_LIVE).
| 결과 | 권고 사항 | 의미 | 신호 |
|---|---|---|---|
PROCESS_RESULT_ERROR | 거부 | 프로세스가 오류로 완료되었습니다. | 시스템 |
PROCESS_RESULT_VERIFIED | 승인 | 캡처 시 사용자가 활성 상태였으며, 신분증 소지자의 얼굴이고 사기 관련 증거가 발견되지 않았습니다. | 신원: 확인됨 |
PROCESS_RESULT_LIVE | 검토/승인 | 캡처 시 사용자가 활성 상태였으며, 신분증 소지자임을 보장할 충분한 증거를 찾지 못했고 사기 증거도 없습니다. | 신원: 불확실 · 사기: 없음 |
PROCESS_RESULT_HIGH_RISK | 거부 권고 | 강력한 사기 증거가 최소 1건 발견되었습니다. 최종 결정은 귀사에 있습니다. | 사기 행동: 강한 신호 1개 |
PROCESS_RESULT_CRITICAL_RISK | 거부 권고 | 강력한 사기 증거가 최소 2건 발견되었습니다. 최종 결정은 귀사에 있습니다. | 사기 행동: 강한 신호 2개 이상 |
PROCESS_RESULT_NOT_APPROVED | 거부 | 다수의 사기 징후가 감지되어 거부가 권고됩니다. | 신원: 거부됨 · 사기 행동: 복수 신호 |
PROCESS_RESULT_NOT_LIVE | 최대 2회 재시도 허용 | 캡처 시 사용자가 라이브 상태가 아니었지만, 다른 사기 징후는 발견되지 않았습니다. | Liveness: 얼굴이 라이브 아님 |
PROCESS_RESULT_VERIFIED는 활성화가 필요합니다. 기본적으로 이 결과는 활성화되지 않습니다 — 활성화하려면 Unico 프로젝트 매니저와 협의하십시오.
결정을 위한 보조 신호:
LIVE, HIGH_RISK 또는 CRITICAL_RISK 경우, 다음 필드로 결정을 보완하십시오:
| 필드 | 유형 | 의미 |
|---|---|---|
face_match | boolean | 문서와 셀피 간의 얼굴 매칭 상태. |
document.front.face_analysis.match_fraud_flag | boolean | 문서 얼굴이 사기 활동과 연관되어 있는지 여부. |
selfie.match_fraud_flag | boolean | 셀피 얼굴이 사기 활동과 연관되어 있는지 여부. |
warnings.external_id | string | 사용자의 얼굴이 여러 외부 ID와 연관되어 있다는 경고. |
data.response — 최상위 결과 신호:
| 필드 | 유형 | 설명 |
|---|---|---|
data.response.face_match | boolean | 셀피 얼굴이 문서 얼굴과 일치하는지 여부. |
data.response.label | string (nullable) | 특정 하위 프로세스의 결과를 위해 예약됨; 해당 사항 없을 시 null. |
data.response.reason | string (nullable) | 할당된 레이블의 이유. |
data.response.request_id | string | API 요청의 고유 식별자. |
data.response.curp — RENAPO 대상 CURP 검증:
| 필드 | 유형 | 설명 |
|---|---|---|
curp | string | 분석 중인 CURP 문자열. |
government_valid | boolean | RENAPO에 따라 CURP가 유효한지 여부. |
government_name | string | 공식 데이터베이스에서 CURP와 연결된 전체 이름. |
name_to_CURP_valid | boolean | 제공된 이름이 CURP와 일치하는지 여부. |
is_mexican | boolean | CURP가 멕시코 시민에 해당하는지 여부. |
deceased | boolean | 공식 데이터베이스에서 CURP가 사망으로 표시되어 있는지 여부. |
date_of_birth | string | CURP에서 디코딩된 생년월일(DD/MM/YYYY). |
age | integer | 계산된 사용자 나이. |
gender | string | CURP에서 디코딩된 성별(M 또는 F). |
state_of_birth | string | CURP에서 디코딩된 출생 주. |
state_iso | string | 출생 주의 ISO 3166-2 코드. |
data.response.document.details — 문서 감지 및 포렌식:
| 필드 | 유형 | 설명 |
|---|---|---|
detected | boolean | 이미지에서 문서가 성공적으로 감지되었는지 여부. |
document_id | integer | 처리된 문서의 고유 식별자. |
forensics.is_valid | string | 포렌식 분석 결과: yes, no 또는 inconclusive. |
data.response.document.front.information — INE 앞면에서 OCR로 추출된 필드. 각 필드에는 text(추출된 값)와 valid(구조적으로 검증 가능 여부)가 포함됩니다:
| 필드 | 설명 |
|---|---|
name | 이름. |
last_name | 부성. |
mother_last_name | 모성. |
complete_name | 전체 이름. |
birthdate | 생년월일(DD/MM/YYYY). |
sex | 성별(H 또는 M). |
curp | 문서에서 추출된 CURP. |
electoral_key | 선거 키. |
address | 주소. |
registration_year | 문서 등록 연도. |
valid_thru | 문서 만료 연도. |
data.response.document.front.face_analysis — INE에서 발견된 얼굴 분석:
| 필드 | 유형 | 설명 |
|---|---|---|
face_id | integer | 이 얼굴 인스턴스의 고유 식별자. |
face_id_v2 | integer | 고유 식별자(버전 2). |
unique_face_id_v2 | integer | 모든 조회에서 이 실제 얼굴에 대한 영구 식별자. |
first_seen | string | 이 얼굴이 시스템에서 처음 확인된 시간 타임스탬프. |
last_seen | string | 네트워크에서 이 얼굴이 가장 최근에 확인된 시간 타임스탬프. |
last_seen_by_your_company | string | 귀사의 조회에서 이 얼굴이 가장 최근에 확인된 시간. |
inquiry_date | string | 현재 검증 조회의 타임스탬프. |
match | boolean | 이 얼굴이 데이터베이스의 다른 얼굴과 잠재적으로 일치하는지 여부. |
match_fraud_flag | boolean | 이 얼굴이 사기 활동과 연관되어 있는지 여부. |
seen_by_your_company | boolean | 이 얼굴이 이전에 귀사에서 확인되었는지 여부. |
seen_different_companies | integer | 네트워크에서 이 얼굴을 확인한 다른 회사 수. |
times_seen_by_your_company | integer | 귀사 조회에서 이 얼굴이 확인된 총 횟수. |
times_seen_last_month | integer | 지난달 네트워크 전체에서 확인된 횟수. |
warnings.external_id | string | 사용자의 얼굴이 여러 외부 ID와 연관된 경우의 경고. |
data.response.document.back — INE 뒷면의 MRZ 데이터:
| 필드 | 유형 | 설명 |
|---|---|---|
mrz | string | 전체 기계 판독 영역 문자열. |
cic | string | MRZ에서 추출된 CIC 번호. |
citizen_id | string | MRZ에서 추출된 시민 식별 번호. |
data.response.selfie — 캡처된 셀피 분석:
| 필드 | 유형 | 설명 |
|---|---|---|
face_id | integer | 셀피 얼굴 인스턴스의 고유 식별자. |
face_id_v2 | integer | 고유 식별자(버전 2). |
unique_face_id_v2 | integer | 모든 조회에서 이 실제 얼굴에 대한 영구 식별자. |
first_seen | string | 이 셀피의 얼굴이 시스템에서 처음 확인된 시간. |
first_seen_image | boolean | 이 정확한 이미지가 처음 확인되었는지 여부. |
last_seen | string | 네트워크에서 이 얼굴이 가장 최근에 확인된 시간. |
last_seen_by_your_company | string | 귀사에서 이 얼굴이 가장 최근에 확인된 시간. |
inquiry_date | string | 현재 검증 조회의 타임스탬프. |
match | boolean | 셀피 얼굴이 데이터베이스의 다른 얼굴과 일치하는지 여부. |
match_fraud_flag | boolean | 셀피 얼굴이 사기 활동과 연관되어 있는지 여부. |
seen_by_your_company | boolean | 이 얼굴이 이전에 귀사에서 확인되었는지 여부. |
seen_different_companies | integer | 네트워크에서 이 얼굴을 확인한 다른 회사 수. |
times_seen_by_your_company | integer | 귀사 조회에서 이 얼굴이 확인된 총 횟수. |
times_seen_last_month | integer | 지난달 네트워크 전체에서 확인된 횟수. |
warnings | object | 셀피 분석과 관련된 특정 경고(document face_analysis와 동일한 구조). |
지수 백오프로 폴링하십시오 — 촘촘한 루프에서 호출하지 마십시오.
오류 응답 — GET /v2/history/request
| 코드 | 메시지 | 설명 |
|---|---|---|
400 Bad Request | Input should be a valid UUID, invalid group length... | magic_link_token 매개변수의 형식이 잘못되었거나 유효한 UUID 형식이 아닙니다. |
404 Not Found | This magic link have no requests associated | 제공된 토큰은 존재하지만 연결된 완료된 KYC 프로세스가 없습니다. 사용자가 아직 여정을 완료하지 않았을 수 있습니다. |
500 Internal Server Error | internal server error | 서버 측 처리 실패. 지수 백오프로 재시도하십시오. 지속되면 지원팀에 보고하십시오. |
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"
}
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"
}
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
}
}
웹훅
세 가지 웹훅 이벤트를 사용할 수 있습니다. 활성화하려면 온보딩 프로젝트 매니저에게 다음 정보를 제공하여 설정을 요청하십시오: 엔드포인트 URL(HTTPS 필수), 인증 유형(basic_auth, api_key, oauth2 또는 NoAuth), 인증 구성, 최대 재시도 횟수, 재시도 간격(초) 및 타임아웃(초).
이 이벤트는 흐름 종료 시, Decision Maker가 전송된 정보 처리를 완료했을 때 전송됩니다.
{
"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"
}
이 이벤트는 사용자가 작업을 완료했을 때 수신됩니다. 예를 들어, form_start는 사용자가 문서 앞면을 촬영 중일 때, 즉 첫 번째 화면을 클릭하고 완료했을 때 수신됩니다.
{
"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"
}
| 필드 | 유형 | 설명 |
|---|---|---|
data.step | string | 완료된 단계의 이름. |
data.user_id | string (nullable) | magic link에 설정된 외부 ID. |
data.started_on | datetime | UTC 타임존 단계 시작 시간. |
data.completed_on | datetime | UTC 타임존 단계 완료 시간. |
event | string | 이벤트 유형 식별자. |
magic_link_token | uuid | 고유한 magic link 토큰. |
user_id | string (nullable) | 외부 식별자. |
date | datetime | 이벤트 타임스탬프. |
지원되는 단계:
| 단계 | 설명 |
|---|---|
form_start | 사용자가 초기 magic link 버튼을 클릭했습니다. |
form_document_front | 사용자가 INE 앞면 캡처를 완료했습니다. |
form_document_back | 사용자가 INE 뒷면 캡처를 완료했습니다. |
form_document | 사용자가 앞면과 뒷면 프로세스를 모두 완료했습니다. |
form_selfie | 사용자가 라이브니스 프로세스를 완료했습니다. |
form_decision_maker | 사용자가 전체 흐름을 완료했습니다. |
이 이벤트는 앞면 또는 뒷면 프로세스 중 문서 재촬영이 필요할 때 전송됩니다. INE에서 중요한 데이터를 읽을 수 없었음을 나타냅니다.
{
"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"
}
| 필드 | 유형 | 설명 |
|---|---|---|
data.document_type | string | 문서 면: ine_front 또는 ine_back. |
data.invalid_document | boolean | 캡처된 이미지가 유효한 INE(어느 면이든)가 아닌 경우 true. |
data.invalid_curp | boolean | CURP를 읽을 수 없는 경우 true(ine_front만 해당). |
data.invalid_back_ocr | boolean | MRZ 코드를 읽을 수 없는 경우 true(ine_back만 해당). |
event | string | 이벤트 유형 식별자. |
magic_link_token | uuid | 고유한 magic link 토큰. |
user_id | string (nullable) | 외부 식별자. |
date | datetime | 이벤트 타임스탬프. |
페이로드는 각 문서 면에 대해 오류(true)가 하나만 수신되도록 설계되었습니다.
실패 시나리오 — INE 앞면:
- 유효하지 않은 문서 →
invalid_document: true만 - CURP 읽기 실패 →
invalid_curp: true만
실패 시나리오 — INE 뒷면:
- 유효하지 않은 문서 →
invalid_document: true만 - MRZ 읽기 실패 →
invalid_back_ocr: true만
요청의 metadata에 webhook_url을 계속 전송하는 경우(웹훅 V1), 해당 구성이 글로벌 V2보다 우선 적용됩니다. 마이그레이션하려면 metadata에서 webhook_url을 제거하고 온보딩 PM과 함께 V2를 구성하십시오.
커스터마이징
호스팅된 Magic Link 페이지는 클라이언트의 시각적 커스터마이징을 지원하지 않습니다 — 기본 Unico/Trully 시각적 아이덴티티를 따릅니다. 여정을 커스터마이징하려면(로고, 색상, 텍스트) SDK 또는 Web과 함께 온보딩(글로벌)을 사용하십시오.
제공 지역: 멕시코 · 엔드포인트: POST https://api.trully.ai/v2/magic-link · 문서: INE · 인증: x-api-key(Trully)