Pular para o conteúdo principal

Documento, face match e prova de vida

Os três módulos base do KYC de pessoa: Documento (OCR) (cpf_ocr), Face Match (face) e Liveness (liveness). A captura inteira acontece no widget, e nenhuma foto passa pelo seu front nem chega ao seu backend. A leitura do cpf_ocr é feita por fornecedor externo, com o rosto do documento tarjado antes do envio quando o detector está disponível e encontra o rosto, e com o fornecedor declarado na lista de subprocessadores. No resumo checks do webhook, cpf_ocr e face saem combinados na chave identity ("pass" ou "fail") e o liveness sai como número de 0 a 1; o detalhe de cada módulo vem em check_details, como abaixo.

Documento (OCR): cpf_ocr

Lê RG, CNH ou CIN e extrai nome, CPF, número do documento e nascimento. O CPF passa pelo dígito verificador ainda na leitura: CPF que não fecha vem null, nunca um número inválido entregue como bom. A foto do documento não sai no webhook: mídia fica no painel, com acesso restrito por papel.
Documento vencido não reprova. A validade volta em document.valid_until e o vencimento em document.expired, com três estados: true (vencido), false (vigente) e null (não deu para afirmar). O documento vencido é aceito e fica guardado como evidência; o que fazer com ele é decisão da sua política. null nunca é false. Na CIN e no passaporte, o impresso é conferido com a zona de leitura mecânica (MRZ). Quando o nome, o nascimento ou o número impressos não batem com os da MRZ, a verificação vai para review, nunca para recusa automática, com decision_reason: "identity_document_mrz_review". O motivo do módulo é mrz_visual_mismatch, e o painel mostra qual dos campos divergiu. Nesse caso os campos lidos do documento não vêm no data: não há como saber qual das duas identidades é a verdadeira, e quem decide é a pessoa que revisa. No sandbox, com o sufixo no campo document do submit: 41 leva a verificação para review com mrz_visual_mismatch, e 45 aprova com o documento vencido (document.expired: true). A lista completa está em Sandbox.

Face Match 1:1: face

Compara a selfie com a foto do documento apresentado e responde se é a mesma pessoa. O payload separa a verdade biométrica (match e similarity, contra um limiar calibrado) do score de negócio, e entrega a qualidade de imagem dos dois lados: com quality baixo você sabe que uma recusa pode ser foto ruim, não fraude. Exige um documento no mesmo flow, cpf_ocr ou doc_global: é dele que sai a foto contra a qual a selfie é comparada. Sem ele a criação do flow é recusada com module_dependency_violation, e um flow antigo montado sem documento recebe o mesmo código na criação de sessão e de link. Para comparar com uma referência que não é documento, use face_reauth (a matrícula da conta) ou doclink (a selfie de uma verificação anterior). No widget, a pessoa escolhe como envia o documento: a foto do documento (uma foto, ou frente e verso) ou o QR code do documento, que traz a foto do titular com a assinatura digital do órgão emissor conferida. A resposta é a mesma nos dois caminhos; só o campo type diz qual foi usado: document_single_photo, document_front_back ou qr_code. O QR aparece quando o flow tem face e cpf_ocr, sem doc_forensics, doc_global nem age_assurance, e nesse caminho o cpf_ocr sai com os dados lidos do QR, no mesmo formato. A resposta é match. A similarity pode vir null: quando a comparação é feita por um motor que mede numa escala própria, o número não é comparável entre verificações e não é publicado. O mesmo vale para confidence e quality.

Prova de vida: liveness

Confirma que há uma pessoa viva na frente da câmera: barra foto impressa, tela e vídeo gravado. Num módulo só saem a prova passiva (a análise da selfie) e a ativa (o desafio de gestos, quando o flow pediu), mais dois vereditos de captura: capture (a origem dos bytes é coerente com uma câmera real?) e active.volume (o rosto tem volume 3D ou é um plano?). Detecção de mídia sintética não faz parte do payload: não há modelo de deepfake com licença que permita uso comercial de ponta a ponta, e preferimos não publicar um campo a publicar um campo que nunca tem valor. Se um dia a medição existir, o campo entra documentado aqui na mesma entrega. O veredito é passed e o score do módulo, de 0 a 100; live_probability vai de 0 a 1 e não é o mesmo número. O bloco friction diz qual prova aquele titular fez, como explicado em Webhooks.

Origem da captura

O veredito capture acima confere a origem da captura em toda prova de vida, dentro do liveness, sem módulo nem preço à parte. Os valores são coherent, suspected e indeterminate, e o campo chega null quando o flow não tem prova de vida. O desfecho da verificação já leva esse veredito em conta: siga o desfecho e use a mídia do painel quando o caso cair em revisão. indeterminate quer dizer que não houve como afirmar a origem, e não é acusação contra o titular.