Documento, face match e prova de vida
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.
// cpf_ocr no check_details: o que foi LIDO do documento
{ "module": "cpf_ocr", "passed": true, "outcome": "approved", "score": 95,
"data": { "name": "João Silva", "cpf": "123.456.789-00",
"birth_date": "01/03/1990", "birth_date_iso": "1990-03-01",
"document": { "type": "cnh", "number": "07969013668",
"valid_until": "15/03/2029", "expired": false } } }
// "affiliation" (filiação) entra quando o documento traz o campo.
// "expired": true (vencido) | false (vigente) | null (não deu para afirmar).
// Com um módulo de Validação CPF no mesmo flow, name/birth_date preferem a fonte OFICIAL
// (o OCR vira fallback): o dado que chega é o mais confiável disponível.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.
// face no check_details: verdade biométrica + qualidade das imagens
{ "module": "face", "passed": true, "outcome": "approved", "score": 93,
"data": { "match": true, // é a mesma pessoa? (limiar biométrico, não o score de negócio)
"similarity": 0.82, // similaridade 0..1 entre selfie e foto do documento
"confidence": 0.97,
"threshold": 0.36, // o limiar que valeu NESTA decisão (carimbado com a política)
"quality": { "selfie": 84, "document": 71 } } } // qualidade de imagem (FIQA) 0..100Prova 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. Repare na unidade do threshold: ele é o corte do score do módulo, de 0 a 100, e não um corte de live_probability (que é de 0 a 1). Comparar os dois inverte o sinal, e é o erro de integração mais fácil de cometer aqui. O bloco friction diz qual prova aquele titular fez, como explicado em Webhooks.
// liveness no check_details: prova passiva + desafio ativo num módulo só
{ "module": "liveness", "passed": true, "outcome": "approved", "score": 96,
"data": { "live_probability": 0.97, // 0..1, alto = pessoa viva
"spoof_probability": 0.03, // 0..1, alto = artefato apresentado no lugar da pessoa
"threshold": 80, // ATENÇÃO à unidade: é o corte do SCORE do módulo (0..100),
// NÃO um corte de live_probability. Nunca compare os dois.
"frames_used": 3, "face_quality": 0.88,
"capture": "coerente", // origem dos bytes: coerente | suspeita | indeterminado
"friction": { "mode": "adaptive", "level": 3, "actions_required": 2 },
"active": { "challenge": ["turn_left", "look_up"], "challenge_passed": true,
"steps_passed": 2, "steps_total": 2,
"volume": "confirmado" } } }
// active = null quando o flow não pediu desafio (ou o nível adaptativo dispensou);
// volume: confirmado | plano | indeterminado (a prova de volume 3D por paralaxe)Detecção de injeção de câmera
O veredito capture acima é uma capacidade com nome: detecção de injeção de câmera, dentro do liveness, sem módulo nem preço à parte. Dois caminhos independentes vigiam a origem do stream: o que o navegador declara na captura (automação declarada, câmera virtual, cadência implausível de frames) e o que o pixel denuncia (ausência de ruído de sensor, congelamento alinhado a bloco de codec, típico de vídeo injetado). A régua é deliberada: nenhum indício reprova sozinho. A recusa automática exige o único sinal forte, a automação declarada pelo próprio navegador, somado a ao menos mais um indício; os demais são sinais fracos, somados com teto, que seguram a verificação em revisão, nunca em recusa, porque câmera virtual e codec têm causas inocentes conhecidas. Não vendemos selo de laboratório sobre isso: a promessa é o veredito nomeado em cada verificação com prova de vida, que você audita no próprio payload.
Pronto para integrar? A chave de sandbox sai no painel, logo depois do cadastro. Criar conta grátis