> ## 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.

# 얼굴 검색(Face Search) 1:N 보고서: 일치 결과 JSON

> Didit의 얼굴 검색 1:N 보고서 레퍼런스입니다. 부정 행위 조사를 위한 일치된 세션 ID, 유사도 백분율, 차단 목록 플래그, 사용자 세부 정보를 확인하세요.

## 개요

얼굴 검색은 **1:N** 생체 인식 검색입니다. Didit은 `user_image`에서 감지된 가장 큰 얼굴을 추출하여 애플리케이션의 얼굴 검색 색인(인증 세션, 저장된 독립형 API 호출, 사용자 프로필 직접 얼굴 업로드 및 차단/허용 목록에서 등록된 얼굴)을 대상으로 검색합니다. 이는 **1:1** 비교인 얼굴 대조와 구별됩니다. 얼굴 대조는 셀피를 특정 신분증의 인물 사진과 비교하는 반면, 얼굴 검색은 "이 사람을 이전에 본 적이 있는가?"를 확인합니다.

보고서를 파싱하기 전에 이해해야 할 두 가지 동작 방식이 있습니다.

* **차단 목록 일치 항목만 거부됩니다.** `face_search.status`는 `FACE_IN_BLOCKLIST` 또는 `POSSIBLE_FACE_IN_BLOCKLIST` 경고가 발생할 때만 `Declined`가 됩니다. 중복 일치 항목만 있는 경우에는 `Approved`를 반환하므로, `status`뿐만 아니라 `matches` 및 `warnings`도 확인해야 합니다.
* **선택적 영속화 및 등록.** `save_api_request=true`(기본값)인 경우 호출은 API 유형 세션으로 영속화되며 검색된 얼굴이 얼굴 검색 색인에 등록됩니다. 얼굴 검색 호출로 등록된 얼굴은 **향후 얼굴 검색 결과에서 제외**되므로, 반복된 검색이 서로 일치하지 않습니다. 일회성 조회의 경우 `save_api_request=false`를 전달하면 아무것도 저장되지 않고 얼굴도 등록되지 않습니다.

## 결과 표시 위치

얼굴 검색은 독립형 API입니다. 검색 결과는 **`POST /v3/face-search/` 응답에서만 동기식으로**, 최상위 레벨의 단일 `face_search` 객체로 반환됩니다.

```text theme={null}
POST /v3/face-search/  ──▶  { "request_id": …, "face_search": { … }, "vendor_data": …, "metadata": …, "created_at": … }
```

어디에도 복수형 `face_searches[]` 배열은 존재하지 않습니다. 세션 결정 endpoint의 `id_verifications[]`, `aml_screenings[]`, `liveness_checks[]`에서 사용되는 복수형 배열 규칙은 적용되지 않습니다.

`save_api_request=true`(기본값)인 경우, 호출은 API 유형 세션으로도 영속화됩니다.

* **비즈니스 콘솔** — 세션 목록에 검색 이미지, 일치 항목 및 경고와 함께 세션이 표시됩니다.
* **`GET /v3/session/{sessionId}/decision/`** — 반환된 `request_id`를 세션 ID로 사용하여 조회할 수 있습니다. 영속화된 데이터는 `face_search` 객체가 **아닌**, `features[]`의 `FACE_SEARCH` 항목 및 저장된 `matches`(새로 서명된 `match_image_url` 값 포함)와 `warnings`를 포함하는 `liveness_checks[]` 항목으로 나타납니다.

`save_api_request=false`인 경우, `request_id`는 일시적인 상관관계 UUID입니다. 세션이 저장되지 않으므로 콘솔이나 결정 endpoint에서 조회할 수 없습니다.

## 스키마

표준 필드 표는 [데이터 모델 참조의 얼굴 검색](https://docs.didit.me/ko/reference/data-models.md#얼굴-검색)을 참고하십시오. 아래 구조는 런타임에 endpoint가 실제로 반환하는 형태를 반영합니다.

```typescript theme={null}
interface FaceSearchResponse {
  request_id: string;            // UUID — the persisted session id when save_api_request=true
  face_search: {
    status: 'Approved' | 'Declined';
    total_matches: number;       // 0-5, length of matches[]
    matches: FaceSearchMatch[];  // capped at 5, ordered by similarity
    user_image: {                // always present
      entities: {
        bbox: [number, number, number, number];
        confidence: number;      // 0-1, one entry per detected face
      }[];
      best_angle: 0 | 90 | 180 | 270;
    };
    warnings: Warning[];
  };
  vendor_data: string | null;    // echoed from the request
  metadata: object | null;       // echoed from the request
  created_at: string;            // ISO 8601, e.g. "2026-06-12T01:04:42.763237+00:00"
}

interface FaceSearchMatch {
  session_id: string | null;     // UUID of the matched session; null for non-session matches
  session_number: number | null; // Console-friendly number; null for non-session matches
  similarity_percentage: number; // 0-100
  source: 'session' | 'imported' | 'list_entry' | 'retained_template';
  vendor_data: string | null;    // the matched session's, imported profile's, or retained template's User vendor_data
  vendor_user_id: string | null; // UUID of the linked User; null for list_entry matches and sessions without a User
  biometric_template_id: string | null; // set only for retained_template matches
  verification_date: string | null;  // "YYYY-MM-DDThh:mm:ssZ"; null for list_entry matches; the retention date for retained_template matches
  user_details: {
    full_name: string | null;
    document_type: string | null;
    document_number: string | null;
  } | null;                      // null when the matched session has no document data
  match_image_url: string | null; // signed URL when save_api_request=true; raw storage path otherwise; null for retained_template matches
  status: 'Approved' | 'Declined' | 'In Review' | null;  // the matched session's status
  is_blocklisted: boolean;
  is_allowlisted: boolean;
  api_service: 'ID_VERIFICATION' | 'FACE_MATCH' | 'AGE_ESTIMATION' | 'POA' | 'AML'
             | 'PASSIVE_LIVENESS' | 'DATABASE_VALIDATION' | 'PHONE_VERIFICATION'
             | 'EMAIL_VERIFICATION' | null;  // null when the match comes from a workflow session
}

interface Warning {
  risk: string;
  feature: 'LIVENESS';           // always LIVENESS on this endpoint
  additional_data: object | null;
  log_type: 'error' | 'warning' | 'information';
  short_description: string;
  long_description: string;
}
```

필드 참고 사항:

* **`matches[]`는 유사도 하한선 이상의 항목 중 최대 5개로 제한**되며 유사도 내림차순으로 정렬됩니다(`search_type=blocklisted_or_approved`는 차단 목록 항목을 먼저 배치한 다음 허용 목록, 그 다음 유사도 순으로 순위를 매깁니다).
* **`source`**는 일치하는 얼굴이 어디에서 등록되었는지를 나타냅니다. `session`은 인증 세션 또는 저장된 독립형 API 호출, `imported`는 사용자 프로필에 직접 업로드된 얼굴, `list_entry`는 목록 중 하나에 연결된 얼굴, `retained_template`은 원본 세션을 삭제한 후 애플리케이션이 보관한 이미지가 없는 [생체 인식 템플릿](https://docs.didit.me/ko/management-api/biometric-templates/overview.md)입니다. `imported`, `list_entry`, `retained_template` 일치 항목의 경우 `session_id`, `session_number`, `status`, `api_service`는 `null`입니다.
* **`retained_template` 일치 항목**은 `vendor_user_id`, `vendor_data`, `biometric_template_id`를 전달하며, `match_image_url`, `user_details` 및 세션 관련 모든 항목은 항상 `null`입니다. 얼굴을 생성한 세션이 더 이상 존재하지 않으며 템플릿에 이미지나 신원 데이터가 포함되어 있지 않기 때문입니다. 보관된 템플릿의 경우 `is_blocklisted`는 항상 `false`이며, 차단 목록에 등록된 얼굴은 `list_entry` 일치 항목으로 별도 보고됩니다. `DELETE /v3/biometric-templates/{biometric_template_id}/`를 사용하여 템플릿을 영구 삭제할 수 있습니다.
* **`api_service`**는 일치한 세션의 독립형 API 유형(대문자, 예: `PASSIVE_LIVENESS`)이며, 일치한 얼굴이 일반 워크플로 인증 세션에서 생성된 경우에는 `null`입니다.
* **`user_details`**는 일치한 세션의 신분증 인증에서 가져옵니다. `source: imported` 일치 항목의 경우 사용자 프로필에서 채워지며(`full_name` 설정됨, `document_type`/`document_number`는 null), 신원 데이터가 없는 경우(예: 라이브니스 전용 세션)에는 `null`입니다.
* **경고는 워크플로 경고에 비해 축소된 구조를 사용**합니다. `node_id`가 없습니다. 문서화된 응답 명세(`FaceSearchResponseSerializer`)는 `risk`, `additional_data`, `log_type`, `short_description`, `long_description`의 5개 필드를 선언하며, 런타임 payload에는 추가로 `feature`가 포함되며 여기서는 항상 `"LIVENESS"`입니다. [얼굴 검색 경고](https://docs.didit.me/ko/core-technology/face-search/warnings-face-search.md)를 참고하십시오.
* **동일 사용자 일치 항목은 제외되지 않습니다.** 워크플로 중복 감지와 달리 독립형 endpoint는 동일한 `vendor_data`를 가진 이전 세션을 필터링하지 않으므로, 다시 방문한 정당한 사용자가 자신의 이전 세션과 일치하게 됩니다.

## 상태 값

최상위 레벨의 `face_search.status`는 `warnings[]`에서 파생됩니다. 일치 항목 레벨의 `status`는 **일치한 세션의** 인증 결과를 반영하며 독립적입니다.

| 값 | 표시 시점 |
| - | - |
| `Approved` | 차단 목록 경고가 발생하지 않았습니다. 중복 일치 항목이 발견된 경우도 포함됩니다. 중복은 정보 제공용 신호이며 거부 사유가 아닙니다. |
| `Declined` | `FACE_IN_BLOCKLIST` 또는 `POSSIBLE_FACE_IN_BLOCKLIST` 경고가 발생했습니다. 검색 이미지가 얼굴 차단 목록의 얼굴과 일치했습니다. |

참고: 검색 이미지에 감지 가능한 얼굴이 없는 경우, API는 `face_search` 객체가 생성되기 **전**에 `{"error": "No face detected in the image"}`와 함께 HTTP `400`을 반환합니다. 이 경우에는 `Declined` 상태가 존재하지 않습니다. 크레딧이 부족하면 이미지 처리가 시작되기 전에 HTTP `403`을 반환합니다.

## 예시

### Approved — 중복 일치, 차단 목록 없음

```json theme={null}
{
  "request_id": "5e0c3a1f-7b2d-4c8e-9f10-2a3b4c5d6e7f",
  "face_search": {
    "status": "Approved",
    "total_matches": 1,
    "matches": [
      {
        "session_id": "1f2e3d4c-5b6a-7980-1122-334455667788",
        "session_number": 1024,
        "similarity_percentage": 87.42,
        "source": "session",
        "vendor_data": "user-9",
        "verification_date": "2025-11-20T09:15:00Z",
        "user_details": {
          "full_name": "Jane Marie Doe",
          "document_type": "Passport",
          "document_number": "X1234567"
        },
        "match_image_url": "https://<media-host>/face/9c8b7a6d/reference.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": [
      {
        "risk": "DUPLICATED_FACE",
        "feature": "LIVENESS",
        "additional_data": {
          "duplicated_session_id": "1f2e3d4c-5b6a-7980-1122-334455667788",
          "duplicated_session_number": 1024,
          "api_service": null
        },
        "log_type": "information",
        "short_description": "Duplicated face from other approved session",
        "long_description": "The system identified a duplicated face from another approved session, requiring further investigation."
      }
    ]
  },
  "vendor_data": "user-123",
  "metadata": null,
  "created_at": "2026-06-12T01:04:42.763237+00:00"
}
```

### Declined — 차단 목록 일치

```json theme={null}
{
  "request_id": "a1b2c3d4-e5f6-7890-1234-567890abcdef",
  "face_search": {
    "status": "Declined",
    "total_matches": 1,
    "matches": [
      {
        "session_id": "882c42d5-8a4d-4d20-8080-a22f57822c86",
        "session_number": 323442,
        "similarity_percentage": 99.99,
        "source": "session",
        "vendor_data": "user-1",
        "verification_date": "2025-01-01T00:00:00Z",
        "user_details": {
          "full_name": "Jane Marie Doe",
          "document_type": "ID",
          "document_number": "X1234567"
        },
        "match_image_url": "https://<media-host>/face/3f6a1c2e/reference.jpg?signature=...",
        "status": "Approved",
        "is_blocklisted": true,
        "is_allowlisted": false,
        "api_service": "PASSIVE_LIVENESS"
      }
    ],
    "user_image": {
      "entities": [
        {
          "bbox": [40, 40, 120, 120],
          "confidence": 0.732973
        }
      ],
      "best_angle": 0
    },
    "warnings": [
      {
        "risk": "FACE_IN_BLOCKLIST",
        "feature": "LIVENESS",
        "additional_data": {
          "blocklisted_session_id": "882c42d5-8a4d-4d20-8080-a22f57822c86",
          "blocklisted_session_number": 323442,
          "api_service": "PASSIVE_LIVENESS"
        },
        "log_type": "error",
        "short_description": "Face in blocklist",
        "long_description": "The system identified a face in the blocklist, which means the face is not allowed to be verified."
      }
    ]
  },
  "vendor_data": "user-123",
  "metadata": null,
  "created_at": "2026-06-12T01:04:42.763237+00:00"
}
```

## 관련 문서

* [얼굴 검색 경고](https://docs.didit.me/ko/core-technology/face-search/warnings-face-search.md) — 검색에서 발생할 수 있는 모든 경고 코드
* [얼굴 검색 API 레퍼런스](https://docs.didit.me/ko/standalone-apis/face-search.md) — 요청 파라미터 및 `search_type` 모드
* [데이터 모델 — 얼굴 검색](https://docs.didit.me/ko/reference/data-models.md#얼굴-검색) — 표준 스키마
* [webhook](https://docs.didit.me/ko/integration/webhooks.md) — 저장된 세션의 `status.updated` payload

> [!NOTE]
>
> `save_api_request=true`인 경우, `match_image_url` 값은 서명된 유효 기간이 짧은 URL입니다. 새 URL을 가져오려면 반환된 `request_id`로 세션 결정 endpoint를 다시 호출하세요. `save_api_request=false`인 경우, 내부 저장소 경로이므로 직접 다운로드할 수 없습니다. 시스템에는 일치하는 세션 ID, 상태 및 `similarity_percentage`만 저장하고, 원본 생체 이미지는 보관하지 마세요.


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