> ## Documentation Index
> Fetch the complete documentation index at: https://docs.didit.me/llms.txt
> Use this file to discover all available pages before exploring further.

# Didit 데이터 모델 JSON 스키마

> Didit 보고서 객체의 표준 JSON 스키마입니다. NFC, 신분증, 라이브니스, 얼굴 대조, AML, IP, 주소 증명, 전화번호, 이메일, KYB 법인 등기부, 문서, 주요 인물을 다룹니다.

## 개요

모든 기능별 보고서는 `service-didit-verification`에 정의된 V3 직렬화 형식을 따릅니다. 같은 객체가 세 곳에 나타나므로, 여기서 보는 스키마가 이 세 곳 전체의 단일 기준입니다.

* `GET /v3/session/{sessionId}/decision/`: 각 기능은 복수형 배열로 반환됩니다(`id_verifications[]`, `nfc_verifications[]`, `liveness_checks[]`, `face_matches[]`, `poa_verifications[]`, `phone_verifications[]`, `email_verifications[]`, `aml_screenings[]`, `ip_analyses[]`, `database_validations[]`, `questionnaire_responses[]`, `signatures[]`, `bank_verifications[]`([은행 인증 방법](https://docs.didit.me/ko/core-technology/bank-verification/verification-methods.md#결과에서-인증-방법-확인) 참조), 그리고 KYB 대응 항목인 `registry_checks[]`, `document_verifications[]`, `key_people_checks[]`).
* webhook payload(`status.updated`, `data.updated`): `decision` 래퍼 안에 같은 형식이 포함됩니다.
* 독립형 API: 단일 객체 응답(얼굴 검색, 연령 추정, 생체 인증)은 같은 필드 집합을 재사용합니다.

> [!NOTE]
>
> V3에서 다중 인스턴스 워크플로가 도입되었습니다. 모든 기능 객체는 `node_id`를 포함하며, 이 값은 보고서를 생성한 워크플로 그래프 노드에 고정합니다. V2 endpoint(단수형 `kyc`, `face`, `aml` 등)는 하위 호환성을 유지하지만 첫 번째 인스턴스만 반환합니다.

## 공통 필드

모든 보고서 객체는 다음 필드를 제공합니다.

| 필드 | 유형 | 설명 |
| - | - | - |
| `status` | string | 기능 수준의 수명 주기 상태이며, [상태 열거형](#상태-열거형-참조)의 값 중 하나입니다. 출처: `common/config/choices.py:FeatureStatusChoices`(343-348행). 상위 세션의 최상위 `status`는 더 넓은 세션 열거형(`StatusChoices`, 106-117행)을 사용합니다. |
| `node_id` | string \| null | 워크플로 그래프 노드 식별자입니다. V3 다중 인스턴스 워크플로에서 채워지며, 레거시 단일 기능 세션에서는 `null`입니다. |
| `warnings` | [경고 객체](#경고-객체)의 배열 | 이 기능과 `node_id`로 필터링된 위험 신호입니다. `Session.get_logs(...)`(`sessions/models/session.py:1611`)가 반환합니다. |

미디어 필드(`portrait_image`, `front_image`, `document_file` 등)는 유효 기간이 제한된 사전 서명 URL입니다. URL을 저장하지 말고 즉시 다운로드하십시오. 예시에서는 이를 `https://<media-host>/...`로 표시합니다.

## 경고 객체

모든 `warnings[]` 배열에 포함됩니다. 스키마는 `logs/serializers/log.py:8-65`(`LogV3Serializer`)에서 가져왔습니다.

| 필드 | 유형 | 널 허용 | 설명 | 예시 |
| - | - | - | - | - |
| `feature` | string(열거형) | 아니요 | 경고를 발생시킨 기능입니다. 값은 `LogWarningChoices`(`common/config/choices.py:190-204`)에서 가져옵니다: `ID_VERIFICATION`, `NFC`, `LIVENESS`, `FACEMATCH`, `PROOF_OF_ADDRESS`, `PHONE`, `EMAIL`, `AML`, `LOCATION`, `DATABASE_VALIDATION`, `QUESTIONNAIRE`, `KYB_REGISTRY`, `KYB_DOCUMENTS`, `KYB_KEY_PEOPLE`. | `"ID_VERIFICATION"` |
| `risk` | string | 아니요 | 안정적인 위험 코드입니다(예: `DOCUMENT_EXPIRED`, `LOW_LIVENESS_SCORE`). 값은 `logs/choices.py:RiskChoices`에서 가져옵니다. 설명 표의 키로 사용됩니다. | `"DOCUMENT_EXPIRED"` |
| `additional_data` | object \| null | 예 | 위험별 컨텍스트입니다(예: 점수 임계값, 일치한 필드). 형식은 위험 코드에 따라 다릅니다. | `{ "score": 42.1, "threshold": 70 }` |
| `log_type` | string(열거형) | 아니요 | `error`, `warning`, `information` 중 하나입니다. `LogTypeChoices`(`common/config/choices.py:207-210`)에서 가져옵니다. | `"error"` |
| `short_description` | string | 아니요 | 위험에 대한 사람이 읽을 수 있는 짧은 레이블입니다. `logs/choices.py:RISK_SHORT_DESCRIPTIONS`에서 가져옵니다. | `"Document expired"` |
| `long_description` | string | 아니요 | 최종 사용자에게 보이는 화면에 적합한, 사람이 읽을 수 있는 더 긴 설명입니다. `logs/choices.py:RISK_LONG_DESCRIPTIONS`에서 가져옵니다. | `"The document's expiration date has passed, rendering it no longer valid for use."` |
| `node_id` | string \| null | 예 | 경고가 발생한 워크플로 그래프 노드입니다. `node_id`가 없는 레거시 V2 로그에서는 `null`입니다. | `"first_id_verification"` |

```json theme={null}
{
  "feature": "ID_VERIFICATION",
  "risk": "DOCUMENT_EXPIRED",
  "additional_data": null,
  "log_type": "error",
  "short_description": "Document expired",
  "long_description": "The document's expiration date has passed, rendering it no longer valid for use.",
  "node_id": "first_id_verification"
}
```

## 보고서 객체

나머지 섹션에서는 기능별 보고서 객체를 각각 다룹니다. 다른 문서에서 딥링크로 연결할 수 있도록 H3 제목 텍스트는 고정되어 있습니다.

### 신분증 인증

사용자가 제출한 KYC/ID 문서마다 반환됩니다. `GET /v3/session/{sessionId}/decision/` 응답에는 `id_verifications[]`로 나타나며, V2 응답에서는 `kyc` 필드 안에 포함됩니다. 출처: `kyc/serializers/kyc.py:383-414` (`IDVerificationV3Serializer`, `kyc/serializers/kyc.py:320-380`의 `IDVerificationV2Serializer`를 확장).

| 필드 | 타입 | 널 허용 | 설명 | 예시 |
| - | - | - | - | - |
| `status` | 문자열 | 아니요 | [상태 열거형](#상태-열거형-참조)을 참조하세요. | `"Approved"` |
| `document_type` | 문자열 | 예 | 사람이 읽을 수 있는 문서 분류입니다(`Passport`, `Identity Card`, `Driver's License`, `Residence Permit`, `Health Insurance Card`, `Tax Card`, `Social Security Card`, `Work Permit`, `Visa`, `Public Service Card`, `Birth Certificate`, `Firearm License`, `Other`). 출처: `DOC_TYPE_MAPPING` (`common/config/choices.py:1275-1289`). | `"Passport"` |
| `document_subtype` | 문자열 | 예 | Didit 문서 레지스트리의 문서 하위 유형 코드입니다. 워크플로의 문서 설정이 허용하는 항목으로 필터링됩니다. 지역별 문서에는 지역이 포함됩니다. 전체 코드 목록: [문서 하위 유형](https://docs.didit.me/ko/core-technology/id-verification/document-subtypes-id-verification.md). | `"QUEENSLAND_DRIVER_LICENSE_GENERIC"` |
| `document_number` | 문자열 | 예 | OCR로 추출한 문서 번호입니다. | `"AB1234567"` |
| `personal_number` | 문자열 | 예 | OCR로 추출한 개인 또는 국가 식별 번호입니다. | `"99999999R"` |
| `portrait_image` | 문자열 (URL) | 예 | 얼굴 크롭 이미지의 사전 서명된 URL입니다. | `"https://<media-host>/.../portrait.jpg?..."` |
| `front_image` | 문자열 (URL) | 예 | 정리된 문서 앞면의 사전 서명된 URL입니다. | `"https://<media-host>/.../front.jpg?..."` |
| `front_video` | 문자열 (URL) | 예 | 앞면 촬영 영상의 사전 서명된 URL입니다(사용 가능한 경우). | `"https://<media-host>/.../front.mp4?..."` |
| `back_image` | 문자열 (URL) | 예 | 정리된 문서 뒷면의 사전 서명된 URL입니다. | `"https://<media-host>/.../back.jpg?..."` |
| `back_video` | 문자열 (URL) | 예 | 뒷면 촬영 영상의 사전 서명된 URL입니다. | `null` |
| `full_front_image` | 문자열 (URL) | 예 | 잘리지 않은(전체 프레임) 앞면 촬영 이미지입니다. | `"https://<media-host>/.../full_front.jpg?..."` |
| `full_back_image` | 문자열 (URL) | 예 | 잘리지 않은(전체 프레임) 뒷면 촬영 이미지입니다. | `null` |
| `front_image_camera_front` | 문자열 (URL) | 예 | 문서 앞면과 같은 시점에 찍은 전면 카메라 이미지입니다. | `null` |
| `back_image_camera_front` | 문자열 (URL) | 예 | 문서 뒷면과 같은 시점에 찍은 전면 카메라 이미지입니다. | `null` |
| `front_image_camera_front_face_match_score` | 실수 (0-100) | 예 | 문서 초상 사진과 전면 카메라 촬영본 간의 유사도입니다. | `null` |
| `back_image_camera_front_face_match_score` | 실수 (0-100) | 예 | 위와 같지만 뒷면 촬영본에 대한 값입니다. | `null` |
| `document_selfie_face_matches` | 배열 | 예 | 문서 촬영 중 찍은 셀피와 일치하는 이전 세션 또는 얼굴 차단 목록 항목입니다. 형식은 `liveness_checks[].matches`와 같습니다. 검색이 실행되지 않으면 `null`, 일치하는 항목이 없으면 `[]`입니다. | `null` |
| `front_image_quality_score` | 객체 | 예 | 앞면 이미지의 품질 지표입니다. 점수는 0-100이며(`focus_score`, `brightness_score`, `resolution_score`, `overall_score`), 추가로 `brightness_issue`(`ok`, `too_dark`, `too_bright`)와 `is_document_fully_visible`(불리언)을 포함합니다. | `{ "focus_score": 91.0, "overall_score": 88.5 }` |
| `back_image_quality_score` | 객체 | 예 | `front_image_quality_score`와 같은 형식입니다. | `null` |
| `date_of_birth` | 문자열 (YYYY-MM-DD) | 예 | OCR로 추출한 생년월일입니다. | `"1990-05-12"` |
| `age` | 정수 | 예 | 추출 시점 기준으로 계산한 나이(년)입니다. | `35` |
| `expiration_date` | 문자열 (YYYY-MM-DD) | 예 | 문서 만료일입니다. | `"2032-05-11"` |
| `date_of_issue` | 문자열 (YYYY-MM-DD) | 예 | 문서 발급일입니다. | `"2022-05-11"` |
| `issuing_state` | 문자열 (ISO 3166-1 alpha-3) | 예 | 발급 국가 코드입니다. | `"ESP"` |
| `issuing_state_name` | 문자열 | 예 | 현지화된 발급 국가 이름입니다. | `"Spain"` |
| `first_name` | 문자열 | 예 | OCR로 추출한 이름입니다. | `"María"` |
| `last_name` | 문자열 | 예 | OCR로 추출한 성입니다. | `"García López"` |
| `full_name` | 문자열 | 예 | 정규화된 성명입니다(공급업체 제공). | `"María García López"` |
| `gender` | 문자열 | 예 | `M`, `F` 또는 공급업체가 제공하는 기타 값입니다. | `"F"` |
| `address` | 문자열 | 예 | OCR로 추출한 원본 주소 줄입니다. | `"Calle Mayor 1, 28001 Madrid"` |
| `formatted_address` | 문자열 | 예 | 지오코딩된 형식의 주소입니다(파싱이 가능한 경우). | `"Calle Mayor 1, 28001 Madrid, Spain"` |
| `parsed_address` | 객체 | 예 | 구조화되고 지오코딩된 주소입니다. `street_1`, `street_2`, `city`, `region`, `country`, `postal_code`, `address_type`, `formatted_address`, `document_location`(`{latitude, longitude}`), `raw_results`, `is_best_match`를 포함합니다. 출처: `kyc/utils/address.py:147-197`. | `{ "street_1": "Calle Mayor 1", "city": "Madrid", "postal_code": "28001", "country": "ES" }` |
| `place_of_birth` | 문자열 | 예 | OCR로 추출한 출생지입니다. | `"Madrid"` |
| `marital_status` | 문자열 | 예 | 추출할 수 있는 경우에만 제공됩니다. | `null` |
| `nationality` | 문자열 (ISO 3166-1 alpha-3) | 예 | OCR로 추출한 국적입니다. | `"ESP"` |
| `extra_fields` | 객체 | 예 | 표준 스키마에 포함되지 않은 문서 유형별 필드입니다(예: 운전면허 등급). | `{ "DL Class": "B" }` |
| `mrz` | 객체 | 예 | 있는 경우 파싱된 MRZ 필드입니다(`document_number`, `birth_date`, `expiry_date`, `surname`, `given_names`, …). | `{ "document_number": "AB1234567", "surname": "GARCIA", "given_names": "MARIA" }` |
| `extra_files` | 문자열 배열 (URL) | 아니요 | 추가로 업로드된 파일의 사전 서명된 URL입니다. | `[]` |
| `matches` | 객체 배열 | 아니요 | 세션 간 문서 일치 항목입니다. 각 항목은 `{ session_id, session_number, vendor_data, verification_date, user_details: { name, document_type, document_number }, status, is_blocklisted, api_service, front_image_url }` 형식입니다. `front_image_url`은 사전 서명된 URL입니다. | `[]` |
| `verification_method` | string | 아니요 | 이 행을 만든 [신분증 인증 방식](https://docs.didit.me/ko/core-technology/id-verification/verification-methods.md)입니다: `document`, `id_lookup` 또는 `wallet`. 촬영한 문서이면 항상 `document`이며, 다른 방식이 도입되기 전에 생성된 모든 세션도 포함합니다. | `"id_lookup"` |
| `assurance` | string | 아니요 | `verification_method`에서 도출된 보증 등급: `documentary`, `data_match` 또는 `cryptographic`. | `"data_match"` |
| `wallet_provider` | string \| null | 예 | 이 행을 지갑이 만든 경우의 카탈로그 지갑 ID(`mitid`, `bankid_se`, `itsme`, ...). 그 외에는 `null`입니다. | `"mitid"` |
| `fallback_from` | object \| null | 예 | 문서 이외의 방식이 신분증 단계를 종료한 이유: `{ method, reason, action }`. 조회 또는 지갑 로그인이 실패하면 설정되며, 국가 설정이 `decline`이었던 경우 거부된 행에는 `action: "decline"`이, 설정이 `fallback_to_document`였던 경우 사용자가 이어서 진행하는 문서 인증에는 `action: "fallback_to_document"`가 설정됩니다. 이전에 문서 이외 방식의 실패가 기록되지 않았으면 `null`입니다. | `{ "method": "id_lookup", "reason": "no_match", "action": "decline" }` |
| `id_lookup` | object \| null | 예 | 출처 증거로, `verification_method`가 `id_lookup`인 경우에만 존재합니다: `source`(조회된 정확한 출처이며, 대부분의 국가에서는 정부 등록부이고 일부 국가에서는 신용평가기관 또는 주민 기록 파일입니다), `checked_at`, `attempts`, `max_attempts`, `outcome`(`match`, `partial_match`, `no_match`, `provider_error`, `format_rejected`), `comparison[]`(`{ field, label, provided, record, result }`; `field`는 `identification_number`, `full_name`, `date_of_birth`, `address` 중 하나이고, `result`는 `match`, `partial` 또는 `no_match`입니다. 이전 릴리스에서는 `error`가 포함된 `provider` 행이 있을 수 있습니다), `source_errors[]`(현재 스테이징: 출처별 개별 진단 정보이며, 프로덕션 배포 여부를 확인하십시오), `registry_portrait`(사전 서명 URL, 이를 반환하는 출처에만 해당) 및 `face_match_score`. | 아래 참조 |
| `wallet_verification` | object \| null | 예 | 자격 증명 증거로, `verification_method`가 `wallet`인 경우에만 존재합니다: `provider`, `provider_name`, `issuing_authority`, `issuing_country`, `credential_type`, `level_of_assurance`(`low`, `substantial`, `high`), `verified_at`, `signature_valid`, `attributes`(지갑이 공유한 정보), `portrait`(지갑이 얼굴 사진을 공유하는 경우의 사전 서명 URL) 및 `face_match_score`. | 아래 참조 |
| `document_liveness` | object \| null | 예 | 사기 유형별 문서 라이브니스 점수(`portrait_replace`, `printed_copy`, `screen_replay`)이며, 경고가 발생했는지와 관계없이 보고됩니다. 각 항목은 다음과 같습니다: `score`(0-100. 높을수록 실제일 가능성이 높으며, 앞면과 뒷면 중 더 낮은 값이 결정에 사용됨), `front`, `back`, `decline_threshold`, `review_threshold`, `bucket`(`approve`, `review`, `decline` 또는 `null`). 임계값과 버킷은 평가 시점에 저장되며, 과거 평가 증거를 사용할 수 없으면 세 값 모두 `null`이 되지만 저장된 점수는 계속 표시됩니다. 검사가 실행되지 않았으면 `null`입니다. [문서 라이브니스 점수](https://docs.didit.me/ko/core-technology/id-verification/report-id-verification.md#문서-라이브니스-점수)를 참조하십시오. V3 전용입니다. | `{ "portrait_replace": { "score": 96.46, "bucket": "approve" } }` |
| `node_id` | string \| null | 예 | 워크플로 노드 식별자(V3). | `"first_id_verification"` |
| `warnings` | array | 아니요 | [경고 객체](#경고-객체)를 참조하십시오. | `[]` |
| `region` | string | 예 | 문서에 명시된 경우, 발급 국가의 지역 또는 주입니다. | `"CA"` |
| `extracted_data` | object | 예 | 본인이 검토하도록 표시된 문서에서 추출된 데이터의 스냅샷으로, 확정된 값 옆에 함께 제공되어 비교할 수 있습니다. 본인에게 검토를 요청하지 않았으면 `null`입니다. | |
| `barcodes` | array of objects | 아니요 | 문서 바코드에서 읽은 데이터이며, 바코드마다 `type`, `position`, `data`, `data_raw`, `side`를 포함한 항목 하나가 있습니다. 바코드가 없으면 `[]`입니다. | `[]` |

```json theme={null}
{
  "status": "Approved",
  "document_type": "Passport",
  "document_subtype": "PASSPORT_GENERIC",
  "document_number": "AB1234567",
  "personal_number": "99999999R",
  "portrait_image": "https://<media-host>/.../portrait.jpg?signature=...",
  "front_image": "https://<media-host>/.../front.jpg?signature=...",
  "front_video": null,
  "back_image": "https://<media-host>/.../back.jpg?signature=...",
  "back_video": null,
  "full_front_image": "https://<media-host>/.../full_front.jpg?signature=...",
  "full_back_image": null,
  "front_image_camera_front": null,
  "back_image_camera_front": null,
  "front_image_camera_front_face_match_score": null,
  "back_image_camera_front_face_match_score": null,
  "front_image_quality_score": {
    "focus_score": 91.0,
    "brightness_score": 88.0,
    "brightness_issue": "ok",
    "is_document_fully_visible": true,
    "resolution_score": 95.0,
    "overall_score": 88.5
  },
  "back_image_quality_score": null,
  "date_of_birth": "1990-05-12",
  "age": 35,
  "expiration_date": "2032-05-11",
  "date_of_issue": "2022-05-11",
  "issuing_state": "ESP",
  "issuing_state_name": "Spain",
  "first_name": "María",
  "last_name": "García López",
  "full_name": "María García López",
  "gender": "F",
  "address": "Calle Mayor 1, 28001 Madrid",
  "formatted_address": "Calle Mayor 1, 28001 Madrid, Spain",
  "parsed_address": { "street_1": "Calle Mayor 1", "street_2": null, "city": "Madrid", "region": "Madrid", "postal_code": "28001", "country": "ES", "address_type": "Calle" },
  "place_of_birth": "Madrid",
  "marital_status": null,
  "nationality": "ESP",
  "extra_fields": {},
  "mrz": {
    "document_number": "AB1234567",
    "surname": "GARCIA",
    "given_names": "MARIA",
    "birth_date": "900512",
    "expiry_date": "320511"
  },
  "extra_files": [],
  "matches": [],
  "node_id": "first_id_verification",
  "verification_method": "document",
  "assurance": "documentary",
  "wallet_provider": null,
  "fallback_from": null,
  "id_lookup": null,
  "wallet_verification": null,
  "document_liveness": {
    "portrait_replace": {
      "score": 96.46,
      "front": 96.46,
      "back": 98.2,
      "decline_threshold": 35,
      "review_threshold": 70,
      "bucket": "approve"
    },
    "printed_copy": {
      "score": 91.2,
      "front": 91.2,
      "back": 93.7,
      "decline_threshold": 35,
      "review_threshold": 77,
      "bucket": "approve"
    },
    "screen_replay": {
      "score": 99.9,
      "front": 99.9,
      "back": 99.5,
      "decline_threshold": 30,
      "review_threshold": 70,
      "bucket": "approve"
    }
  },
  "warnings": []
}
```

문서 이외의 방식을 사용한 동일한 객체입니다. 방식에 따라 달라지는 키만 변경됩니다. 문서 판독으로 채워지는 모든 값은 대신 등록부 레코드 또는 지갑 속성에서 채워지며, 해당하지 않는 키는 `null`입니다.

```json theme={null}
{
  "status": "Approved",
  "issuing_state": "ZAF",
  "first_name": "Thabo",
  "last_name": "Mokoena",
  "full_name": "Thabo Mokoena",
  "date_of_birth": "1991-06-15",
  "personal_number": "9106155043088",
  "node_id": "first_id_verification",
  "verification_method": "id_lookup",
  "assurance": "data_match",
  "wallet_provider": null,
  "fallback_from": null,
  "id_lookup": {
    "source": "Department of Home Affairs",
    "checked_at": "2026-09-04T09:12:44Z",
    "attempts": 1,
    "max_attempts": 2,
    "outcome": "match",
    "comparison": [
      { "field": "identification_number", "label": "ID number", "provided": "9106155043088", "record": "9106155043088", "result": "match" },
      { "field": "full_name", "label": "Full name", "provided": "Thabo Mokoena", "record": "Thabo Mokoena", "result": "match" },
      { "field": "date_of_birth", "label": "Date of birth", "provided": "1991-06-15", "record": "1991-06-15", "result": "match" }
    ],
    "registry_portrait": "https://<media-host>/.../registry_portrait.jpg?signature=...",
    "face_match_score": 96.4
  },
  "wallet_verification": null,
  "warnings": []
}
```

```json theme={null}
{
  "status": "Approved",
  "issuing_state": "DNK",
  "first_name": "Freja",
  "last_name": "Nielsen",
  "full_name": "Freja Nielsen",
  "date_of_birth": "1988-03-02",
  "node_id": "first_id_verification",
  "verification_method": "wallet",
  "assurance": "cryptographic",
  "wallet_provider": "mitid",
  "fallback_from": null,
  "id_lookup": null,
  "wallet_verification": {
    "provider": "mitid",
    "provider_name": "MitID",
    "issuing_authority": "Danish Agency for Digital Government",
    "issuing_country": "DNK",
    "credential_type": "person_identification",
    "level_of_assurance": "substantial",
    "verified_at": "2026-09-04T09:12:44Z",
    "signature_valid": true,
    "attributes": {
      "full_name": "Freja Nielsen",
      "date_of_birth": "1988-03-02",
      "cpr_alias": "b0f1c2d3-e4f5-4678-9abc-def012345678"
    },
    "portrait": null,
    "face_match_score": null
  },
  "warnings": []
}
```

### NFC 인증

신분증에 대해 칩을 읽을 때마다 반환됩니다. 대상은 ICAO 9303 ePassport 또는 eID 칩, 또는 JPKI를 통해 읽은 일본 마이넘버 카드(`chip_protocol: "jpki"`)입니다. `GET /v3/session/{sessionId}/decision/`에서 `nfc_verifications[]`로 나타나며(상위 KYC 레코드당 하나), 출처는 `kyc/serializers/epassport.py:121-139`(`NFCV3Serializer`, `kyc/serializers/epassport.py:83-118`의 `NFCV2Serializer`를 확장)입니다.

| 필드 | 타입 | 널 허용 | 설명 | 예시 |
| - | - | - | - | - |
| `status` | string | 아니요 | [상태 열거형](#상태-열거형-참조)을 참조하십시오. | `"Approved"` |
| `portrait_image` | string (URL) | 예 | 칩에서 추출한 얼굴 이미지의 사전 서명 URL입니다. | `"https://<media-host>/.../nfc_portrait.jpg?..."` |
| `signature_image` | string (URL) | 예 | 칩에서 추출한 서명 이미지의 사전 서명 URL입니다(칩에 저장된 경우). | `null` |
| `chip_data` | object | 예 | 칩의 데이터 그룹에서 파싱한 개인 데이터로 평탄화되어 있습니다(`kyc/utils/epassport.py:165-212`): `dgs`(읽은 데이터 그룹), `surname`, `name`, `country`, `nationality`, `birth_date`(`YYYY-MM-DD`), `expiry_date`(`YYYY-MM-DD`), `sex`(`M`/`F`), `document_type`(MRZ 문서 코드), `document_number`, `optional_data`, MRZ 검사 숫자(`birth_date_hash`, `expiry_date_hash`, `document_number_hash`, `optional_data_hash`, `final_hash`), `mrz_string`, `mrz_type`(`TD1`/`TD2`/`TD3`). 칩에 DG11이 포함된 경우 `place_of_birth`와 `address`(그리고 비라틴 문자 이름의 경우 `full_name` / `full_name_non_latin`)도 포함되며, 그렇지 않으면 이 키들은 없습니다. NFC 단계를 건너뛴 경우 `null`입니다. | `{ "document_number": "AB1234567", "name": "MARIA" }` |
| `authenticity` | object | 예 | `{ sod_integrity, dg_integrity }`이며, JPKI 판독인 경우 `null`입니다. `sod_integrity`는 문서 보안 객체(SOD)의 서명이 유효한 발급 국가 CSCA까지 연결되는지(그리고 DSC가 폐기되거나 만료되지 않았는지) 검증하고, `dg_integrity`는 각 데이터 그룹의 해시가 SOD와 일치하는지 검증합니다. 두 값이 모두 `true`이면 칩이 진짜이며 변조되지 않았다는 뜻입니다. | `{ "sod_integrity": true, "dg_integrity": true }` |
| `certificate_summary` | object | 예 | 문서 서명자 인증서의 요약(`kyc/utils/epassport.py:338-348`)입니다. `issuer`, `subject`, `serial_number`(정수), `not_valid_before`, `not_valid_after`(`YYYY-MM-DD HH:MM:SS`)와 `validation` 객체 `{ csca_verified, dsc_revoked, dsc_expired, csca_expired }`(`kyc/views/epassport.py:86`)를 포함합니다. | `{ "issuer": "Common Name: CSCA SPAIN, Country: ES", "not_valid_after": "2031-02-18 10:21:11" }` |
| `node_id` | string \| null | 예 | 워크플로 노드 식별자(V3)입니다. | `"first_nfc"` |
| `is_nfc_skipped` | boolean | 아니요 | NFC 단계를 읽지 않고 명시적으로 건너뛴 경우 `true`입니다. 건너뛴 이유는 `skip_reason`에 기재됩니다. | `false` |
| `skip_reason` | string | 예 | 단계를 건너뛴 이유입니다. `is_nfc_skipped`가 `true`인 경우에만 설정됩니다. 값은 `USER_SKIPPED`, `DOCUMENT_WITHOUT_CHIP`, `CHIP_CERTIFICATE_UNAVAILABLE`, `DEVICE_WITHOUT_NFC`, `INTEGRATION_WITHOUT_NFC_ACCESS`, `MRZ_KEY_UNAVAILABLE`, `JPKI_UNAVAILABLE` 중 하나입니다. 자세한 내용은 [건너뛴 이유](https://docs.didit.me/ko/core-technology/nfc-verification/warnings-nfc-verification.md#건너뛰기-이유)를 참조하세요. 결정 payload에는 세션 수준의 `nfc_skip_reason`도 포함되며, 이 값은 보고서를 만들기 전에 건너뛴 NFC 단계를 같은 분류 체계로 나타냅니다. | `null` |
| `chip_protocol` | string | 아니요 | 칩을 읽는 방식입니다. `icao`(ICAO 9303 전자여권 또는 eID 칩) 또는 `jpki`(일본 마이넘버 카드)입니다. `jpki`인 경우 `portrait_image`, `signature_image`, `chip_data`, `authenticity`, `certificate_summary`는 `null`입니다. 건너뛴 단계에도 설정됩니다. | `"icao"` |
| `jpki` | object | 예 | 마이넘버 카드 읽기로 검증된 내용입니다. `certificate_types`, `chain_valid`, `signature_valid`, `revocation_status`(`good`, `revoked`, `unchecked`), `ca_generation`, `certificate_expires_at`, `certificates[]`, `attributes`(서명 인증서의 성명, 생년월일, 성별, 주소), `attributes_match_ocr`, `mismatched_attributes`를 포함합니다. 인증서, 일련번호, 서명은 절대 포함하지 않습니다. ICAO 칩, 건너뛴 단계, 카드 읽기 없이 종료된 단계에서는 `null`입니다. 자세한 내용은 [JPKI 필드](https://docs.didit.me/ko/core-technology/nfc-verification/report-nfc-verification.md#jpki-필드)를 참조하세요. | `null` |
| `warnings` | array | 아니요 | [경고 객체](#경고-객체)를 참조하세요. | `[]` |

```json theme={null}
{
  "status": "Approved",
  "portrait_image": "https://<media-host>/.../nfc_portrait.jpg?signature=...",
  "signature_image": null,
  "chip_data": {
    "dgs": ["DG1", "DG2", "DG11"],
    "surname": "GARCIA LOPEZ",
    "name": "MARIA",
    "country": "ESP",
    "nationality": "ESP",
    "birth_date": "1990-05-12",
    "expiry_date": "2032-05-11",
    "sex": "F",
    "document_type": "P",
    "document_number": "AB1234567",
    "optional_data": "",
    "birth_date_hash": "4",
    "expiry_date_hash": "7",
    "document_number_hash": "3",
    "optional_data_hash": "",
    "final_hash": "8",
    "mrz_string": "P<ESPGARCIA<LOPEZ<<MARIA<<<<<<<<<<<<<<<<<<<<AB1234567ESP9005124F3205117<<<<<<<<<<<<<<08",
    "mrz_type": "TD3",
    "place_of_birth": "MADRID",
    "address": "CALLE MAYOR 1, MADRID"
  },
  "authenticity": { "sod_integrity": true, "dg_integrity": true },
  "certificate_summary": {
    "issuer": "Common Name: CSCA SPAIN, Organization: DIRECCION GENERAL DE LA POLICIA, Country: ES",
    "subject": "Common Name: DS n-eID SPAIN 2, Organizational Unit: PASSPORT, Organization: DIRECCION GENERAL DE LA POLICIA, Country: ES",
    "serial_number": 118120836164494130086420187336801405660,
    "not_valid_before": "2020-11-18 10:21:11",
    "not_valid_after": "2031-02-18 10:21:11",
    "validation": {
      "csca_verified": true,
      "dsc_revoked": false,
      "dsc_expired": false,
      "csca_expired": false
    }
  },
  "node_id": "first_nfc",
  "is_nfc_skipped": false,
  "skip_reason": null,
  "chip_protocol": "icao",
  "jpki": null,
  "warnings": []
}
```

### 라이브니스 검사

세션별 라이브니스 결과로 반환됩니다. `GET /v3/session/{sessionId}/decision/` 응답의 `liveness_checks[]`로 나타납니다. 출처: `face/serializers/face.py:301-320`(`LivenessV3Serializer`, `face/serializers/face.py:216-298`의 `LivenessV2Serializer`를 확장).

| 필드 | 타입 | 널 허용 | 설명 | 예시 |
| - | - | - | - | - |
| `status` | string | 아니요 | [상태 열거형](#상태-열거형-참조)을 참조하세요. | `"Approved"` |
| `method` | string (enum) | 예 | `ACTIVE_3D`, `FLASHING`, `PASSIVE` 중 하나입니다(`LivenessMethodChoices`, `common/config/choices.py:514-517`). 데스크톱 세션이 허용되고 사용자가 데스크톱에 있으면 패시브 방식이 실행됩니다. | `"PASSIVE"` |
| `score` | float (0-100) | 예 | 라이브니스 신뢰도이며 소수점 둘째 자리까지 반올림합니다. | `92.41` |
| `reference_image` | string (URL) | 예 | 사용자 기준 얼굴 크롭 이미지의 사전 서명된 URL입니다. | `"https://<media-host>/.../reference.jpg?..."` |
| `video_url` | string (URL) | 예 | 라이브니스 영상의 사전 서명된 URL입니다(액티브 모드에서만). | `"https://<media-host>/.../liveness.webm?..."` |
| `age_estimation` | float | 예 | 기준 이미지에서 가장 큰 얼굴의 추정 나이(년)입니다. | `34.2` |
| `matches` | array of objects | 아니요 | 세션 간 얼굴 대조 결과입니다. 각 항목은 `{ session_id, session_number, similarity_percentage, vendor_data, vendor_user_id, biometric_template_id, verification_date, user_details: { full_name, document_type, document_number }, match_image_url, status, is_blocklisted, is_allowlisted, api_service, source }` 형식입니다. `source`는 `session`, `imported`, `list_entry`, `retained_template` 중 하나입니다. 보관된 템플릿 대조 결과에는 `vendor_user_id`, `vendor_data`, `biometric_template_id`가 있으며, 세션, 이미지, 신원 세부 정보, 상태, API 서비스 필드는 `null`입니다. | `[]` |
| `face_quality` | float (0-100) | 예 | 패시브 라이브니스의 얼굴 품질 점수(백분율로 정규화)입니다. | `87.50` |
| `face_luminance` | float (0-100) | 예 | 패시브 라이브니스의 얼굴 밝기 점수(0\~255 값을 백분율로 정규화)입니다. | `54.12` |
| `node_id` | string \| null | 예 | 워크플로 노드 식별자(V3)입니다. | `"first_liveness"` |
| `warnings` | array | 아니요 | [경고 객체](#경고-객체)를 참조하세요. | `[]` |

```json theme={null}
{
  "status": "Approved",
  "method": "PASSIVE",
  "score": 92.41,
  "reference_image": "https://<media-host>/.../reference.jpg?signature=...",
  "video_url": null,
  "age_estimation": 34.2,
  "matches": [],
  "face_quality": 87.50,
  "face_luminance": 54.12,
  "node_id": "first_liveness",
  "warnings": []
}
```

### 얼굴 대조

얼굴 대조 비교마다 반환됩니다(일반적으로 사용자의 라이브니스 얼굴과 문서 초상을 비교합니다). `GET /v3/session/{sessionId}/decision/` 응답의 `face_matches[]`로 나타납니다. 출처: `face/serializers/face.py:367-389`(`FaceMatchV3Serializer`, `face/serializers/face.py:323-364`의 `FaceMatchV2Serializer`를 확장).

| 필드 | 타입 | 널 허용 | 설명 | 예시 |
| - | - | - | - | - |
| `status` | string | 아니요 | [상태 열거형](#상태-열거형-참조)을 참조하세요. | `"Approved"` |
| `score` | float (0-100) | 예 | 유사도이며 소수점 둘째 자리까지 반올림합니다. 제공자가 `unmatched_faces[].Confidence`만 반환하면 `100 - confidence`로 변환합니다. | `97.83` |
| `source_image_session_id` | string (UUID) | 예 | 기준(참조) 이미지를 제공한 세션의 ID입니다. 저장된 초상을 사용하는 흐름(생체 인증 또는 세션 생성 시 제공된 초상)에서 설정됩니다. 기준 이미지가 같은 세션의 문서 초상이면 `null`입니다. | `null` |
| `source_image` | string (URL) | 예 | 기준(참조) 이미지의 사전 서명된 URL입니다. 보통 문서 초상이며, 생체 인증 흐름에서는 저장된 초상입니다. | `"https://<media-host>/.../source.jpg?..."` |
| `target_image` | string (URL) | 예 | 라이브니스 중 촬영된 대상(실시간 얼굴) 이미지의 사전 서명된 URL입니다. | `"https://<media-host>/.../target.jpg?..."` |
| `node_id` | string \| null | 예 | 워크플로 노드 식별자(V3)입니다. | `"first_face_match"` |
| `warnings` | array | 아니요 | [경고 객체](#경고-객체)를 참조하세요. | `[]` |
| `face_coverage` | object | 예 | 촬영 이미지에서 `eyes`, `mouth`, `face`가 가려졌는지 여부입니다. 각 영역에는 `covered`, `calibrated`, `visibility_score`가 있으며, `calibrated: false`는 그림자로 인한 증거이며, 이에 대해서는 경고가 발생하지 않음을 뜻합니다. `GET /v3/session/{sessionId}/decision/`에서만 반환되며 webhook payload에는 절대 포함되지 않습니다. | `{ "eyes": { "covered": false, "calibrated": true, "visibility_score": 0.98 } }` |

```json theme={null}
{
  "status": "Approved",
  "score": 97.83,
  "source_image_session_id": null,
  "source_image": "https://<media-host>/.../source.jpg?signature=...",
  "target_image": "https://<media-host>/.../target.jpg?signature=...",
  "node_id": "first_face_match",
  "warnings": []
}
```

### 얼굴 검색

독립형 얼굴 검색 API(`POST /v3/face-search/`)가 반환합니다. 얼굴 검색 결과는 `/v3/session/{sessionId}/decision/`에 복수형 배열로 나타나지 않습니다. `save_api_request=true`로 저장하면 세션은 `features[]`의 `FACE_SEARCH` 항목과, 저장된 `matches`를 담은 `liveness_checks[]` 항목으로 나타납니다. 출처: `apis/serializers/face_search.py:8-79` (`FaceSearchDetailsSerializer`를 감싸는 `FaceSearchResponseSerializer`), 일치 딕셔너리는 `face/utils/utils.py:869-884`에서 생성됩니다.

최상위 응답:

| 필드 | 타입 | null 허용 여부 | 설명 | 예시 |
| - | - | - | - | - |
| `request_id` | 문자열 (UUID) | 아니요 | `save_api_request=true`인 경우 저장된 세션 ID입니다(`GET /v3/session/{sessionId}/decision/`에서 사용 가능). 그렇지 않으면 일시적인 상관 UUID입니다. | `"4a1c2c4e-8b1b-4d6a-91b5-ee9a1f3a2c7f"` |
| `face_search` | 객체 | 아니요 | 검색 상세 payload입니다. 아래 필드를 참조하세요. | - |
| `vendor_data` | 문자열 | 예 | 요청에서 전달된 `vendor_data`를 그대로 반환합니다. | `null` |
| `metadata` | 객체 | 예 | 요청에서 전달된 `metadata`를 그대로 반환합니다. | `null` |
| `created_at` | 문자열 (ISO 8601) | 아니요 | 서버에서 기록한 요청 타임스탬프입니다. | `"2026-06-12T01:04:42.763237+00:00"` |

`face_search` 객체:

| 필드 | 타입 | null 허용 여부 | 설명 | 예시 |
| - | - | - | - | - |
| `status` | 문자열 | 아니요 | `FACE_IN_BLOCKLIST` 또는 `POSSIBLE_FACE_IN_BLOCKLIST` 경고가 발생한 경우에만 `Declined`입니다. 그 외에는 `Approved`입니다. 중복 일치만으로는 절대 거부되지 않습니다(`apis/views/face_search.py:242-248`). | `"Approved"` |
| `total_matches` | 정수 | 아니요 | `matches[]`에 반환된 일치 항목 수입니다(0-5). | `1` |
| `matches` | [얼굴 검색 일치 객체](#얼굴-검색-일치-객체) 배열 | 아니요 | 유사도 하한선 이상인 일치 항목을 최대 5개까지 유사도 내림차순으로 정렬한 결과입니다(차단 목록 항목이 먼저 오며, `search_type=blocklisted_or_approved`). | `[…]` |
| `user_image` | 객체 | 아니요 | 제출된 이미지의 감지 결과입니다: `{ entities: [{ bbox, confidence }], best_angle }`. 감지된 얼굴마다 엔티티 하나가 있습니다. | `{ "entities": [{ "bbox": [40, 40, 120, 120], "confidence": 0.73 }], "best_angle": 0 }` |
| `warnings` | 객체 배열 | 아니요 | 이 독립형 API의 축약된 경고 형식이며 `node_id`가 없습니다. 직렬화기 계약은 `{ risk, additional_data, log_type, short_description, long_description }`을 선언합니다(`apis/serializers/face_search.py:49-54`). 런타임 payload에는 항상 `"LIVENESS"`인 `feature`도 포함됩니다(`apis/views/face_search.py:332-341`). | `[]` |

#### 얼굴 검색 일치 객체

| 필드 | 타입 | null 허용 여부 | 설명 | 예시 |
| - | - | - | - | - |
| `session_id` | 문자열 (UUID) | 예 | 일치한 인증 세션입니다. `source`가 `imported`, `list_entry`, `retained_template`인 경우 `null`입니다. | `"a3f2a6f1-…"` |
| `session_number` | 정수 | 예 | 일치한 세션의 콘솔 표시용 번호입니다. 세션이 아닌 일치 항목은 `null`입니다. | `1024` |
| `similarity_percentage` | 실수 (0-100) | 아니요 | 제출된 얼굴과 일치한 얼굴 간의 유사도입니다. | `96.42` |
| `source` | 문자열 (열거형) | 아니요 | 일치한 얼굴이 등록된 출처입니다: `session`(인증 세션 또는 저장된 독립 호출), `imported`(사용자 프로필에 직접 업로드한 얼굴), `list_entry`(목록에 연결된 얼굴), `retained_template`(원본 세션이 삭제된 후 보관된 이미지 없는 [생체 인식 템플릿](https://docs.didit.me/ko/management-api/biometric-templates/overview.md)). | `"session"` |
| `vendor_data` | 문자열 | 예 | 일치한 세션의 `vendor_data`입니다. `imported` 및 `retained_template` 일치 항목에서는 연결된 사용자의 값입니다. | `"user-12345"` |
| `vendor_user_id` | 문자열 (UUID) | 예 | 연결된 사용자입니다. `list_entry` 일치 항목과 사용자가 없는 세션에서는 `null`입니다. | `"2f7c1a9e-…"` |
| `biometric_template_id` | 문자열 (UUID) | 예 | 일치한 보관 템플릿입니다. `retained_template` 일치 항목에만 설정되며, `GET`/`DELETE /v3/biometric-templates/{id}/`와 함께 사용합니다. | `null` |
| `verification_date` | 문자열 (ISO 8601) | 예 | 일치한 얼굴을 촬영한 시점 또는 `retained_template`을 보관한 시점입니다. `list_entry` 일치 항목에서는 `null`입니다. | `"2024-11-04T09:14:02Z"` |
| `user_details` | 객체 | 예 | 일치한 세션의 문서 인증에서 가져온 `{ full_name, document_type, document_number }`입니다. `imported` 일치 항목에서는 `full_name`만 설정되며, 신원 데이터가 없으면 `null`이고, `retained_template` 일치 항목에서는 항상 `null`입니다. | `{ "full_name": "María García López", "document_type": "Passport", "document_number": "AB1234567" }` |
| `match_image_url` | 문자열 (URL) | 예 | 일치한 사용자의 참조 얼굴입니다. `save_api_request=true`이면 사전 서명된 URL이고, 그렇지 않으면 원본 스토리지 경로입니다. 이미지를 보관하지 않는 `retained_template` 일치 항목에서는 항상 `null`입니다. | `"https://<media-host>/.../matched.jpg?..."` |
| `status` | 문자열 | 예 | 일치한 세션의 인증 상태입니다([상태 열거형](#상태-열거형-참조) 참조). 세션이 아닌 일치 항목은 `null`입니다. | `"Approved"` |
| `is_blocklisted` | 불리언 | 아니요 | 일치한 얼굴이 얼굴 차단 목록에 있는지 여부입니다. `retained_template` 일치 항목에서는 항상 `false`입니다. 차단 목록의 얼굴은 `list_entry` 일치 항목으로 별도 보고됩니다. | `false` |
| `is_allowlisted` | 불리언 | 아니요 | 일치한 얼굴이 허용 목록 중 하나에 있는지 여부입니다. | `false` |
| `api_service` | 문자열 (열거형) | 예 | 일치한 세션의 독립형 API 유형(대문자)입니다(예: `PASSIVE_LIVENESS`, `FACE_MATCH`). 워크플로 세션과 세션이 아닌 일치 항목에서는 `null`입니다. | `null` |

```json theme={null}
{
  "request_id": "4a1c2c4e-8b1b-4d6a-91b5-ee9a1f3a2c7f",
  "face_search": {
    "status": "Approved",
    "total_matches": 1,
    "matches": [
      {
        "session_id": "a3f2a6f1-1c1c-4eec-8b69-1c1c2f3a2c7f",
        "session_number": 1024,
        "similarity_percentage": 96.42,
        "source": "session",
        "vendor_data": "user-12345",
        "verification_date": "2024-11-04T09:14:02Z",
        "user_details": {
          "full_name": "María García López",
          "document_type": "Passport",
          "document_number": "AB1234567"
        },
        "match_image_url": "https://<media-host>/.../matched.jpg?signature=...",
        "status": "Approved",
        "is_blocklisted": false,
        "is_allowlisted": false,
        "api_service": null
      }
    ],
    "user_image": {
      "entities": [
        {
          "bbox": [40, 40, 120, 120],
          "confidence": 0.732973
        }
      ],
      "best_angle": 0
    },
    "warnings": []
  },
  "vendor_data": null,
  "metadata": null,
  "created_at": "2026-06-12T01:04:42.763237+00:00"
}
```

### AML 스크리닝

검사된 엔티티마다 반환됩니다. KYC 및 KYB 세션 모두에서 `GET /v3/session/{sessionId}/decision/`의 `aml_screenings[]`로 나타납니다. 출처: `aml/serializers/aml.py:63-85` (`AMLV3Serializer`, `aml/serializers/aml.py:28-60`의 `AMLV2Serializer`를 확장).

| 필드 | 타입 | null 허용 여부 | 설명 | 예시 |
| - | - | - | - | - |
| `status` | 문자열 | 아니요 | [상태 열거형](#상태-열거형-참조) 참조. | `"Approved"` |
| `total_hits` | 정수 | 아니요 | 스크리닝 히트 수입니다(항상 존재하며 기본값은 `0`). | `2` |
| `entity_type` | 문자열 (열거형) | 예 | `person` 또는 `company`입니다(`EntityTypeChoices`, `common/config/choices.py:675-677`). | `"person"` |
| `hits` | 객체 배열 | 아니요 | 히트마다 항목 하나입니다. 주요 필드: `id`, `caption`, `match`(불리언), `target`(불리언 \| null: 엔티티가 해당 목록의 직접 대상인지 여부), `match_score`(0-100 실수, 신원 신뢰도), `risk_score`(0-100 실수, 엔티티 위험도), `score`(사용 중단됨, 0-1 실수), `datasets[]`(예: `PEP`, `PEP Level 1`-`4`, `Sanctions`, `Adverse Media`, `Warnings and Regulatory Enforcement`, `Fitness and Probity`), `properties`(이름, 별칭, 생년월일 등), `features`, `url`, `first_seen`, `last_seen`, `rca_name`, `risk_view`, `score_breakdown`, `pep_matches`, `sanction_matches`, `warning_matches`, `adverse_media_matches`, `adverse_media_details`, `linked_entities`, `additional_information`, `review_status`(`Unreviewed`, `Confirmed Match`, `False Positive`, `Inconclusive`. AML 히트 상태 업데이트 엔드포인트로 편집할 수 있으며 `AMLHitStatusChoices`에 정의되어 있습니다). | `[…]` |
| `score` | float (0-100) | 예 | 전체 스크리닝 점수입니다. `False Positive`로 표시되지 않은 일치 항목 중 가장 높은 `risk_score`이며 (`aml/services/aml.py:832-842`), 모든 일치 항목이 오탐이면 `0`입니다. 계산되기 전에는 `null`입니다. | `42.7` |
| `screened_data` | 객체 | 예 | 스크리닝에 전송된 데이터의 스냅샷으로, `full_name`, `nationality`, `date_of_birth`, `document_number`를 포함합니다. | `{ "full_name": "María García López", "date_of_birth": "1990-05-12" }` |
| `is_ongoing_monitoring_enabled` | 불리언 | 아니요 | 해당 엔티티가 지속적인 모니터링 재스크리닝을 구독하고 있는지 여부입니다. | `false` |
| `next_ongoing_monitoring_bill_date` | 문자열 (YYYY-MM-DD) | 예 | 지속적인 모니터링이 활성화되어 있으면 `last_aml_bill_date + 365 days`로 계산됩니다. 스크리닝 날짜가 아니라 **결제** 날짜입니다. | `null` |
| `last_ongoing_screening_at` | 문자열 (ISO 8601) | 예 | 결과 변경 여부와 관계없이, 지속적인 모니터링이 이 레코드에 대해 마지막으로 재스크리닝을 완료한 시각입니다. 재스크리닝한 적이 없으면 `null`이며, 과거 시점으로 소급해 채우지 않습니다. | `"2026-09-12T04:03:11Z"` |
| `last_ongoing_screening_datasets_updated_at` | 문자열 (ISO 8601) | 예 | 해당 스크리닝에 대해 제공업체가 보고한 가장 최근 AML 데이터셋 업데이트 시각입니다. 데이터셋 날짜가 보고되지 않으면 `null`이며, 추정하지 않습니다. | `null` |
| `node_id` | 문자열 \| null | 예 | 워크플로 노드 식별자(V3)입니다. | `"first_aml"` |
| `warnings` | 배열 | 아니요 | [경고 객체](#경고-객체)를 참조하십시오. | `[]` |

```json theme={null}
{
  "status": "In Review",
  "total_hits": 1,
  "entity_type": "person",
  "hits": [
    {
      "id": "Q7XW3-aml-hit-1",
      "caption": "Maria Garcia Lopez",
      "match": true,
      "target": true,
      "match_score": 86.4,
      "risk_score": 42.7,
      "datasets": ["PEP Level 2"],
      "properties": {
        "name": ["María García López", "M. García"],
        "alias": ["Maria Garcia"],
        "birthDate": ["1990-05-12"]
      },
      "url": "https://example.org/registry/entities/Q7XW3",
      "first_seen": "2023-11-02T00:00:00Z",
      "last_seen": "2026-05-01T00:00:00Z",
      "review_status": "Unreviewed"
    }
  ],
  "score": 42.7,
  "screened_data": {
    "full_name": "María García López",
    "date_of_birth": "1990-05-12",
    "nationality": "ES",
    "document_number": "AB1234567"
  },
  "is_ongoing_monitoring_enabled": false,
  "next_ongoing_monitoring_bill_date": null,
  "last_ongoing_screening_at": null,
  "last_ongoing_screening_datasets_updated_at": null,
  "node_id": "first_aml",
  "warnings": []
}
```

### IP 분석

캡처된 네트워크 위치마다 반환됩니다. KYC 및 KYB 세션 모두에서 `GET /v3/session/{sessionId}/decision/` 응답의 `ip_analyses[]`로 나타납니다. 출처: `kyc/serializers/location.py:196-243` (`IPAnalysisSerializerV3`).

| 필드 | 유형 | Null 허용 | 설명 | 예시 |
| - | - | - | - | - |
| `status` | 문자열 | 아니요 | [상태 enum](#상태-열거형-참조)을 참조하십시오. | `"Approved"` |
| `node_id` | 문자열 \| null | 예 | 워크플로 노드 식별자(V3)입니다. | `"first_ip_analysis"` |
| `device_brand` | 문자열 | 예 | 사용자 에이전트에서 추출한 기기 브랜드입니다. | `"Apple"` |
| `device_model` | 문자열 | 예 | 기기 모델입니다. | `"iPhone"` |
| `browser_family` | 문자열 | 예 | 브라우저 계열입니다. | `"Mobile Safari"` |
| `os_family` | 문자열 | 예 | OS 계열입니다. | `"iOS"` |
| `platform` | 문자열 | 예 | 상위 수준의 플랫폼(`mobile`, `desktop`, `tablet`)입니다. | `"mobile"` |
| `device_fingerprint` | 문자열 | 예 | 기기별로 안정적인 핑거프린트 해시입니다. | `"f2a3…"` |
| `ip_country` | 문자열 | 예 | IP에서 확인된 국가 이름입니다. | `"Spain"` |
| `ip_country_code` | 문자열 (ISO 3166-1 alpha-2) | 예 | IP에서 확인된 국가 코드입니다. | `"ES"` |
| `ip_state` | 문자열 | 예 | IP에서 확인된 지역 또는 주입니다. | `"Comunidad de Madrid"` |
| `ip_city` | 문자열 | 예 | IP에서 확인된 도시입니다. | `"Madrid"` |
| `latitude` | float | 예 | IP 기반 위도입니다. | `40.4168` |
| `longitude` | float | 예 | IP 기반 경도입니다. | `-3.7038` |
| `ip_address` | 문자열 | 예 | 캡처된 주소입니다. | `"203.0.113.42"` |
| `isp` | 문자열 | 예 | ISP 이름입니다. | `"Telefonica de Espana"` |
| `organization` | 문자열 | 예 | 조직 이름입니다(ISP와 같은 경우가 많습니다). | `"Telefonica de Espana"` |
| `is_vpn_or_tor` | 불리언 | 예 | IP가 VPN, 프록시 또는 Tor 출구 노드에 속하면 `true`입니다. | `false` |
| `is_data_center` | 불리언 | 예 | IP가 알려진 호스팅 또는 데이터 센터 ASN에 속하면 `true`입니다. | `false` |
| `time_zone` | 문자열 | 예 | IANA 시간대 이름입니다. | `"Europe/Madrid"` |
| `time_zone_offset` | 문자열 | 예 | UTC 오프셋입니다. | `"+02:00"` |
| `ip` | 객체 | 아니요 | `{ location, distance_from_id_document, distance_from_poa_document }`입니다. `location = { latitude, longitude }`입니다. 거리는 km 단위이며, 어느 한쪽 위치가 없으면 `null`입니다. | `{ "location": { "latitude": 40.4168, "longitude": -3.7038 }, "distance_from_id_document": 3.4, "distance_from_poa_document": 1.1 }` |
| `id_document` | 객체 | 아니요 | `{ location, distance_from_ip, distance_from_poa_document }`입니다. 신분증 위치는 `issuing_state`와 파싱된 주소에서 확인됩니다. | `{ "location": { "latitude": 40.4165, "longitude": -3.7026 }, "distance_from_ip": 3.4, "distance_from_poa_document": 4.0 }` |
| `poa_document` | 객체 | 아니요 | `{ location, distance_from_ip, distance_from_id_document }`입니다. 주소 증명 문서의 주소를 지오코딩한 결과입니다. | `{ "location": { "latitude": 40.4170, "longitude": -3.7040 }, "distance_from_ip": 1.1, "distance_from_id_document": 4.0 }` |
| `matches` | 객체 배열 | 아니요 | 세션 간 IP 및 기기 일치 항목입니다. 각 항목은 `{ session_id, session_number, vendor_data, verification_date, match_type, match_source, matched_value, status, is_blocklisted, api_service, source, device_info, location_info, confidence, match_mode }`입니다. `match_type`은 `ip_address` 또는 `device_fingerprint`이고, `match_source`는 `ip_address`, `persistent_id`, `legacy_fp` 또는 `recovered_high`입니다(복구된 일치 항목에는 `recovery_similarity`, `tls_ja4_corroborated`, `recovery_gate_reason`도 포함됩니다). IP 일치 5건과 기기 일치 5건으로 제한됩니다. | `[]` |
| `warnings` | 배열 | 아니요 | [경고 객체](#경고-객체)를 참조하십시오. | `[]` |
| `browser_version`, `os_version` | 문자열 | 예 | 사용자 에이전트에서 가져온 브라우저 및 OS 버전입니다. | `"17.4"` |
| `user_agent`, `accept_language` | 문자열 | 예 | 브라우저가 전송한 사용자 에이전트 문자열과 `Accept-Language` 헤더입니다. | `"en-US,en;q=0.9"` |
| `session_identifier`, `session_age_ms` | 문자열, 정수 | 예 | 해당 단계가 실행된 브라우징 세션과 그 경과 시간(밀리초)입니다. | `48210` |
| `coords_accuracy` | float | 예 | 기기가 보고한 좌표의 정확도 반경(미터)입니다. | `35.0` |
| `raw_device_data` | 객체 | 예 | 해당 단계에서 수집된 원시 기기 신호입니다. | `{}` |

```json theme={null}
{
  "status": "Approved",
  "node_id": "first_ip_analysis",
  "device_brand": "Apple",
  "device_model": "iPhone",
  "browser_family": "Mobile Safari",
  "os_family": "iOS",
  "platform": "mobile",
  "device_fingerprint": "f2a3c1de8b994a3f9e4cdf3a02b1a7c9",
  "ip_country": "Spain",
  "ip_country_code": "ES",
  "ip_state": "Comunidad de Madrid",
  "ip_city": "Madrid",
  "latitude": 40.4168,
  "longitude": -3.7038,
  "ip_address": "203.0.113.42",
  "isp": "Telefonica de Espana",
  "organization": "Telefonica de Espana",
  "is_vpn_or_tor": false,
  "is_data_center": false,
  "time_zone": "Europe/Madrid",
  "time_zone_offset": "+02:00",
  "ip": {
    "location": { "latitude": 40.4168, "longitude": -3.7038 },
    "distance_from_id_document": 3.4,
    "distance_from_poa_document": 1.1
  },
  "id_document": {
    "location": { "latitude": 40.4165, "longitude": -3.7026 },
    "distance_from_ip": 3.4,
    "distance_from_poa_document": 4.0
  },
  "poa_document": {
    "location": { "latitude": 40.4170, "longitude": -3.7040 },
    "distance_from_ip": 1.1,
    "distance_from_id_document": 4.0
  },
  "matches": [],
  "warnings": []
}
```

### 위치 확인

[위치 확인](https://docs.didit.me/ko/core-technology/location-verification/overview.md) 단계마다 반환됩니다. `GET /v3/session/{sessionId}/decision/` 응답의 `geolocation_checks[]`로 나타나며, 단계당 하나의 항목으로 승인된 시도입니다. `geolocation_attempts[]`는 모든 단계의 모든 시도를 오래된 순서대로 나열합니다. 해당 단계가 없는 워크플로에서는 둘 다 `null`입니다. 출처: `GeolocationDecisionSerializer`.

| 필드 | 유형 | Null 허용 | 설명 | 예시 |
| - | - | - | - | - |
| `node_id` | 문자열 | 예 | 결과를 생성한 워크플로 노드입니다. | `"geolocation_1"` |
| `status` | string | 아니요 | [상태 열거형](#상태-열거형-참조)을 참조하십시오. | `"Declined"` |
| `outcome` | string | 예 | 시도의 결과입니다: `verified`, `low_accuracy`, `accuracy_undetermined`, `stale`, `approximate`, `denied`, `restricted`, `unavailable`, `timeout`, `mock_detected`, `outside_geofence`, `in_blocked_area`, `anonymizer_detected`, `skipped`, `replay_rejected` 또는 `unsupported_client`. | `"outside_geofence"` |
| `permission` | string | 예 | 시스템이 부여한 권한입니다: `granted_precise`, `granted_approximate`, `denied`, `restricted`, `unavailable`, `timeout`, `dismissed` 또는 `not_requested`. | `"granted_precise"` |
| `latitude`, `longitude` | float | 예 | WGS84 위치입니다. 위치 정보가 없으면 `null`입니다. | `48.8566` |
| `accuracy_m` | float | 예 | 미터 단위의 불확실성 반경입니다. | `35.0` |
| `accuracy_confidence` | string | 예 | `p95`, `p68` 또는 `unspecified`. | `"p95"` |
| `measured_at`, `age_seconds` | datetime, integer | 예 | 기기가 위치를 측정한 시각과 Didit이 이를 수신할 때까지 걸린 시간(초)입니다. | `2` |
| `source`, `platform`, `sdk_version` | string | 예 | 위치 정보의 출처, 해당 위치를 생성한 클라이언트, 그리고 SDK 버전입니다. | `"browser"` |
| `is_mock`, `produced_by_accessory` | boolean | 예 | 플랫폼이 보고하는 스푸핑 증거입니다. `null`은 플랫폼이 이를 보고하지 않는다는 뜻입니다. | `null` |
| `integrity` | string | 아니요 | `attested`, `not_attested`, `failed`, `unsupported`(웹) 또는 `not_determined`. | `"unsupported"` |
| `country_code`, `region_code`, `city` | string | 예 | 위치 정보가 확인되는 장소입니다. | `"FR"` |
| `geofence`, `inside_geofence`, `geofence_basis`, `inside_areas`, `blocked_areas` | object, boolean, string, arrays | 예 | 국가 및 지역 판정 결과입니다. | `{ "enabled": true, "result": "outside" }` |
| `position_source`, `anonymizers` | string, object | 예 | 이 단계가 위치를 가져오는 출처와 VPN, 프록시, Tor, 스푸핑 및 에뮬레이터 신호입니다. | `"device_and_ip"` |
| `ip_distance_km`, `ip_distance_uncertainty_km`, `ip_consistent`, `document_distance_km`, `travel_excused`, `consecutive_mismatches` | number, boolean, integer | 예 | IP 위치 및 등록된 주소와의 비교 결과입니다. | `12.4` |
| `attempts` | integer | 아니요 | 해당 단계 내 시도 번호입니다. | `3` |
| `consent` | object | 예 | 사용자가 동의한 고지의 `accepted_at`, `version`, `locale`입니다. | |
| `warnings` | [경고 객체](#경고-객체) 배열 | 아니요 | 해당 단계의 `LOCATION_*` 경고입니다. `geolocation_attempts[]`에는 없으며, 이 항목에는 `received_at`과 `created_at`이 추가됩니다. | `[]` |

모든 필드와 예시는 [위치 인증 보고서](https://docs.didit.me/ko/core-technology/location-verification/report-location-verification.md)에 있습니다.

### 주소 증명

제출된 주소 문서마다 반환됩니다. `GET /v3/session/{sessionId}/decision/`의 `poa_verifications[]`로 나타납니다. 출처: `poa/serializers/poa.py:212-227` (`POAV3Serializer`, `poa/serializers/poa.py:173-209`의 `POAV2Serializer`를 확장).

| 필드 | 타입 | Null 허용 | 설명 | 예시 |
| - | - | - | - | - |
| `status` | string | 아니요 | [상태 열거형](#상태-열거형-참조)을 참조하십시오. | `"Approved"` |
| `issuing_state` | string (ISO 3166-1 alpha-3) | 예 | 문서 발급자의 국가 코드입니다. | `"ESP"` |
| `document_type` | string | 아니요 | `PoaDocumentTypeChoices`(`common/config/choices.py:868-873`)의 상위 유형입니다: `UTILITY_BILL`, `BANK_STATEMENT`, `GOVERNMENT_ISSUED_DOCUMENT`, `OTHER_POA_DOCUMENT`. 해당하지 않으면 `UNKNOWN`으로 대체되며, 절대 `null`이 아닙니다. | `"UTILITY_BILL"` |
| `document_subtype` | string | 아니요 | `PoaDocumentSubtypeChoices`의 하위 유형 코드입니다(예: `ELECTRICITY_BILL`, `WATER_BILL`, `ACCOUNT_STATEMENT`). 해당하지 않으면 `UNKNOWN`으로 대체되며, 절대 `null`이 아닙니다. | `"ELECTRICITY_BILL"` |
| `issuer` | string | 예 | 발급 기관의 이름입니다. | `"Iberdrola"` |
| `issue_date` | string (YYYY-MM-DD) | 예 | 문서 발급일입니다. | `"2026-04-15"` |
| `expiration_date` | string (YYYY-MM-DD) | 예 | 문서에 인쇄된 만료일입니다(있는 경우). | `null` |
| `poa_address` | string | 예 | OCR로 추출한 원본 주소입니다. | `"Calle Mayor 1, 28001 Madrid"` |
| `poa_formatted_address` | string | 예 | 지오코딩된 형식의 주소입니다. | `"Calle Mayor 1, 28001 Madrid, Spain"` |
| `poa_parsed_address` | object | 예 | 구조화된 주소입니다(`street_1`, `street_2`, `city`, `region`, `postal_code`, `country`(alpha-2), `address_type`, `document_location`, …). | `{ "street_1": "Calle Mayor 1", "city": "Madrid", "postal_code": "28001" }` |
| `document_file` | string (URL) | 예 | 업로드된 문서의 사전 서명된 URL입니다. | `"https://<media-host>/.../poa.pdf?..."` |
| `document_language` | string | 예 | 감지된 문서 언어(ISO 639-1)입니다. | `"es"` |
| `document_metadata` | object | 예 | 필터링된 메타데이터: `file_size`, `content_type`, `creation_date`, `modified_date`, `creator`, `producer`, `software`, `encryption`, `is_signed`, `is_tampered`, `signature_info`, `exif_original_date`, `exif_digitized_date`, `processed_by_known_editor`, `has_different_creation_mod_date`, `overlay_manipulation`. | `{ "file_size": 184221, "content_type": "application/pdf", "is_tampered": false }` |
| `extra_fields` | object | 아니요 | 은행 계좌 필드(`bank_account_number`, `bank_iban`, `bank_sort_code`, `bank_routing_number`, `bank_swift_bic`, `bank_branch_name`, `bank_branch_address`), `document_phone_number`, `additional_names`, 그리고 레코드에 저장된 사용자 지정 키입니다. | `{ "bank_iban": null, "additional_names": [] }` |
| `name_on_document` | string | 예 | 주소 증명에 표시된 이름입니다. | `"María García López"` |
| `expected_details_address` | string | 예 | 고객이 가입 시 입력한 주소(입력한 그대로)입니다. | `"Calle Mayor 1, Madrid"` |
| `expected_details_formatted_address` | string | 예 | 지오코딩된 예상 주소입니다. | `"Calle Mayor 1, 28001 Madrid, Spain"` |
| `expected_details_parsed_address` | object | 예 | 구조화된 예상 주소입니다. | `{ "city": "Madrid", "postal_code": "28001" }` |
| `name_match_score_expected_details` | float (0-100) | 예 | `name_on_document`와 세션 생성 시 제공된 이름 간의 퍼지 매칭 점수입니다. | `94.0` |
| `name_match_score_id_verification` | float (0-100) | 예 | `name_on_document`와 검증된 신분증의 `full_name` 간의 퍼지 매칭 점수입니다. | `100.0` |
| `extra_files` | 문자열 배열(URL) | 아니요 | 업로드된 추가 파일에 대한 사전 서명된 URL입니다. | `[]` |
| `detected_codes` | 객체 배열 | 아니요 | 처리된 문서의 모든 페이지에서 탐지된 QR 코드와 바코드입니다: `type`, `page_number`(1부터 시작), `position`(다각형), `x`/`y`/`width`/`height`(경계 상자), `page_width`/`page_height`, `raw_payload`(base64), `parsed_payload`(디코딩된 값입니다. 코드 위치는 찾았지만 디코딩할 수 없으면 `null`입니다). 탐지 결과가 없으면 빈 배열입니다. | `[{ "type": "QR_CODE", "page_number": 1, "parsed_payload": "https://issuer.example/inv/9981" }]` |
| `node_id` | 문자열 \| null | 예 | 워크플로 노드 식별자(V3)입니다. | `"first_poa"` |
| `warnings` | 배열 | 아니요 | [경고 객체](#경고-객체)를 참조하십시오. | `[]` |

```json theme={null}
{
  "status": "Approved",
  "issuing_state": "ESP",
  "document_type": "UTILITY_BILL",
  "document_subtype": "ELECTRICITY_BILL",
  "issuer": "Iberdrola",
  "issue_date": "2026-04-15",
  "expiration_date": null,
  "poa_address": "Calle Mayor 1, 28001 Madrid",
  "poa_formatted_address": "Calle Mayor 1, 28001 Madrid, Spain",
  "poa_parsed_address": { "street_1": "Calle Mayor 1", "city": "Madrid", "postal_code": "28001", "country": "ES" },
  "document_file": "https://<media-host>/.../poa.pdf?signature=...",
  "document_language": "es",
  "document_metadata": {
    "file_size": 184221,
    "content_type": "application/pdf",
    "creation_date": "2026-04-15T08:11:32Z",
    "modified_date": "2026-04-15T08:11:32Z",
    "creator": "Iberdrola Billing",
    "producer": "Adobe PDF Library 15.0",
    "software": null,
    "encryption": null,
    "is_signed": true,
    "is_tampered": false,
    "signature_info": { "signer_name": "Iberdrola Clientes", "date": "2026-04-15T08:11:32Z" },
    "exif_original_date": null,
    "exif_digitized_date": null,
    "processed_by_known_editor": false,
    "has_different_creation_mod_date": false,
    "overlay_manipulation": null
  },
  "extra_fields": {
    "bank_account_number": null,
    "bank_iban": null,
    "bank_sort_code": null,
    "bank_routing_number": null,
    "bank_swift_bic": null,
    "bank_branch_name": null,
    "bank_branch_address": null,
    "document_phone_number": null,
    "additional_names": []
  },
  "name_on_document": "María García López",
  "expected_details_address": "Calle Mayor 1, Madrid",
  "expected_details_formatted_address": "Calle Mayor 1, 28001 Madrid, Spain",
  "expected_details_parsed_address": { "city": "Madrid", "postal_code": "28001", "country": "ES" },
  "name_match_score_expected_details": 94.0,
  "name_match_score_id_verification": 100.0,
  "extra_files": [],
  "detected_codes": [
    {
      "type": "QR_CODE",
      "page_number": 1,
      "position": [[820, 1120], [1002, 1120], [1002, 1302], [820, 1302]],
      "x": 820,
      "y": 1120,
      "width": 182,
      "height": 182,
      "page_width": 1190,
      "page_height": 1684,
      "raw_payload": "aHR0cHM6Ly9pYmVyZHJvbGEuZXMvZmFjdHVyYS85OTgx",
      "parsed_payload": "https://iberdrola.es/factura/9981"
    },
    {
      "type": "CODE_128",
      "page_number": 1,
      "position": [[112, 1480], [560, 1480], [560, 1540], [112, 1540]],
      "x": 112,
      "y": 1480,
      "width": 448,
      "height": 60,
      "page_width": 1190,
      "page_height": 1684,
      "raw_payload": "MDA5OTgxMDAwNDI=",
      "parsed_payload": "0099810042"
    }
  ],
  "node_id": "first_poa",
  "warnings": []
}
```

### 전화번호 인증

전화번호 인증 시도마다 반환됩니다. KYC 세션과 KYB 세션 모두에서 `GET /v3/session/{sessionId}/decision/` 응답의 `phone_verifications[]`로 나타납니다. 출처: `phone/serializers/phone.py:251-266`(`PhoneV3Serializer`, `phone/serializers/phone.py:103-248`의 `PhoneV2Serializer`를 확장한 것입니다).

| 필드 | 유형 | Null 허용 | 설명 | 예시 |
| - | - | - | - | - |
| `status` | 문자열 | 아니요 | [상태 열거형](#상태-열거형-참조)을 참조하십시오. | `"Approved"` |
| `phone_number_prefix` | 문자열 | 아니요 | `+`를 포함한 E.164 국가 번호입니다. | `"+34"` |
| `phone_number` | 문자열 | 아니요 | 국가 번호를 제외한 가입자 번호입니다. | `"612345678"` |
| `full_number` | 문자열 | 아니요 | 전체 E.164 번호입니다(`phone_number_prefix + phone_number`). | `"+34612345678"` |
| `country_code` | 문자열(ISO 3166-1 alpha-2) | 예 | 번호의 국가입니다. | `"ES"` |
| `country_name` | 문자열 | 예 | 현지화된 국가 이름입니다. | `"Spain"` |
| `carrier` | 객체 | 아니요 | `type`이 `LineTypeChoices` 값(`common/config/choices.py:648-667`)인 `{ name, type }`입니다: `mobile`, `fixed_line`, `voip`, `isp`, `vpn`, `toll_free`, `premium_rate`, `satellite`, `pager`, `payphone`, `voice_mail`, `unknown` 및 그 밖의 회선 유형입니다. | `{ "name": "Movistar", "type": "mobile" }` |
| `is_disposable` | 불리언 | 아니요 | 통신사가 해당 번호를 임시용 또는 일회용으로 표시한 경우 `true`입니다. | `false` |
| `is_virtual` | 불리언 | 아니요 | `carrier.type`이 `voip`, `isp`, `vpn` 중 하나인 경우 `true`입니다. | `false` |
| `verification_method` | 문자열 | 아니요 | OTP 전송에 사용된 채널입니다(`whatsapp`, `sms`, …). 마지막 전송 시도의 `actual_channel` 값을 읽으며, 없으면 요청된 `channel` 값을, 그다음 `sms`를 사용합니다. | `"whatsapp"` |
| `verification_attempts` | 정수 | 아니요 | OTP 전송 시도의 총 횟수입니다(최초 전송과 재전송 포함). | `1` |
| `verified_at` | 문자열(ISO 8601) | 예 | OTP가 성공적으로 입력된 시각입니다. | `"2026-05-17T10:14:02Z"` |
| `lifecycle` | 객체 배열 | 아니요 | 시간순 이벤트입니다: 전송 시도, 전달 콜백, 코드 확인, 최종 상태 이벤트. 각 이벤트는 `{ type, timestamp, details, fee }`입니다. 이벤트 유형은 `PhoneEventChoices`에서 가져옵니다. | `[…]` |
| `matches` | 객체 배열 | 아니요 | 세션 간 전화번호 일치 항목입니다. 각 항목은 `{ session_id, session_number, vendor_data, verification_date, phone_number, status, is_blocklisted, api_service, source }`입니다. `source`는 `session` 또는 `list_entry`입니다. | `[]` |
| `node_id` | 문자열 \| null | 예 | 워크플로 노드 식별자(V3)입니다. | `"first_phone"` |
| `warnings` | 배열 | 아니요 | [경고 객체](#경고-객체)를 참조하십시오. | `[]` |
| `phone_intelligence` | 객체 | 예 | 전화번호 인텔리전스 신호입니다. 인텔리전스 부가 기능이 해당 번호에 대해 실행된 경우에만 존재합니다. | |
| `phone_social` | 객체 | 예 | 번호의 소셜 활동 흔적입니다. 소셜 활동 흔적 부가 기능이 실행된 경우에만 존재합니다. | |

```json theme={null}
{
  "status": "Approved",
  "phone_number_prefix": "+34",
  "phone_number": "612345678",
  "full_number": "+34612345678",
  "country_code": "ES",
  "country_name": "Spain",
  "carrier": { "name": "Movistar", "type": "mobile" },
  "is_disposable": false,
  "is_virtual": false,
  "verification_method": "whatsapp",
  "verification_attempts": 1,
  "verified_at": "2026-05-17T10:14:02Z",
  "lifecycle": [
    {
      "type": "PHONE_VERIFICATION_MESSAGE_SENT",
      "timestamp": "2026-05-17T10:13:51Z",
      "details": { "status": "Success", "reason": null, "channel": "whatsapp", "actual_channel": "whatsapp" },
      "fee": 0.02
    },
    {
      "type": "PHONE_DELIVERY_DELIVERED",
      "timestamp": "2026-05-17T10:13:52Z",
      "details": { "channel": "whatsapp", "status": "delivered" },
      "fee": 0
    },
    {
      "type": "VALID_CODE_ENTERED",
      "timestamp": "2026-05-17T10:14:02Z",
      "details": { "code_tried": "482917", "status": "Approved" },
      "fee": 0
    },
    {
      "type": "PHONE_VERIFICATION_APPROVED",
      "timestamp": "2026-05-17T10:14:02Z",
      "details": null,
      "fee": 0
    }
  ],
  "matches": [],
  "node_id": "first_phone",
  "warnings": []
}
```

### 이메일 인증

이메일 인증 시도마다 반환됩니다. KYC 세션과 KYB 세션 모두에서 `GET /v3/session/{sessionId}/decision/` 응답의 `email_verifications[]`로 나타납니다. 출처: `email_verification/serializers/email.py:149-164`(`EmailV3Serializer`, `email_verification/serializers/email.py:38-146`의 `EmailV2Serializer`를 확장합니다).

| 필드 | 유형 | Null 허용 | 설명 | 예시 |
| - | - | - | - | - |
| `status` | 문자열 | 아니요 | [상태 열거형](#상태-열거형-참조)을 참조하십시오. | `"Approved"` |
| `email` | 문자열 | 아니요 | 제출된 이메일 주소입니다. | `"maria.garcia@example.com"` |
| `is_breached` | 불리언 | 아니요 | 이메일이 알려진 데이터 유출 사건에 포함된 경우 `true`입니다. | `false` |
| `breaches` | 객체 배열 | 아니요 | `is_breached`가 `true`인 경우 유출 건별 상세 정보입니다: `{ name, domain, logo_path, breach_date, description, is_verified, data_classes, breach_emails_count }`. | `[]` |
| `is_disposable` | 불리언 | 아니요 | 이메일이 일회용 메일 제공업체에 속한 경우 `true`입니다. | `false` |
| `is_undeliverable` | 불리언 | 아니요 | SMTP 전송 검사에서 받은편지함이 메일을 수락하지 않는 것으로 확인된 경우 `true`입니다. | `false` |
| `verification_attempts` | 정수 | 아니요 | OTP 확인 시도의 총 횟수입니다. | `1` |
| `verified_at` | 문자열(ISO 8601) | 예 | OTP가 성공적으로 입력된 시각입니다. | `"2026-05-17T10:15:22Z"` |
| `lifecycle` | 객체 배열 | 아니요 | 시간순 이벤트입니다: 전송 시도, 코드 확인, 최종 상태 이벤트. 각 이벤트는 `{ type, timestamp, details, fee }`입니다. 이벤트 유형은 `EmailEventChoices`에서 가져옵니다. | `[…]` |
| `matches` | 객체 배열 | 아니요 | 세션 간 이메일 일치 항목입니다. 각 항목은 `{ session_id, session_number, vendor_data, verification_date, email, status, is_blocklisted, api_service, source }`입니다. `source`는 `session` 또는 `list_entry`입니다. | `[]` |
| `node_id` | 문자열 \| null | 예 | 워크플로 노드 식별자(V3)입니다. | `"first_email"` |
| `warnings` | 배열 | 아니요 | [경고 객체](#경고-객체)를 참조하십시오. | `[]` |
| `email_intelligence` | 객체 | 예 | 이메일 인텔리전스 신호입니다. 인텔리전스 부가 기능이 해당 주소에 대해 실행된 경우에만 존재합니다. | |
| `email_social` | 객체 | 예 | 주소의 소셜 활동 흔적입니다. 소셜 활동 흔적 부가 기능이 실행된 경우에만 존재합니다. | |

```json theme={null}
{
  "status": "Approved",
  "email": "maria.garcia@example.com",
  "is_breached": false,
  "breaches": [],
  "is_disposable": false,
  "is_undeliverable": false,
  "verification_attempts": 1,
  "verified_at": "2026-05-17T10:15:22Z",
  "lifecycle": [
    {
      "type": "EMAIL_VERIFICATION_MESSAGE_SENT",
      "timestamp": "2026-05-17T10:15:11Z",
      "details": { "status": "Success", "reason": null },
      "fee": 0.02
    },
    {
      "type": "VALID_CODE_ENTERED",
      "timestamp": "2026-05-17T10:15:22Z",
      "details": { "code_tried": "739204", "status": "Approved" },
      "fee": 0
    },
    {
      "type": "EMAIL_VERIFICATION_APPROVED",
      "timestamp": "2026-05-17T10:15:22Z",
      "details": null,
      "fee": 0
    }
  ],
  "matches": [],
  "node_id": "first_email",
  "warnings": []
}
```

### 데이터베이스 검증

사용자가 제출한 데이터를 대상으로 실행된 데이터베이스 조회마다 반환됩니다. `GET /v3/session/{sessionId}/decision/` 응답의 `database_validations[]`로 나타납니다. 출처: `database_validation/serializers/database_validation.py:21-142`(`DatabaseValidationV3Serializer`, `DatabaseValidationV2Serializer`를 확장한 것입니다).

| 필드 | 타입 | 널 허용 여부 | 설명 | 예시 |
| - | - | - | - | - |
| `issuing_state` | 문자열 (ISO 3166-1 alpha-3) | 예 | 조회한 레지스트리의 국가입니다. | `"ESP"` |
| `validation_type` | 문자열 (열거형) | 아니요 | 결과가 검증된 방식입니다: `one_by_one`(단일 서비스의 결과), `two_by_two`(둘 이상의 서로 다른 서비스가 독립적으로 신원 번호를 완전히 일치시킨 경우), `not_enabled`(검증기가 건너뛰어졌거나 제공자가 응답하지 않은 경우)입니다. 명확한 `no_match`의 경우에도 `one_by_one`이 반환됩니다. 절대 `null`이 아닙니다. 출처: `DatabaseValidationChoices`(`common/config/choices.py:1097-1100`). | `"one_by_one"` |
| `screened_data` | 객체 | 아니요 | 레지스트리에 제출된 데이터입니다. 파일 필드(`selfie`, `cnh_qr_code_image`, `document_image`)는 조회 시점에 사전 서명된 URL로 제공됩니다. | `{ "document_number": "99999999R", "date_of_birth": "1990-05-12" }` |
| `validations` | 객체 배열 | 아니요 | 일치 결과를 낸 카탈로그 서비스마다 항목이 하나씩 있습니다. 각 항목에는 `service_id`, `service_name`, `validation`(제공자 판정 객체), `outcome_code`, `outcome_detail`, `source_data`(정리된 시민 프로필: `full_name`, `gender`, `date_of_birth`, `photo`(사전 서명된 URL), `signature`(사전 서명된 URL), …)가 포함될 수 있습니다. | `[…]` |
| `errors` | 객체 배열 | 예 | 조회가 실패한 경우의 서비스별 오류입니다. 값이 비어 있으면 키가 완전히 생략됩니다. 각 항목은 업스트림 서비스의 오류 객체에 이를 생성한 `service_id`를 더한 것입니다. | `[]` |
| `match_type` | 문자열 (열거형) | 예 | 조회한 서비스 전체에 대한 종합 일치 판정입니다: `full_match`, `partial_match`, `no_match`(`DatabaseValidationMatchTypeChoices`, `common/config/choices.py:1103-1106`). 평가되기 전까지는 `null`입니다. | `"full_match"` |
| `status` | 문자열 | 아니요 | [상태 열거형](#상태-열거형-참조)을 참조하세요. | `"Approved"` |
| `node_id` | 문자열 \| null | 예 | 워크플로 노드 식별자(V3)입니다. | `"first_db_validation"` |
| `warnings` | 배열 | 아니요 | [경고 객체](#경고-객체)를 참조하세요. | `[]` |

```json theme={null}
{
  "issuing_state": "ESP",
  "validation_type": "one_by_one",
  "screened_data": {
    "document_number": "99999999R",
    "date_of_birth": "1990-05-12",
    "first_name": "María",
    "last_name": "García López"
  },
  "validations": [
    {
      "service_id": "esp_dni",
      "service_name": "Spain - DNI/NIE verification",
      "validation": { "is_valid": true, "match_score": 100 },
      "outcome_code": "MATCH",
      "outcome_detail": "All identifiers match the registry record.",
      "source_data": {
        "full_name": "María García López",
        "gender": "F",
        "date_of_birth": "1990-05-12",
        "photo": "https://<media-host>/.../registry_photo.jpg?signature=...",
        "signature": null
      }
    }
  ],
  "match_type": "full_match",
  "status": "Approved",
  "node_id": "first_db_validation",
  "warnings": []
}
```

### 설문지 응답

설문지 제출마다 반환됩니다. KYC 및 KYB 세션 모두에서 `GET /v3/session/{sessionId}/decision/`의 `questionnaire_responses[]`로 나타납니다. 출처: `questionnaires/serializers/questionnaire.py:591-597`(`QuestionnaireResponseV3Serializer`, `questionnaires/serializers/questionnaire.py:520-588`의 `QuestionnaireResponseSerializer`를 확장).

| 필드 | 타입 | 널 허용 여부 | 설명 | 예시 |
| - | - | - | - | - |
| `questionnaire_id` | 문자열 (UUID) | 아니요 | 응답한 설문지 버전의 식별자입니다. | `"6a0f1c2c-…"` |
| `title` | 문자열 | 아니요 | 콘솔에서 설정한 설문지 이름입니다. | `"Customer risk profile"` |
| `description` | 문자열 | 예 | 설문지 설명입니다. | `"Short risk-profile questions."` |
| `languages` | 문자열 배열 | 아니요 | 설문지가 게시된 언어 코드입니다. | `["en", "es"]` |
| `default_language` | 문자열 | 아니요 | 대체 언어 코드입니다. | `"en"` |
| `is_active` | 불리언 | 아니요 | 이 설문지 버전이 활성 버전인지 여부입니다. | `true` |
| `is_simple_questionnaire` | 불리언 | 아니요 | 설문지에 분기가 없는 경우(평면 목록) `true`입니다. | `true` |
| `questionnaire_group_id` | 문자열 (UUID) | 아니요 | 같은 설문지의 모든 버전에서 공유되는 식별자입니다. | `"a7c2c2c2-…"` |
| `version` | 정수 | 아니요 | 활성 템플릿의 버전 번호입니다. | `3` |
| `status` | 문자열 | 아니요 | `Approved`, `In Review`, `Not Finished` 중 하나입니다(설문지 수준의 거부는 `In Review`로 매핑됩니다). | `"Approved"` |
| `published_at` | 문자열 (ISO 8601) | 예 | 템플릿이 게시된 시점입니다. | `"2026-01-12T11:00:00Z"` |
| `sections` | 객체 배열 | 아니요 | 그래프 순회와 표시 여부 필터를 적용한 뒤의 순서가 지정된 섹션입니다. 각 섹션은 `{ title, description, items[] }`입니다(title과 description은 시작 `SECTION_HEADER`에서 가져오며 미리 번역되어 있습니다). 각 항목은 폼 요소입니다(`uuid`, `value`(노드 ID), `element_type`, `is_required`, `title`, `description`, `placeholder`, `choices`, `max_files`, `required_if`, `repeatable_config`, 그리고 `answer` 필드). 이 필드는 응답하지 않은 경우 `null`이며, `HEADING`/`PARAGRAPH`/`SEPARATOR` 레이아웃 항목에서는 생략됩니다. 파일 응답은 `{ files: [<presigned URL>, …] }` 형태입니다. | `[…]` |
| `node_id` | 문자열 \| null | 예 | 워크플로 노드 식별자(V3)입니다. | `"first_questionnaire"` |

```json theme={null}
{
  "questionnaire_id": "6a0f1c2c-3b7d-4d2c-9eb6-fdc6c7c92ef9",
  "title": "Customer risk profile",
  "description": "Short risk-profile questions.",
  "languages": ["en", "es"],
  "default_language": "en",
  "is_active": true,
  "is_simple_questionnaire": true,
  "questionnaire_group_id": "a7c2c2c2-1111-4d2c-9eb6-fdc6c7c92ef9",
  "version": 3,
  "status": "Approved",
  "published_at": "2026-01-12T11:00:00Z",
  "sections": [
    {
      "title": "Source of funds",
      "description": null,
      "items": [
        {
          "uuid": "4f1d5e2c-aaaa-4d2c-9eb6-fdc6c7c92ef9",
          "value": "q_source_of_funds",
          "element_type": "SINGLE_CHOICE",
          "is_required": true,
          "title": "What is your main source of funds?",
          "description": null,
          "placeholder": null,
          "choices": [
            { "label": "Salary", "value": "salary" },
            { "label": "Business income", "value": "business" },
            { "label": "Investments", "value": "investments" }
          ],
          "max_files": 1,
          "required_if": null,
          "repeatable_config": null,
          "answer": { "value": "salary" }
        }
      ]
    }
  ],
  "node_id": "first_questionnaire"
}
```

### 전자 서명

[전자 서명](https://docs.didit.me/ko/core-technology/electronic-signature/overview.md) 단계의 서명자마다 반환됩니다. KYC 및 KYB 세션 모두에서 `GET /v3/session/{sessionId}/decision/`의 `signatures[]`로 나타나며, 워크플로에 해당 단계가 있는 경우에만 나타납니다. 다른 보고서 객체와 달리 `status`는 서명 단계이고 결과는 `verdict`에 있습니다. 또한 `warnings[]` 항목은 [경고 객체](#경고-객체)가 아니라 `{ code, node_id }`입니다.

| 필드 | 타입 | 널 허용 여부 | 설명 | 예시 |
| - | - | - | - | - |
| `id` | 문자열 (UUID) | 아니요 | 서명자의 서명 ID입니다. 증거 및 검증 경로에서 `signature_id`로 사용하세요. | `"0e6c2a8e-…"` |
| `node_id` | 문자열 | 아니요 | 워크플로 노드 식별자입니다. | `"feature_signature"` |
| `status` | 문자열 | 아니요 | 서명 단계: `intro`, `review`, `code`, `signing`, `signed`, `declined`. 문서가 서명 완료된 상태는 `signed`뿐입니다. | `"signed"` |
| `verdict` | 문자열 | 아니요 | `Not Finished`, `Approved`, `In Review`, `Declined` 중 하나입니다. | `"Approved"` |
| `level` | 문자열 | 아니요 | `simple`(기본값) 또는 `aes`입니다. `qes`는 추가 기능이며 아직 사용할 수 없습니다. | `"aes"` |
| `format` | 문자열 | 아니요 | 단순 서명은 `pdf`, 고급(AES) 서명은 `pades`입니다. | `"pades"` |
| `profile` | 문자열 | 예 | 고급(AES) 서명이 서명 완료되면 `PAdES-B-LT`이며, 그 밖에는 null입니다. | `"PAdES-B-LT"` |
| `signer` | 객체 | 아니요 | `{ name, capacity, company, role, roles, identity_session_id }`입니다. `capacity`는 `self`(KYC) 또는 `company`(KYB)입니다. | `{ "name": "Jane Doe", "capacity": "self", … }` |
| `identity_used` | 객체 | 아니요 | `{ session_id, kyc_id, verified, expected_name }`입니다. 서명이 근거로 하는 검증된 신원입니다. 검증된 신원이 없는 단순 서명에서는 비어 있습니다. | `{ "verified": true, … }` |
| `certificate` | 객체 | 예 | `{ issuer, issued_to, serial, valid_from, valid_until }`입니다. 서명 완료 전까지는 `null`이며, 단순 서명에서는 항상 `null`입니다. | `{ "serial": "5A3F9C21", … }` |
| `confirmation` | object | 아니요 | `{ channel, destination, confirmed_at, attempts }`. `destination`은 마스킹됩니다. `attempts`는 입력된 코드 수를 나타내며, 올바른 코드도 포함됩니다. 단순 서명(Simple signature)에는 코드가 없으므로 `channel`과 `destination`은 `null`입니다. | `{ "channel": "email", … }` |
| `timestamp` | object | 예 | `{ time, qualified, valid }`. `qualified`는 AES에서 항상 `false`입니다. 서명 전에는 `null`이며, 단순 서명에서는 항상 `null`입니다. | `{ "qualified": false, … }` |
| `documents` | array of objects | 아니요 | `{ id, uuid, title, file_name, pages, size_bytes, sha256_original, sha256_signed, status, opened_at, read_at, read_to_end, consented_at, consent, signed_file, mode, source_format, conversion, fields }`. `status`는 `signed`, `declined`, `not_signed`, `not_reached` 중 하나입니다. `mode`는 `fields` 또는 `read_and_agree`입니다. `source_format`은 `pdf` 또는 `docx`입니다. `conversion`은 원본 Word 파일을 설명하며, PDF인 경우 `null`입니다. | `[…]` |
| `documents[].fields` | array of objects | 아니요 | 문서의 각 필드에 대한 `{ key, type, role, label, page, x, y, width, height, required, value, display_value, value_source, filled_at, image_url, value_unavailable_reason }`. `value`는 문자열, 체크박스의 경우 불리언, 적용된 서명 또는 이니셜의 경우 `true`입니다. 필드가 없는 문서에서는 비어 있습니다. | `[…]` |
| `adopted_signature` | object | 예 | `{ method, font, adopted_at }`: 서명자가 채택한 서명과 이니셜입니다. `method`는 `typed` 또는 `drawn`입니다. `font`는 입력 서명의 필기체 스타일입니다. 채택 전에는 `null`입니다. | `{ "method": "drawn", … }` |
| `electronic_signature_consent_at` | string (ISO 8601) | 예 | 서명자가 문서에 전자적으로 서명하는 데 동의한 시점입니다. 문서 중 하나라도 필드가 있으면 설정됩니다. | `"2026-11-03T10:41:40Z"` |
| `evidence_file` | string | 예 | 서명이 완료된 후 증거 PDF의 경로입니다. | `"/v3/session/…/evidence/?signature_id=…"` |
| `warnings` | array of objects | 아니요 | `{ code, node_id }`이며, `code`는 `SIGNATURE_DECLINED`, `SIGNATURE_OTP_FAILED`, `SIGNATURE_NAME_MISMATCH`, `SIGNATURE_IDENTITY_NOT_VERIFIED`, `SIGNATURE_DOCUMENT_CHANGED` 중 하나입니다. | `[]` |
| `validation` | object | 예 | `{ valid, checked_at, documents[] }`: 서명된 문서에 대한 마지막 암호학적 검증입니다. 서명 전에는 `null`입니다. 서명 결과를 확인할 수 없는 경우 `{ valid: null, reason: "signature_provider_outcome_unknown", checked_at }`입니다. | `{ "valid": true, … }` |
| `declined_at` | string (ISO 8601) | 예 | 서명자가 서명을 거부한 시점입니다. | `null` |
| `declined_action` | string | 아니요 | 해당 단계의 `signature_declined_action`입니다. | `"REVIEW"` |
| `signed_at` | string (ISO 8601) | 예 | 문서에 서명한 시점입니다. | `"2026-11-03T10:42:24Z"` |
| `expires_at` | string (ISO 8601) | 아니요 | 서명 링크가 작동을 멈추는 시점입니다. | `"2026-11-10T10:30:00Z"` |
| `email_sent_at` | string (ISO 8601) | 예 | 서명자에게 서명된 사본을 이메일로 보낸 시점입니다. | `"2026-11-03T10:42:30Z"` |
| `email_unavailable_reason` | string | 예 | 사본을 요청했으나 이메일로 보내지 않은 이유입니다. | `null` |
| `ip_address` | string | 예 | 서명자가 코드를 요청했을 때의 IP 주소입니다. | `"203.0.113.10"` |
| `place` | string | 예 | 수집되지 않으며, 항상 `null`입니다. | `null` |
| `place_unavailable_reason` | string | 예 | `not_collected`. | `"not_collected"` |

[전자 서명 보고서](https://docs.didit.me/ko/core-technology/electronic-signature/report-electronic-signature.md)에 전체 예시와 중첩된 모든 필드가 있습니다.

### 연령 추정

독립형 연령 추정 API(`POST /v3/age-estimation/`)가 반환합니다. 응답은 `age_estimation` 래퍼 아래에 [`Liveness check`](#라이브니스-검사)의 구조 일부를 담고 있습니다. 포함되는 필드는 `status`, `method`, `score`, `age_estimation`, `warnings`이며, 독립형 API에만 있는 `user_image` 얼굴 감지 블록이 추가됩니다. **포함되지 않는** 필드는 `reference_image`, `video_url`, `matches`, `face_quality`, `face_luminance`입니다. 워크플로 세션에는 별도의 배열이 없습니다. 추정된 연령은 `GET /v3/session/{sessionId}/decision/`의 `liveness_checks[].age_estimation`으로 제공됩니다. 출처: `apis/serializers/age_estimation.py:50-55`(`AgeEstimationResponseSerializer`), 래퍼는 `apis/views/age_estimation.py:138-174`에서 조립됩니다.

| 필드 | 타입 | Null 허용 | 설명 | 예시 |
| - | - | - | - | - |
| `request_id` | string (UUID) | 아니요 | `save_api_request=true`(기본값)일 때 저장된 세션 ID이며, 그렇지 않으면 일시적인 상관관계 UUID입니다. | `"3b1f1e2c-…"` |
| `age_estimation` | object | 아니요 | 결과 래퍼: `status`(`Approved` / `Declined`), `method`(항상 `PASSIVE`), `score`(라이브니스 0-100, null 가능), `age_estimation`(가장 큰 얼굴의 예측 연령(년), null 가능), `user_image`(얼굴별 `age`, `bbox` `[x_min, y_min, x_max, y_max]`, `confidence`, `gender`를 담은 `entities[]`, 그리고 `best_angle`), `warnings[]`. | `{ … }` |
| `vendor_data` | string | 예 | 요청에서 그대로 반환된 `vendor_data`입니다. | `null` |
| `metadata` | object | 예 | 요청에서 그대로 반환된 `metadata`입니다. | `null` |
| `created_at` | string (ISO 8601) | 아니요 | 서버 측 요청 타임스탬프입니다. | `"2026-05-17T10:22:13.512941+00:00"` |

```json theme={null}
{
  "request_id": "3b1f1e2c-7777-4d2c-9eb6-fdc6c7c92ef9",
  "age_estimation": {
    "status": "Approved",
    "method": "PASSIVE",
    "score": 94.10,
    "age_estimation": 28.7,
    "user_image": {
      "entities": [
        { "age": 28.7, "bbox": [40, 40, 100, 100], "confidence": 0.72, "gender": "male" }
      ],
      "best_angle": 0
    },
    "warnings": []
  },
  "vendor_data": null,
  "metadata": null,
  "created_at": "2026-05-17T10:22:13.512941+00:00"
}
```

### 생체 인증

생체 인증은 표준 KYC에서 사용하는 것과 같은 라이브니스 + 얼굴 대조 파이프라인을 실행하지만, 캡처한 얼굴을 새로 OCR 처리한 문서 초상 대신 기존 사용자의 참조 이미지와 비교하도록 구성됩니다. 전용 시리얼라이저는 없습니다. `GET /v3/session/{sessionId}/decision/`이 표준 [라이브니스 검사](#라이브니스-검사) 및 [얼굴 대조](#얼굴-대조) 객체를 `liveness_checks[]`와 `face_matches[]` 아래에 반환합니다. 세션의 워크플로는 `workflow_type = "biometric_authentication"`으로 설정됩니다(`WorkflowTypeChoices`, `common/config/choices.py:636`).

| 필드 | 타입 | Null 허용 | 설명 | 예시 |
| - | - | - | - | - |
| `liveness_checks` | array of [라이브니스 검사](#라이브니스-검사) | 아니요 | 인증 시도에 대한 라이브니스 결과입니다. | `[ { "status": "Approved", … } ]` |
| `face_matches` | array of [얼굴 대조](#얼굴-대조) | 아니요 | 등록된 참조 이미지에 대한 대조 결과입니다. `source_image_session_id`는 세션 자체의 `session_id`로 설정됩니다. 참조 얼굴(제공된 `portrait_image`, 또는 `portrait_image`를 생략한 경우 `vendor_data`를 통해 재사용되는 저장된 얼굴)은 인증 세션 자체에 기록됩니다(`face/views/face.py:656-659`). | `[ { "status": "Approved", "source_image_session_id": "…", … } ]` |
| `status` | string | 아니요 | 최상위 세션 상태([Status enum](#상태-열거형-참조) 참조). | `"Approved"` |

```json theme={null}
{
  "session_id": "9b1f1e2c-8888-4d2c-9eb6-fdc6c7c92ef9",
  "status": "Approved",
  "liveness_checks": [
    {
      "status": "Approved",
      "method": "PASSIVE",
      "score": 95.10,
      "reference_image": "https://<media-host>/.../reference.jpg?signature=...",
      "video_url": null,
      "age_estimation": null,
      "matches": [],
      "face_quality": 91.20,
      "face_luminance": 53.10,
      "node_id": "biometric_auth_liveness",
      "warnings": []
    }
  ],
  "face_matches": [
    {
      "status": "Approved",
      "score": 98.42,
      "source_image_session_id": "9b1f1e2c-8888-4d2c-9eb6-fdc6c7c92ef9",
      "source_image": "https://<media-host>/.../source.jpg?signature=...",
      "target_image": "https://<media-host>/.../target.jpg?signature=...",
      "node_id": "biometric_auth_face_match",
      "warnings": []
    }
  ]
}
```

### KYB 법인 등기부

KYB 워크플로에서 법인 등기부로 확인된 회사마다 반환됩니다. 기업 세션의 `GET /v3/session/{sessionId}/decision/` 응답에 `registry_checks[]`로 나타납니다. 출처: `kyb/serializers/kyb.py:939-964` (`RegistryCheckV3Serializer`).

| 필드 | 타입 | Null 허용 | 설명 | 예시 |
| - | - | - | - | - |
| `status` | string | 아니요 | 상태 열거형([Status enum](#상태-열거형-참조)) 참조. | `"Approved"` |
| `node_id` | string \| null | 예 | 워크플로 노드 식별자(V3)입니다. | `"first_registry"` |
| `data_resolved` | boolean | 아니요 | 레지스트리 조회가 완료되었을 때 `true`입니다(또는 `is_from_registry`가 `false`인 경우, 즉 데이터를 수동으로 입력한 경우입니다). | `true` |
| `company` | object | 아니요 | 전체 회사 페이로드입니다. 아래 [회사 객체](#회사-객체)를 참조하세요. | `{ … }` |
| `ownership_structure` | object | 예 | 법인 등기부에서 확인한 지분표입니다. 각 소유자의 등기부상 신원, 지분, 표준 `shareholding`이 포함된 `shareholders[]`와 `beneficial_owners[]`로 구성됩니다. | `{ "shareholders": [...], "beneficial_owners": [] }` |
| `warnings` | array | 아니요 | [경고 객체](#경고-객체)를 참조하세요. | `[]` |

#### 회사 객체

출처: `kyb/serializers/kyb.py:220-321` (`KYBCompanyResponseSerializer`).

| 필드 | 타입 | Null 허용 | 설명 |
| - | - | - | - |
| `uuid` | string (UUID) | 아니요 | 내부 회사 식별자입니다. |
| `node_id` | string \| null | 예 | 워크플로 노드 식별자입니다. |
| `status` | string | 아니요 | 기능 상태(`FeatureStatusChoices`)입니다. |
| `registry_status` | string | 예 | 레지스트리의 회사 상태(`active`, `dissolved`, …)입니다. |
| `data_resolved` | boolean | 아니요 | 상위 객체와 정의가 같습니다. |
| `company_name` | string | 예 | 등록된 회사명입니다. |
| `registration_number` | string | 예 | 레지스트리 식별자입니다. |
| `country_code` | string (ISO 3166-1 alpha-2) | 예 | 설립 국가입니다. |
| `region` | string | 예 | 해당되는 경우 ISO 3166-2 하위 지역입니다(예: `US-CA`). |
| `company_type` | string | 예 | 법적 형태입니다(`LLC`, `SL`, …). |
| `incorporation_date` | string (YYYY-MM-DD) | 예 | 설립일입니다. |
| `registered_address` | string | 예 | 등록된 법적 주소입니다. |
| `tax_number` | string | 예 | 세금 / VAT 식별자입니다. |
| `risk_level` | string | 예 | 제공업체가 제공한 위험 등급입니다. |
| `verification_status` | string | 예 | 내부 인증 상태 열거형입니다. |
| `is_from_registry` | boolean | 아니요 | 레지스트리에서 가져온 경우 `true`입니다(수동 입력인 경우와 대비됩니다). |
| `fetch_status` | string | 예 | `pending`, `resolved`, `failed`입니다. |
| `alternative_names` | string | 예 | 쉼표로 구분된 대체 상호명입니다. |
| `nature_of_business` | string | 예 | 자유 형식의 사업 활동 설명입니다. |
| `registered_capital` | string | 예 | 사람이 읽을 수 있는 문자열 형태의 등록 자본입니다. |
| `registered_capital_amount` | string (decimal) | 예 | 파싱된 등록 자본 금액입니다. |
| `registered_capital_currency` | string (ISO 4217) | 예 | 통화 코드입니다. |
| `website` | string (URL) | 예 | 회사 웹사이트입니다. |
| `email` | string | 예 | 공개 연락처 이메일입니다. |
| `phone` | string | 예 | 공개 연락처 전화번호입니다. |
| `legal_entity_identifier` | string | 예 | 사용 가능한 경우의 LEI입니다. |
| `location_of_registration` | string | 예 | 레지스트리 사무소 또는 지역입니다. |
| `vat_number` | string | 예 | 회사에 대해 제출된 VAT 번호입니다. |
| `vat_validation_status` | string | 아니요 | VAT 번호 검증 결과입니다. VAT 번호가 없으면 `tax_number`의 검증 결과입니다: `valid`, `invalid`, `format_valid`, `invalid_format`, `could_not_validate`, 또는 `not_applicable`. [VAT 및 세금 ID 검증](https://docs.didit.me/ko/business-verification/company-data.md#vat-및-납세자-번호-검증)을 참조하세요. |
| `vat_validated_number` | string | 예 | 확인된 번호입니다. 출처가 알고 있는 형태 그대로입니다. |
| `vat_validation_source` | string | 예 | 상태를 결정한 출처입니다: `eu_vies`, `pl_vat_white_list`, `no_brreg`, `ch_uid_register`, `br_receita_federal`, `co_rues`, `cr_hacienda`, `ec_sri`, `py_dnit`, 또는 `format_rules`. |
| `vat_validated_name` | string | 예 | 출처에 등록된 이름입니다(출처가 공개하지 않으면 비어 있습니다). |
| `vat_validated_address` | string | 예 | 출처에 등록된 주소입니다(공개되지 않으면 비어 있습니다). |
| `vat_checked_at` | string (ISO 8601) | 예 | 확인 시각입니다. 확인이 실행되지 않았으면 `null`입니다. |
| `financial_summary` | object | 예 | 레지스트리가 제공한 경우 최신 재무 주요 항목의 스냅샷입니다. |
| `officers` | array of objects | 아니요 | B2C에서 안전하게 노출되는 임원 목록입니다: `{ uuid, name, designation, role, nationality, is_active, kyc_status, kyc_session_url }`. |
| `beneficial_owners` | array of objects | 아니요 | B2C에서 안전하게 노출되는 UBO 목록입니다: `{ uuid, name, first_name, last_name, entity_type, roles, ownership_min_shares, ownership_max_shares, is_active, kyc_status, kyc_session_url, effective_ownership_percent }`. |
| `addresses` | array of objects | 예 | 레지스트리의 주소별 상세 정보입니다. |
| `industries` | array of objects | 예 | SIC/NAICS 방식의 업종 분류입니다. |
| `accounts` | array of objects | 예 | 제출된 회계 자료의 메타데이터입니다. |
| `registry_data` | object | 예 | Didit의 정규화된 레지스트리 상세 정보입니다(소유 구조 결과, 콘솔 수정 사항, 전용 필드가 없는 레지스트리 사실). 안정적인 계약이 아닙니다. |
| `user_provided_data` | object | 예 | 사용자가 수정한 필드의 스냅샷입니다. |
| `confirmed_by_user_at` | string (ISO 8601) | 예 | 사용자가 추출된 데이터를 확인한 시각입니다. |
| `last_console_edit_at` | string (ISO 8601) | 예 | 마지막 콘솔 수정 시각입니다. |
| `is_editable` | boolean | 아니요 | 최종 사용자가 레지스트리 출처 데이터를 아직 수정할 수 있으면 `true`입니다. |

```json theme={null}
{
  "status": "Approved",
  "node_id": "first_registry",
  "data_resolved": true,
  "company": {
    "uuid": "b1f1e2c2-9999-4d2c-9eb6-fdc6c7c92ef9",
    "node_id": "first_registry",
    "status": "Approved",
    "registry_status": "active",
    "data_resolved": true,
    "company_name": "Sante Clinics SL",
    "registration_number": "B12345678",
    "country_code": "ES",
    "region": null,
    "company_type": "SL",
    "incorporation_date": "2018-03-22",
    "registered_address": "Calle Mayor 1, 28001 Madrid, Spain",
    "tax_number": "B12345678",
    "risk_level": "low",
    "verification_status": "verified",
    "is_from_registry": true,
    "fetch_status": "resolved",
    "alternative_names": "Sante Clinics",
    "nature_of_business": "Medical clinic operations",
    "registered_capital": "EUR 50,000",
    "registered_capital_amount": "50000.00",
    "registered_capital_currency": "EUR",
    "website": "https://santeclinics.com",
    "email": "info@santeclinics.com",
    "phone": "+34911223344",
    "legal_entity_identifier": null,
    "location_of_registration": "Registro Mercantil de Madrid",
    "vat_number": "ESB12345678",
    "vat_validation_status": "valid",
    "vat_validated_name": "SANTE CLINICS SL",
    "vat_validated_address": "CALLE MAYOR 1, 28001 MADRID",
    "vat_checked_at": "2026-05-17T10:11:05Z",
    "financial_summary": null,
    "officers": [
      {
        "uuid": "c1f1e2c2-aaaa-4d2c-9eb6-fdc6c7c92ef9",
        "name": "María García López",
        "designation": "Administrador único",
        "role": "Director",
        "nationality": "ESP",
        "is_active": true,
        "kyc_status": "Approved",
        "kyc_session_url": "https://verify.didit.me/s/…"
      }
    ],
    "beneficial_owners": [
      {
        "uuid": "d1f1e2c2-bbbb-4d2c-9eb6-fdc6c7c92ef9",
        "name": "María García López",
        "first_name": "María",
        "last_name": "García López",
        "entity_type": "person",
        "roles": ["UBO"],
        "ownership_min_shares": "75.00",
        "ownership_max_shares": "75.00",
        "is_active": true,
        "kyc_status": "Approved",
        "kyc_session_url": "https://verify.didit.me/s/…",
        "effective_ownership_percent": 75.0
      }
    ],
    "addresses": [],
    "industries": [],
    "accounts": [],
    "registry_data": {},
    "user_provided_data": {},
    "confirmed_by_user_at": "2026-05-17T10:11:02Z",
    "last_console_edit_at": null,
    "is_editable": false
  },
  "ownership_structure": null,
  "warnings": []
}
```

### KYB 문서

KYB 증빙 문서를 수집하는 노드마다 반환됩니다. 기업 세션의 `GET /v3/session/{sessionId}/decision/` 응답에 `document_verifications[]`로 나타나며, `node_id`마다 한 항목이 있고 각 항목의 `items[]`에 업로드된 문서가 하나씩 나열됩니다. 출처: `kyb/serializers/kyb.py:1053-1068` (`DocumentVerificationV3Serializer`). 각 항목은 `kyb/serializers/kyb.py:811-851` (`KYBDocumentResponseSerializer`)을 따릅니다.

| 필드 | 타입 | Null 허용 | 설명 | 예시 |
| - | - | - | - | - |
| `status` | 문자열 | 아니요 | 이 노드 문서 전체의 집계 상태입니다. 이 노드의 모든 문서가 승인된 경우에만 `Approved`이고, 문서 중 하나라도 거부되면 `Declined`입니다. 그 밖의 경우에는 `In Review`입니다. 대기 중에는 `Not Finished`입니다. 자세한 내용은 [상태 열거형](#상태-열거형-참조)을 참고하세요. | `"Approved"` |
| `node_id` | 문자열 \| null | 예 | 워크플로 노드 식별자(V3)입니다. | `"first_kyb_documents"` |
| `items` | [KYB 문서 항목 객체](#kyb-문서-항목-객체) 배열 | 아니요 | 업로드되었거나 요청된 문서마다 하나의 항목이 있습니다. | `[…]` |
| `groups` | 객체 | 아니요 | 문서 그룹별 개수입니다: `{ <group_name>: { total, approved, pending, declined, in_review, other, missing } }`. | `{ "incorporation_certificate": { "total": 1, "approved": 1, "pending": 0, "declined": 0, "in_review": 0, "other": 0, "missing": 0 } }` |
| `required_groups` | 문자열 배열 | 아니요 | 워크플로 구성에서 요구하는 문서 그룹입니다. | `["incorporation_certificate", "shareholder_register"]` |
| `warnings` | 배열 | 아니요 | [경고 객체](#경고-객체)를 참고하세요. | `[]` |

#### KYB 문서 항목 객체

| 필드 | 타입 | 널 허용 | 설명 |
| - | - | - | - |
| `uuid` | 문자열 (UUID) | 아니요 | 내부 문서 식별자입니다. |
| `document_type` | 문자열 | 예 | 상위 그룹(`incorporation_certificate`, `shareholder_register`, …)입니다. |
| `document_subtype` | 문자열 | 예 | 제공업체별 하위 유형입니다. |
| `document_group` | 문자열 | 예 | `document_type`과 같은 값입니다(명확성을 위해 유지된 별칭). |
| `file_url` | 문자열 (URL) | 예 | 정리된 파일의 사전 서명된 URL입니다. |
| `original_filename` | 문자열 | 예 | 업로드된 파일 이름입니다. |
| `file_size` | 정수 | 예 | 파일 크기(바이트)입니다. |
| `status` | 문자열 | 아니요 | 문서별 상태(`FeatureStatusChoices`)입니다. |
| `created_at` | 문자열 (ISO 8601) | 아니요 | 업로드 타임스탬프입니다. |
| `cross_check_result` | 객체 | 예 | 등기부 및 다른 문서와의 교차 검증 결과입니다. |
| `document_metadata` | 객체 | 예 | 주소 증명(POA)의 `document_metadata`와 같은 필터링된 메타데이터 형식입니다. |
| `description` | 문자열 | 예 | 검토자 또는 시스템이 입력한 설명입니다. |
| `is_requested` | 불리언 | 아니요 | 워크플로에서 이 문서를 요구한 경우 `true`입니다. |
| `ocr_data` | 객체 | 예 | 사용 가능한 경우 OCR로 추출한 필드입니다. |
| `is_console_upload` | 불리언 | 아니요 | 콘솔 검토자가 업로드한 문서인 경우 `true`입니다(전체 집계 결과에서 제외됨). |
| `is_confirmed` | 불리언 | 아니요 | 검토자가 문서를 명시적으로 확인한 경우 `true`입니다. |

```json theme={null}
{
  "status": "Approved",
  "node_id": "first_kyb_documents",
  "items": [
    {
      "uuid": "e1f1e2c2-cccc-4d2c-9eb6-fdc6c7c92ef9",
      "document_type": "incorporation_certificate",
      "document_subtype": "registro_mercantil_extract",
      "document_group": "incorporation_certificate",
      "file_url": "https://<media-host>/.../incorporation.pdf?signature=...",
      "original_filename": "incorporation_certificate.pdf",
      "file_size": 256412,
      "status": "Approved",
      "created_at": "2026-05-17T10:08:00Z",
      "cross_check_result": { "matches_registry_name": true, "matches_registration_number": true },
      "document_metadata": {
        "file_size": 256412,
        "content_type": "application/pdf",
        "is_signed": true,
        "is_tampered": false
      },
      "description": null,
      "is_requested": true,
      "ocr_data": { "company_name": "Sante Clinics SL", "registration_number": "B12345678" },
      "is_console_upload": false,
      "is_confirmed": true
    }
  ],
  "groups": {
    "incorporation_certificate": { "total": 1, "approved": 1, "pending": 0, "declined": 0, "in_review": 0, "other": 0, "missing": 0 }
  },
  "required_groups": ["incorporation_certificate", "shareholder_register"],
  "warnings": []
}
```

### KYB 주요 인물

기업 세션의 KYB 워크플로에서 주요 인물(Key People) 노드마다 반환됩니다. 기업 세션의 `GET /v3/session/{sessionId}/decision/` 응답에 `key_people_checks[]`로 나타납니다. 출처: `kyb/serializers/kyb.py:967-1050` (`KeyPeopleCheckV3Serializer`).

| 필드 | 타입 | 널 허용 | 설명 | 예시 |
| - | - | - | - | - |
| `status` | 문자열 | 아니요 | [상태 열거형](#상태-열거형-참조)을 참고하세요. | `"Approved"` |
| `node_id` | 문자열 \| null | 예 | 워크플로 노드 식별자(V3)입니다. | `"first_key_people"` |
| `registry` | 객체 | 아니요 | 등기부에서 추출한 `{ officers[], beneficial_owners[] }`입니다. officers는 `KYBPersonResponseSerializer`(`kyb/serializers/kyb.py:533-645`)를 따르고, beneficial\_owners는 `KYBBeneficialOwnerResponseSerializer`(`kyb/serializers/kyb.py:648-788`)를 따르며, `date_of_birth`, `country_of_birth`, `email`, `company_name`, `registration_number`, `entity_type`, `roles`, `ownership_min_shares`, `ownership_max_shares`, `child_beneficial_owners`, `effective_ownership_percent`를 추가로 포함합니다. 두 항목 모두 당사자별 AML 및 KYC 보강 정보를 포함합니다(`aml_status`, `kyc_status`, `kyc_session_url`, `kyc_session_id`, `verification_workflow_type`, `verification_workflow_id`, `verification_workflow_label`, `verification_workflow_features`, `didit_internal_id`, `kyc_document_type`, `kyc_nationality`, `kyc_liveness_passed`, `kyc_verified_at`, `kyc_aml_categories`, `kyc_notification_sent_at`). | `{ "officers": [...], "beneficial_owners": [...] }` |
| `submitted` | 객체 | 아니요 | `{ parties[] }` - 기업이 주요 인물 흐름을 통해 확인하거나 제출한 항목(`source=USER`인 `BusinessParty` 행)입니다. 각 당사자는 `BusinessPartySubmissionResponseSerializer`(`kyb/serializers/party.py:146-194`)를 따릅니다: `uuid`, `entity_type`, `source`, `name`, `first_name`, `last_name`, `company_name`, `registration_number`, `email`, `nationality`, `phone_number`, `date_of_birth`, `position`, `custom_fields`, `is_active`, `is_skipped`, `requires_verification`, `roles[]`(`{ role, ownership_percent, voting_percent }`), `kyc_session_id`, `kyc_session_status`, `kyc_session_url`, `kyc_session_deleted`, `kyb_sub_session_id`, `kyb_sub_session_status`, `kyb_sub_session_url`, `kyb_sub_session_deleted`, `verification_workflow_type`, `verification_workflow_id`, `verification_workflow_label`, `verification_workflow_features`, `didit_internal_id`. `kyc_session_deleted` 및 `kyb_sub_session_deleted`는 삭제된 하위 세션을 나타냅니다. 이 경우 세션 상태는 삭제 당시 값으로 고정되고, 해당 `*_session_url`은 링크가 더 이상 연결되지 않으므로 `null`로 반환되며, 해당 당사자는 상위 검사를 더 이상 차단하지 않습니다(대신 검사 상태가 `In Review`로 변경됩니다). 이 플래그를 해제하려면 [`PATCH /v3/session/{id}/kyb/parties/{party_uuid}/`](https://docs.didit.me/ko/sessions-api/update-data#주요-인물-당사자-건너뛰기)를 사용하세요. | `{ "parties": [...] }` |
| `ubo_kyc_summary` | 객체 | 예 | 연결된 KYC가 있는 활성 UBO의 개수입니다: `{ total, approved, flagged, pending }`. 연결된 KYC가 있는 활성 UBO가 없으면 `null`입니다. | `{ "total": 2, "approved": 2, "flagged": 0, "pending": 0 }` |
| `warnings` | 배열 | 아니요 | [경고 객체](#경고-객체)를 참고하세요. | `[]` |

```json theme={null}
{
  "status": "Approved",
  "node_id": "first_key_people",
  "registry": {
    "officers": [
      {
        "uuid": "c1f1e2c2-aaaa-4d2c-9eb6-fdc6c7c92ef9",
        "name": "María García López",
        "designation": "Administrador único",
        "role": "Director",
        "nationality": "ESP",
        "appointment_date": "2018-03-22",
        "termination_date": null,
        "is_active": true,
        "address": "Calle Mayor 1, 28001 Madrid",
        "aml_status": "Approved",
        "kyc_status": "Approved",
        "kyc_session_url": "https://verify.didit.me/s/…",
        "kyc_session_id": "9b1f1e2c-8888-4d2c-9eb6-fdc6c7c92ef9",
        "verification_workflow_type": "kyc",
        "verification_workflow_id": "11111111-1111-1111-1111-111111111111",
        "verification_workflow_label": "KYB officer KYC",
        "verification_workflow_features": [
          { "feature": "ID_VERIFICATION", "status": "Approved" },
          { "feature": "LIVENESS", "status": "Approved" },
          { "feature": "FACE_MATCH", "status": "Approved" }
        ],
        "didit_internal_id": "user-12345",
        "kyc_document_type": "Passport",
        "kyc_nationality": "ESP",
        "kyc_liveness_passed": true,
        "kyc_verified_at": "2026-05-17T10:10:11Z",
        "kyc_aml_categories": [],
        "kyc_notification_sent_at": "2026-05-15T08:00:00Z"
      }
    ],
    "beneficial_owners": []
  },
  "submitted": {
    "parties": [
      {
        "uuid": "d1f1e2c2-bbbb-4d2c-9eb6-fdc6c7c92ef9",
        "entity_type": "person",
        "source": "USER",
        "name": "María García López",
        "first_name": "María",
        "last_name": "García López",
        "company_name": null,
        "registration_number": null,
        "email": "maria.garcia@example.com",
        "nationality": "ESP",
        "phone_number": null,
        "date_of_birth": "1990-05-12",
        "position": "Administrador único",
        "custom_fields": {},
        "is_active": true,
        "is_skipped": false,
        "requires_verification": true,
        "roles": [
          { "role": "UBO", "ownership_percent": 75.0, "voting_percent": null }
        ],
        "kyc_session_id": "9b1f1e2c-8888-4d2c-9eb6-fdc6c7c92ef9",
        "kyc_session_status": "Approved",
        "kyc_session_url": "https://verify.didit.me/s/…",
        "kyb_sub_session_id": null,
        "kyb_sub_session_status": null,
        "kyb_sub_session_url": null,
        "verification_workflow_type": "kyc",
        "verification_workflow_id": "11111111-1111-1111-1111-111111111111",
        "verification_workflow_label": "KYB officer KYC",
        "verification_workflow_features": [
          { "feature": "ID_VERIFICATION", "status": "Approved" },
          { "feature": "LIVENESS", "status": "Approved" }
        ],
        "didit_internal_id": "user-12345"
      }
    ]
  },
  "ubo_kyc_summary": { "total": 1, "approved": 1, "flagged": 0, "pending": 0 },
  "warnings": []
}
```

## 결정 수준 필드

이 키들은 `GET /v3/session/{sessionId}/decision/`의 기능 배열 옆에 있으며, webhook의 `decision` 안에도 있습니다.

| 필드 | 유형 | 널 허용 여부 | 설명 |
| - | - | - | - |
| `status_override` | 객체 | 예 | 검토자가 `status`를 직접 설정한 뒤의 `{ overridden_at, automatic_status }`입니다. 상태가 자동 상태이면 `null`입니다. |
| `decision_trace` | 객체 | 아니요 | 상태에 도달한 경위입니다: `status`, `decided_by`(`manual`, `automatic` 또는 `investigator`), `decided_at`, `automatic_status`, `terminal_node_id`, `actor`, `warning_counts`, `status_warnings`. |
| `linked_records` | 객체 | 예 | `same_face`, `earlier_verifications`, `networks` 요약입니다. 표시할 내용이 없으면 `null`입니다. |
| `biometric_retention` | 객체 | 아니요 | `{ jurisdictions, deletes_at }`입니다. `deletes_at`은 세션의 실시간 생체 데이터가 삭제되는 날짜이며, 적용되는 날짜가 아직 없으면 `null`입니다. |
| `database_validation_not_performed_reason` | 객체 | 예 | 설정된 데이터베이스 검증에서 결과가 나오지 않은 이유를 설명하는 `{ code, message }`입니다. |
| `assignee`, `waiting_since`, `sla_due_at` | 객체, 날짜/시간 | 예 | 세션을 담당하는 Console 검토자와 검토 타이머입니다. 세션이 `In Review` 상태가 아니면 검토 타이머는 `null`입니다. |
| `shared_from_session`, `shared_from_session_number` | UUID, 정수 | 예 | 가져온 세션의 원본 세션입니다. |
| `sandbox_scenario` | 문자열 | 예 | 샌드박스 세션을 생성할 때 사용한 시나리오입니다. |
| `fraud_check` | 객체 | 예 | Fraud Check API 결과입니다. 그 밖의 모든 세션에서는 `null`입니다. |
| `full_session_video`, `full_session_video_recorded_at` | URL, 날짜/시간 | 예 | 녹화 영상과 녹화 시각입니다. 조직에서 전체 세션 영상을 녹화하는 경우에만 반환됩니다. |

읽는 방법은 [세션 조회](https://docs.didit.me/ko/sessions-api/retrieve-session.md#상태-결정-추적-및-검토-필드)를 참조하세요.

## 생체 인식 동의

모든 사용자 인증 결정과 세션 webhook에는 `biometric_consent` 객체가 하나씩 포함됩니다(배열이 아닙니다). 이 객체에는 세션에 명시적인 생체 인식 동의가 필요했는지, 필요했다면 그 이유가 무엇인지, 그리고 응답의 근거가 기록됩니다. 세션이 평가되지 않은 경우(예: 얼굴 캡처가 없는 워크플로)에는 `null`입니다. 소스: `BiometricConsentDecisionSerializer`(`sessions/serializers/biometric_consent.py`). 이 단계가 언제 나타나고 각 경우가 무엇을 의미하는지는 [생체 인식 동의](https://docs.didit.me/ko/getting-started/biometric-consent.md)에서 설명합니다.

기록된 값이 없는 필드는 빈 문자열이 아니라 `null`입니다.

| 필드 | 유형 | 설명 |
| - | - | - |
| `required` | boolean | 세션이 명시적인 생체 인식 동의를 받아야 하는지 여부입니다. 다시 `false`로 바뀌지 않습니다. |
| `trigger` | string (enum) \| null | 동의가 필요한 이유 또는 동의가 충족된 방식입니다: `declared_state`, `ip_state`, `ip_unknown`, `document_issuer`, `forced`(애플리케이션의 모드가 Always인 경우), `customer_collected`(세션 생성 시 `biometric_consent`를 전송한 경우). 필요하지 않은 동안에는 `null`입니다. |
| `status` | string (enum) | `not_required`, `pending`(동의가 필요하지만 아직 주어지지 않음), `given`, `declined`(거부가 기록됨. 현재 Didit 화면에는 거부 옵션이 없습니다). |
| `given_at` | string (ISO 8601) \| null | 동의가 주어진 시점입니다. `customer_collected`의 경우 전송한 `given_at` 값입니다. |
| `declined_at` | string (ISO 8601) \| null | 거부가 기록된 시점입니다. |
| `text_version` | string \| null | 응답자가 동의한 동의 문구의 버전 ID이거나, 전송한 동의 문구의 버전 ID입니다. |
| `text_hash` | string \| null | 표시된 정확한 문구의 SHA-256(16진수) 값으로, 표시된 언어 기준입니다. |
| `locale` | string \| null | 문구가 표시된 언어입니다. |
| `policy_url` | string \| null | 이 단계가 연결한 생체 정보 정책입니다. |
| `step` | string \| null | 응답자가 답했을 때 세션이 머물러 있던 워크플로 단계입니다(예: `LIVENESS`). |
| `node_id` | string \| null | 응답자가 답했을 때 세션이 머물러 있던 워크플로 그래프 노드입니다. |
| `ip_address` | string \| null | 응답이 온 IP입니다. |
| `ip_country_code` | string \| null | 응답 IP의 ISO 3166-1 alpha-2 국가 코드입니다. |
| `ip_state` | string \| null | 응답 IP의 ISO 3166-2 행정구역입니다(예: `US-IL`). |
| `ip_city` | string \| null | 응답 IP의 도시입니다. |
| `user_agent` | string \| null | 응답 요청의 사용자 에이전트입니다. |
| `detected_ip_address` | string \| null | 요구 사항이 마지막으로 평가된 응답자의 IP입니다. 응답자가 다른 기기에서 답한 경우 `ip_address`와 다를 수 있습니다. |
| `detected_country_code` | string \| null | 감지된 IP의 ISO 3166-1 alpha-2 국가 코드입니다. |
| `detected_state` | string \| null | 감지된 IP의 ISO 3166-2 행정구역입니다. |
| `detected_city` | string \| null | 감지된 IP의 도시입니다. |
| `declared_state` | string \| null | 귀하가 선언한 ISO 3166-2 행정구역입니다. `user_state` 값이거나, `expected_details`에 있는 미국 주소의 주입니다. |
| `document_state` | string \| null | 신분증을 발급한 ISO 3166-2 행정구역입니다. 신분증 촬영 시 읽은 값입니다. |
| `jurisdictions` | array of string | 응답자가 생체 인식 법의 적용을 받는 미국 주의 목록입니다(USPS 코드, 예: `IL`). 증거상 응답자가 미국에 있으나 주를 알 수 없는 경우 `US`입니다. 해당하는 경우가 없으면 비어 있습니다. |
| `retention_months` | integer \| null | `jurisdictions`에 해당하는 항목 중 가장 짧은 생체 정보 보존 기한(개월 단위)입니다. 해당하는 항목이 없으면 `null`입니다. |
| `reason` | string (enum) \| null | `BIOMETRIC_CONSENT_UNSUPPORTED_SDK`: 동의가 필요했는데 4.10.0 미만의 네이티브 SDK(또는 버전을 보고하지 않은 SDK)가 단계 없이 얼굴을 캡처한 경우입니다. `status`는 `pending`으로 남으며, 응답자가 나중에 호스팅 흐름에서 동의하면 `given`이 됩니다. `BIOMETRIC_CONSENT_DECLINED`: 거부가 기록된 경우입니다(SDK 사유를 대체합니다). 그 외에는 `null`이며, 세션에 동의가 필요하지 않았다면 항상 `null`입니다. |
| `decline_reason` | string \| null | 기록된 거부로 세션이 종료된 경우 `BIOMETRIC_CONSENT_DECLINED`이고, 그 외에는 `null`입니다. |
| `face_data_deleted_at` | string (ISO 8601) \| null | 거부로 세션의 얼굴 이미지, 영상 및 얼굴 템플릿이 삭제된 시점입니다. 거부가 기록되지 않은 경우 `null`입니다. |

일리노이주 세션이 4.10.0 미만의 네이티브 SDK로 처리되었고, 해당 SDK가 단계 없이 셀피를 캡처한 경우:

```json theme={null}
{
  "required": true,
  "trigger": "ip_state",
  "status": "pending",
  "given_at": null,
  "declined_at": null,
  "text_version": null,
  "text_hash": null,
  "locale": null,
  "policy_url": null,
  "step": null,
  "node_id": null,
  "ip_address": null,
  "ip_country_code": null,
  "ip_state": null,
  "ip_city": null,
  "user_agent": null,
  "detected_ip_address": "203.0.113.42",
  "detected_country_code": "US",
  "detected_state": "US-IL",
  "detected_city": "Chicago",
  "declared_state": null,
  "document_state": null,
  "jurisdictions": ["IL"],
  "retention_months": 36,
  "reason": "BIOMETRIC_CONSENT_UNSUPPORTED_SDK",
  "decline_reason": null,
  "face_data_deleted_at": null
}
```

미국 외부에서 종료되는 VPN을 사용하는 응답자가 호스팅 흐름에서 동의한 경우:

```json theme={null}
{
  "required": true,
  "trigger": "declared_state",
  "status": "given",
  "given_at": "2026-10-13T18:31:07.412000Z",
  "declined_at": null,
  "text_version": "bio-consent-2026-10-12",
  "text_hash": "9b2f0c5e4d8a7f61c3e2b4a5d6f7081923a4b5c6d7e8f90a1b2c3d4e5f6a7b8c",
  "locale": "en",
  "policy_url": "https://didit.me/legal/biometric-data-policy",
  "step": "LIVENESS",
  "node_id": "feature_liveness_1",
  "ip_address": "198.51.100.23",
  "ip_country_code": "ES",
  "ip_state": "ES-M",
  "ip_city": "Madrid",
  "user_agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 18_0_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1",
  "detected_ip_address": "198.51.100.23",
  "detected_country_code": "ES",
  "detected_state": "ES-M",
  "detected_city": "Madrid",
  "declared_state": null,
  "document_state": null,
  "jurisdictions": ["IL"],
  "retention_months": 36,
  "reason": null,
  "decline_reason": null,
  "face_data_deleted_at": null
}
```

## 상태 열거형 참조

두 개의 관련 값 집합이 `status` 필드 이름을 공유합니다. 이 페이지의 기능별 보고서 객체는 모두 기능 수준 열거형을 사용하며, 상위 세션의 최상위 `status`는 더 넓은 세션 열거형을 사용합니다.

### 기능 수준 상태

모든 보고서 객체의 `status` 필드에서 사용합니다. 출처: `common/config/choices.py:343-348` (`FeatureStatusChoices`).

| 값 | 의미 |
| - | - |
| `Not Finished` | 기능이 준비되었지만 사용자가 아직 완료하지 않았습니다. |
| `Approved` | 기능이 모든 검사를 통과했습니다. |
| `Declined` | 기능이 하나 이상의 필수 검사에 실패했습니다(`log_type: "error"`인 `warnings[]` 참조). |
| `In Review` | 기능에서 소프트 실패 신호가 발생해 수동 검토를 기다리고 있습니다(`log_type: "warning"`인 `warnings[]` 참조). |
| `Resub Requested` | 검토자가 사용자에게 이 기능을 다시 제출하도록 요청했습니다. |

전화번호 인증, 이메일 인증 및 신분증 인증은 해당 단계의 시간이 초과되면 `Expired`도 나타낼 수 있습니다(`PhoneStatusChoices`는 `common/config/choices.py:377-382`, `EmailStatusChoices`는 `common/config/choices.py:434-439`).

### 세션 수준 상태

상위 세션의 최상위 `status`에서 사용합니다. 출처: `common/config/choices.py:106-117` (`StatusChoices`).

| 값 | 의미 |
| - | - |
| `Not Started` | 세션이 생성되었지만 사용자가 아직 시작하지 않았습니다. |
| `In Progress` | 사용자가 흐름을 시작했으며 결과는 아직 확정되지 않았습니다. |
| `Approved` | 세션이 모든 검사를 통과했습니다. |
| `Declined` | 세션이 하나 이상의 필수 검사에 실패했습니다. |
| `In Review` | 세션이 수동 검토를 기다리고 있습니다. |
| `Expired` | 세션이 완료되기 전에 만료되었습니다. |
| `Abandoned` | 사용자가 완료하지 않고 흐름을 떠났습니다. |
| `Kyc Expired` | KYC의 유효 기간이 경과했습니다(재인증 흐름에서 사용). |
| `Resubmitted` | 사용자가 이전 거부 후 다시 제출했으며, 이 세션은 더 새로운 세션으로 대체되었습니다. |
| `Awaiting User` | 시스템이 사용자 측 작업을 기다리고 있습니다(예: OTP 입력). |

> [!TIP]
>
> 세션의 종결 상태는 `Approved`, `Declined`, `In Review`, `Expired`, `Kyc Expired`, `Abandoned`입니다. 세션은 개별 기능이 `In Review` 상태에 머무는 동안에도 전체 결정에 도달할 수 있습니다.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.