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

# Relatório de busca facial 1:N: JSON de correspondências

> Relatório de busca facial 1:N da Didit: sessões correspondentes, percentuais de similaridade, sinalizações de lista de bloqueio e dados do usuário.

## Visão geral

A Busca facial é uma busca biométrica **1:N**: a Didit pega o maior rosto detectado na sua `user_image` e o procura no índice de busca facial da sua aplicação, que reúne rostos cadastrados a partir de sessões de verificação, chamadas de API avulsas salvas, envios diretos de rosto para perfis de usuário e suas listas de bloqueio e de permissão. Ela é diferente da Correspondência facial, que é **1:1**: a Correspondência facial compara uma selfie com o retrato de um documento específico, enquanto a Busca facial pergunta "já vimos esta pessoa em algum lugar antes?".

Vale entender dois comportamentos antes de interpretar o relatório:

* **Somente correspondências na lista de bloqueio geram recusa.** `face_search.status` é `Declined` somente quando um aviso `FACE_IN_BLOCKLIST` ou `POSSIBLE_FACE_IN_BLOCKLIST` é disparado. Correspondências duplicadas, por si sós, retornam `Approved`. Analise `matches` e `warnings`, e não apenas `status`.
* **Persistência e cadastro opcionais.** Quando `save_api_request=true` (o padrão), a chamada é persistida como uma sessão do tipo API e o rosto buscado é cadastrado no seu índice de busca facial. Rostos cadastrados por chamadas de Busca facial são **excluídos dos resultados futuros da Busca facial**, então buscas repetidas nunca correspondem entre si. Envie `save_api_request=false` para uma consulta pontual: nada é armazenado e o rosto não é cadastrado.

## Onde os resultados aparecem

A Busca facial é uma API avulsa. Os resultados da busca são retornados **de forma síncrona, somente na resposta de `POST /v3/face-search/`**, como um objeto `face_search` no singular, no nível superior:

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

Não existe um array no plural `face_searches[]` em lugar nenhum: a convenção de arrays no plural usada por `id_verifications[]`, `aml_screenings[]` e `liveness_checks[]` no endpoint de decisão da sessão não se aplica aqui.

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

* **Business Console**: a sessão aparece na sua lista de sessões com a imagem usada na busca, as correspondências e os avisos.
* **`GET /v3/session/{sessionId}/decision/`**: a sessão pode ser consultada usando o `request_id` retornado como ID da sessão. Os dados persistidos aparecem como uma entrada `FACE_SEARCH` em `features[]` e como um item de `liveness_checks[]` contendo as `matches` armazenadas (com valores de `match_image_url` assinados novamente) e os `warnings`, **e não** como um objeto `face_search`.

Quando `save_api_request=false`, `request_id` é um UUID de correlação transitório: a sessão nunca é armazenada, então não pode ser consultada no Console nem no endpoint de decisão.

## Esquema

Consulte [Busca facial na referência de modelos de dados](https://docs.didit.me/pt-br/reference/data-models.md#busca-facial) para ver as tabelas de campos oficiais. A estrutura abaixo reflete o que o endpoint de fato retorna 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;
}
```

Observações sobre os campos:

* **`matches[]` é limitado a 5** entradas acima do limiar mínimo de similaridade, ordenadas por similaridade decrescente (`search_type=blocklisted_or_approved` classifica primeiro as entradas da lista de bloqueio, depois as da lista de permissões e, em seguida, por similaridade).
* **`source`** indica de onde o rosto correspondente foi cadastrado: `session`, uma sessão de verificação ou uma chamada de API avulsa salva; `imported`, um rosto enviado diretamente para um perfil de usuário; `list_entry`, um rosto vinculado a uma das suas listas; `retained_template`, um [template biométrico](https://docs.didit.me/pt-br/management-api/biometric-templates/overview.md) sem imagem que a aplicação manteve após excluir a sessão de origem. `session_id`, `session_number`, `status` e `api_service` são `null` em correspondências `imported`, `list_entry` e `retained_template`.
* **Correspondências `retained_template`** contêm `vendor_user_id`, `vendor_data` e `biometric_template_id`, e trazem sempre `null` em `match_image_url`, `user_details` e em tudo o que se refere à sessão: a sessão que gerou o rosto não existe mais e o template não guarda nenhuma imagem nem dado de identidade. `is_blocklisted` é sempre `false` para um template retido; um rosto da lista de bloqueio é informado separadamente como uma correspondência `list_entry`. Exclua o template com `DELETE /v3/biometric-templates/{biometric_template_id}/`.
* **`api_service`** é o tipo de API avulsa 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 comum de um fluxo de verificação (workflow).
* **`user_details`** vem da verificação de documento da sessão correspondente. Em correspondências `source: imported`, ele é preenchido a partir do perfil do usuário (`full_name` preenchido, `document_type`/`document_number` nulos); é `null` quando não há dados de identidade (por exemplo, em sessões apenas de prova de vida).
* **Os avisos usam uma estrutura reduzida** em comparação com os avisos de fluxo: não há `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 também traz `feature`, que aqui é sempre `"LIVENESS"`. Consulte [Avisos da Busca facial](https://docs.didit.me/pt-br/core-technology/face-search/warnings-face-search.md).
* **Correspondências com o mesmo usuário não são excluídas**: diferentemente da detecção de duplicados nos fluxos, o endpoint avulso não filtra sessões anteriores com o mesmo `vendor_data`, portanto, um usuário legítimo que retorna tem correspondência com as próprias sessões anteriores.

## Valores de status

O `face_search.status` de nível superior é derivado de `warnings[]`. O `status` de cada 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 disparado. Inclui o caso em que foram encontradas correspondências duplicadas: duplicados são sinais informativos, não recusas. |
| `Declined` | Um aviso `FACE_IN_BLOCKLIST` ou `POSSIBLE_FACE_IN_BLOCKLIST` foi disparado: a imagem buscada correspondeu a um rosto da sua lista de bloqueio facial. |

Observação: quando a imagem buscada não contém nenhum rosto detectável, a API retorna HTTP `400` com `{"error": "No face detected in the image"}` **antes** de um objeto `face_search` ser criado; não existe status `Declined` para esse caso. Créditos insuficientes retornam HTTP `403` antes de qualquer processamento da imagem.

## Exemplos

### Aprovado: 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"
}
```

### Recusado: 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"
}
```

## Relacionados

* [Avisos da Busca facial](https://docs.didit.me/pt-br/core-technology/face-search/warnings-face-search.md): todos os códigos de aviso que a busca pode emitir
* [Referência da API de Busca facial](https://docs.didit.me/pt-br/standalone-apis/face-search.md): parâmetros da requisição e modos de `search_type`
* [Modelos de dados: Busca facial](https://docs.didit.me/pt-br/reference/data-models.md#busca-facial): schema canônico
* [Webhooks](https://docs.didit.me/pt-br/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 assinadas e de curta duração. Consulte novamente o endpoint de decisão da sessão com o `request_id` retornado para obter URLs novas. Quando `save_api_request=false`, eles são caminhos internos de armazenamento e não podem ser baixados diretamente. Armazene do seu lado apenas o ID da sessão correspondente, o status e o `similarity_percentage`. Não retenha a imagem biométrica subjacente.


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