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

# Pesquisa facial 1:N: Relatório e resultados em JSON

> O relatório de pesquisa facial 1:N da Didit inclui sessões correspondentes, similaridade e listas de bloqueio para investigar fraudes.

## Visão geral

A Pesquisa facial é uma pesquisa biométrica **1:N**: a Didit identifica o maior rosto detetado na sua `user_image` e pesquisa-o no índice de pesquisa facial da sua aplicação — rostos registados a partir de sessões de verificação, chamadas de API autónomas guardadas, carregamentos diretos de rostos no perfil de utilizador e as suas listas de bloqueio/permissão. Distingue-se da Correspondência facial, que é **1:1** — a Correspondência facial compara uma selfie com o retrato num documento específico, enquanto a Pesquisa facial pergunta "já vimos esta pessoa antes, em algum lado?".

Vale a pena compreender dois comportamentos antes de analisar o relatório:

* **Apenas as correspondências com a lista de bloqueio recusam.** O `face_search.status` fica como `Declined` apenas quando é acionado um aviso `FACE_IN_BLOCKLIST` ou `POSSIBLE_FACE_IN_BLOCKLIST`. As correspondências duplicadas por si só devolvem `Approved` — inspecione `matches` e `warnings`, não apenas o `status`.
* **Persistência e registo opcionais.** Quando `save_api_request=true` (o valor predefinido), a chamada é persistida como uma sessão do tipo API e o rosto pesquisado é registado no seu índice de pesquisa facial. Os rostos registados por chamadas de Pesquisa facial são **excluídos de resultados futuros de Pesquisa facial**, pelo que pesquisas repetidas nunca correspondem entre si. Passe `save_api_request=false` para uma consulta única: nada é guardado e o rosto não é registado.

## Onde aparecem os resultados

A Pesquisa facial é uma API autónoma. Os resultados da pesquisa são devolvidos **de forma síncrona, apenas na resposta a `POST /v3/face-search/`**, como um objeto singular `face_search` no nível raiz:

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

Não existe nenhum array plural `face_searches[]` em lado nenhum — a convenção de arrays plurais utilizada por `id_verifications[]`, `aml_screenings[]` e `liveness_checks[]` no endpoint de decisão da sessão não se aplica.

Quando `save_api_request=true` (o valor predefinido), a chamada também é persistida como uma sessão do tipo API:

* **Consola Empresarial** — a sessão aparece na sua lista de sessões com a imagem da pesquisa, as correspondências e os avisos.
* **`GET /v3/session/{sessionId}/decision/`** — recuperável utilizando o `request_id` devolvido como ID de sessão. Os dados persistidos surgem como uma entrada `FACE_SEARCH` em `features[]` e como um item em `liveness_checks[]` que contém os `matches` guardados (com valores `match_image_url` recentemente assinados) e `warnings` — **not** como um objeto `face_search`.

Quando `save_api_request=false`, o `request_id` é um UUID de correlação transitório: a sessão nunca é guardada, pelo que não pode ser obtida a partir da Consola ou do endpoint de decisão.

## Esquema

Consulte [Pesquisa facial na referência dos Modelos de Dados](https://docs.didit.me/pt/reference/data-models.md#pesquisa-facial) para consultar as tabelas canónicas de campos. A estrutura abaixo reflete o que o endpoint realmente devolve em tempo de execução.

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

Notas sobre os campos:

* **`matches[]` está limitado a 5** entradas acima do limiar mínimo de similaridade, ordenadas por similaridade decrescente (`search_type=blocklisted_or_approved` classifica primeiro as entradas na lista de bloqueio, depois na lista de permissões e, em seguida, por similaridade).
* **`source`** indica a origem onde o rosto correspondente foi registado: `session` — uma sessão de verificação ou uma chamada de API autónoma guardada; `imported` — um rosto carregado diretamente para um perfil de utilizador; `list_entry` — um rosto associado a uma das suas listas; `retained_template` — um [template biométrico](https://docs.didit.me/pt/management-api/biometric-templates/overview.md) sem imagem retido pela aplicação após eliminar a sessão de origem. `session_id`, `session_number`, `status` e `api_service` são `null` para correspondências de `imported`, `list_entry` e `retained_template`.
* **As correspondências de `retained_template`** contêm `vendor_user_id`, `vendor_data` e `biometric_template_id`, e são sempre `null` para `match_image_url`, `user_details` e tudo o que esteja relacionado com a sessão: a sessão que gerou o rosto já não existe e o template não contém dados de imagem ou de identidade. O campo `is_blocklisted` é sempre `false` para um template retido; um rosto na lista de bloqueio é comunicado separadamente como uma correspondência de `list_entry`. Elimine o template com `DELETE /v3/biometric-templates/{biometric_template_id}/`.
* **`api_service`** é o tipo de API autónoma da sessão correspondente (em maiúsculas, por exemplo, `PASSIVE_LIVENESS`) e `null` quando o rosto correspondente veio de uma sessão de verificação de fluxo normal.
* **`user_details`** provém da verificação de documentos da sessão correspondente. Para correspondências com `source: imported`, é preenchido a partir do perfil de utilizador (`full_name` definido, `document_type`/`document_number` nulos); é `null` quando não existem dados de identidade (por exemplo, sessões apenas de prova de vida).
* **Os avisos utilizam uma estrutura reduzida** em comparação com os avisos de fluxo: não existe `node_id`. O contrato de resposta documentado (`FaceSearchResponseSerializer`) declara os cinco campos `risk`, `additional_data`, `log_type`, `short_description` e `long_description`; o payload em tempo de execução inclui adicionalmente `feature`, que aqui é sempre `"LIVENESS"`. Consulte [Avisos de Pesquisa facial](https://docs.didit.me/pt/core-technology/face-search/warnings-face-search.md).
* **Correspondências do mesmo utilizador não são excluídas** — ao contrário da deteção de duplicados em fluxos, o endpoint autónomo não filtra sessões anteriores com os mesmos `vendor_data`, pelo que um utilizador legítimo que regresse corresponde às suas próprias sessões anteriores.

## Valores de estado

O `face_search.status` de nível raiz é derivado de `warnings[]`. O `status` ao nível da correspondência reflete o resultado da verificação da **sessão correspondente** e é independente.

| Valor | Quando aparece |
| - | - |
| `Approved` | Nenhum aviso de lista de bloqueio foi acionado. Inclui o caso em que foram encontradas correspondências duplicadas — os duplicados são sinais informativos, não recusas. |
| `Declined` | Foi acionado um aviso `FACE_IN_BLOCKLIST` ou `POSSIBLE_FACE_IN_BLOCKLIST` — a imagem pesquisada correspondeu a um rosto na sua lista de bloqueio de rostos. |

Nota: quando a imagem da pesquisa não contém nenhum rosto detetável, a API devolve HTTP `400` com `{"error": "No face detected in the image"}` **antes** da criação de um objeto `face_search` — não existe um estado `Declined` para esse caso. Créditos insuficientes devolvem HTTP `403` antes de qualquer processamento de imagem.

## Exemplos

### Approved — correspondência duplicada, sem lista de bloqueio

```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 — correspondência na lista de bloqueio

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

## Relacionado

* [Avisos de Pesquisa facial](https://docs.didit.me/pt/core-technology/face-search/warnings-face-search.md) — todos os códigos de aviso que a pesquisa pode emitir
* [Referência da API de Pesquisa facial](https://docs.didit.me/pt/standalone-apis/face-search.md) — parâmetros do pedido e modos de `search_type`
* [Modelos de dados — Pesquisa facial](https://docs.didit.me/pt/reference/data-models.md#pesquisa-facial) — esquema canónico
* [Webhooks](https://docs.didit.me/pt/integration/webhooks.md) — payloads de `status.updated` para sessões persistidas

> [!NOTE]
>
> Quando `save_api_request=true`, os valores de `match_image_url` são URLs assinados e de curta duração — chame novamente o endpoint de decisão da sessão com o `request_id` devolvido para obter novos URLs. Quando `save_api_request=false`, são caminhos de armazenamento interno e não podem ser descarregados diretamente. Armazene apenas o ID da sessão correspondente, o estado e `similarity_percentage` do seu lado — não conserve a imagem biométrica subjacente.


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