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

# Laporan Pencarian Wajah 1:N: Hasil Pencocokan JSON

> Laporan Pencarian Wajah 1:N Didit memuat ID sesi yang cocok, persentase kemiripan, penanda daftar blokir, dan detail pengguna untuk investigasi.

## Overview

Face Search adalah pencarian biometrik **1:N**: Didit mengambil wajah terbesar yang terdeteksi di `user_image` Anda dan mencarinya di indeks Face Search aplikasi Anda — wajah yang didaftarkan dari sesi verifikasi, panggilan API mandiri yang disimpan, unggahan wajah langsung ke profil pengguna, serta daftar blokir/izinkan Anda. Ini berbeda dari Face Match, yang bersifat **1:1** — Face Match membandingkan swafoto dengan potret pada dokumen tertentu, sementara Face Search menanyakan "apakah kita pernah melihat orang ini di suatu tempat sebelumnya?".

Dua perilaku penting untuk dipahami sebelum Anda menguraikan laporan:

* **Hanya kecocokan daftar blokir yang ditolak.** `face_search.status` bernilai `Declined` hanya ketika peringatan `FACE_IN_BLOCKLIST` atau `POSSIBLE_FACE_IN_BLOCKLIST` dipicu. Kecocokan duplikat saja mengembalikan `Approved` — periksa `matches` dan `warnings`, bukan hanya `status`.
* **Persistensi dan pendaftaran opsional.** Saat `save_api_request=true` (default), panggilan tersebut disimpan sebagai sesi bertipe API dan wajah yang dicari didaftarkan ke dalam indeks Face Search Anda. Wajah yang didaftarkan oleh panggilan Face Search **dikecualikan dari hasil Face Search mendatang**, sehingga pencarian berulang tidak akan pernah cocok satu sama lain. Teruskan `save_api_request=false` untuk kueri satu kali: tidak ada yang disimpan dan wajah tidak didaftarkan.

## Tempat hasil ditampilkan

Face Search adalah API mandiri. Hasil pencarian dikembalikan **secara sinkron, hanya dalam respons `POST /v3/face-search/`**, sebagai objek tunggal `face_search` di tingkat atas:

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

Tidak ada array `face_searches[]` di mana pun — konvensi array jamak yang digunakan oleh `id_verifications[]`, `aml_screenings[]`, dan `liveness_checks[]` pada endpoint keputusan sesi tidak berlaku di sini.

Saat `save_api_request=true` (default), panggilan tersebut juga disimpan sebagai sesi bertipe API:

* **Konsol Bisnis** — sesi tersebut muncul di daftar sesi Anda beserta gambar pencarian, kecocokan, dan peringatan.
* **`GET /v3/session/{sessionId}/decision/`** — dapat diambil menggunakan `request_id` yang dikembalikan sebagai ID sesi. Data yang disimpan muncul sebagai entri `FACE_SEARCH` di `features[]` dan sebagai item `liveness_checks[]` yang memuat `matches` yang tersimpan (dengan nilai `match_image_url` yang baru ditandatangani) serta `warnings` — **bukan** sebagai objek `face_search`.

Saat `save_api_request=false`, `request_id` adalah UUID korelasi sementara: sesi tidak pernah disimpan, sehingga tidak dapat diambil dari Konsol atau endpoint keputusan.

## Skema

Lihat [Face Search di referensi Model Data](https://docs.didit.me/id/reference/data-models.md#pencarian-wajah) untuk tabel kolom kanonis. Bentuk di bawah ini mencerminkan apa yang sebenarnya dikembalikan oleh endpoint saat runtime.

```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;
}
```

Catatan kolom:

* **`matches[]` dibatasi maksimal 5** entri di atas ambang kemiripan, diurutkan berdasarkan kemiripan secara menurun (`search_type=blocklisted_or_approved` memberi peringkat entri daftar blokir terlebih dahulu, kemudian daftar izin, lalu kesamaan).
* **`source`** memberi tahu Anda dari mana wajah yang cocok didaftarkan: `session` — sesi verifikasi atau panggilan API mandiri yang disimpan; `imported` — wajah yang diunggah langsung ke profil pengguna; `list_entry` — wajah yang dilampirkan ke salah satu daftar Anda; `retained_template` — [templat biometrik](https://docs.didit.me/id/management-api/biometric-templates/overview.md) tanpa gambar yang disimpan aplikasi setelah menghapus sesi sumber. `session_id`, `session_number`, `status`, dan `api_service` bernilai `null` untuk kecocokan `imported`, `list_entry`, dan `retained_template`.
* **Kecocokan `retained_template`** membawa `vendor_user_id`, `vendor_data`, dan `biometric_template_id`, serta selalu `null` untuk `match_image_url`, `user_details`, dan semua hal yang terkait dengan sesi: sesi yang menghasilkan wajah tersebut sudah tidak ada lagi dan templat tersebut tidak menyimpan data gambar atau identitas. `is_blocklisted` selalu `false` untuk templat yang disimpan; wajah yang masuk daftar blokir dilaporkan secara terpisah sebagai kecocokan `list_entry`. Hapus templat dengan `DELETE /v3/biometric-templates/{biometric_template_id}/`.
* **`api_service`** adalah tipe API mandiri dari sesi yang cocok (huruf besar, misalnya `PASSIVE_LIVENESS`) dan `null` jika wajah yang cocok berasal dari sesi verifikasi alur kerja reguler.
* **`user_details`** berasal dari verifikasi dokumen sesi yang cocok. Untuk kecocokan `source: imported`, nilai ini diisi dari profil pengguna (`full_name` diisi, `document_type`/`document_number` null); nilai ini `null` saat tidak ada data identitas (misalnya sesi khusus liveness).
* **Peringatan menggunakan bentuk yang lebih sederhana** dibandingkan dengan peringatan alur kerja: tidak ada `node_id`. Kontrak respons yang terdokumentasi (`FaceSearchResponseSerializer`) mendeklarasikan lima kolom `risk`, `additional_data`, `log_type`, `short_description`, `long_description`; payload runtime juga membawa `feature`, yang di sini selalu bernilai `"LIVENESS"`. Lihat [Peringatan Face Search](https://docs.didit.me/id/core-technology/face-search/warnings-face-search.md).
* **Kecocokan pengguna yang sama tidak dikecualikan** — tidak seperti deteksi duplikat alur kerja, endpoint mandiri tidak memfilter sesi sebelumnya dengan `vendor_data` yang sama, sehingga pengguna sah yang kembali akan cocok dengan sesi mereka sebelumnya.

## Nilai status

`face_search.status` tingkat atas diturunkan dari `warnings[]`. `status` tingkat kecocokan mencerminkan hasil verifikasi **sesi yang cocok** dan bersifat independen.

| Nilai | Kapan nilai ini muncul |
| - | - |
| `Approved` | Tidak ada peringatan daftar blokir yang dipicu. Termasuk kasus saat kecocokan duplikat ditemukan — duplikat adalah sinyal informasi, bukan penolakan. |
| `Declined` | Peringatan `FACE_IN_BLOCKLIST` atau `POSSIBLE_FACE_IN_BLOCKLIST` dipicu — gambar pencarian cocok dengan wajah di daftar blokir wajah Anda. |

Catatan: jika gambar pencarian tidak berisi wajah yang dapat dideteksi, API mengembalikan HTTP `400` dengan `{"error": "No face detected in the image"}` **sebelum** objek `face_search` dibuat — tidak ada status `Declined` untuk kasus tersebut. Kredit yang tidak mencukupi mengembalikan HTTP `403` sebelum pemrosesan gambar apa pun.

## Contoh

### Disetujui — kecocokan duplikat, tidak ada daftar blokir

```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"
}
```

### Ditolak — kecocokan daftar blokir

```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"
}
```

## Terkait

* [Peringatan Pencarian Wajah](https://docs.didit.me/id/core-technology/face-search/warnings-face-search.md) — setiap kode peringatan yang dapat dimunculkan oleh pencarian
* [Referensi API Pencarian Wajah](https://docs.didit.me/id/standalone-apis/face-search.md) — parameter permintaan dan mode `search_type`
* [Model data — Pencarian Wajah](https://docs.didit.me/id/reference/data-models.md#pencarian-wajah) — skema kanonis
* [Webhook](https://docs.didit.me/id/integration/webhooks.md) — payload `status.updated` untuk sesi yang disimpan

> [!NOTE]
>
> Ketika `save_api_request=true`, nilai `match_image_url` adalah URL berumur pendek yang ditandatangani — panggil kembali endpoint keputusan sesi dengan `request_id` yang dikembalikan untuk mendapatkan URL baru. Ketika `save_api_request=false`, nilai tersebut merupakan jalur penyimpanan internal dan tidak dapat diunduh secara langsung. Simpan hanya id sesi yang cocok, status, dan `similarity_percentage` di sisi Anda — jangan menyimpan gambar biometrik yang mendasarinya.


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