Primeira verificação
Hora de executar uma verificação real com o widget que você incorporou no passo anterior.
O que você está prestes a testar
Um fluxo completo de usuário:
- O usuário clica em Start
- O navegador pede permissão de câmera
- O usuário fotografa a frente do documento (câmera ou galeria)
- O usuário fotografa o verso — a menos que você tenha definido
require-doc-back="false"ou que o tipo de documento sejapassport - O usuário tira uma selfie (somente câmera)
- O widget roda checagens de qualidade, envia cada imagem para a API da Veridia e então chama o submit
- Você recebe um evento
veridia:completecarregando overificationId - O veredito (
approved/review/rejected) é calculado no servidor instantes depois
Execute
Abra a página onde você incorporou o widget. Use um dispositivo real com câmera — o widget é mobile-first, mas também funciona em notebooks.
Nada a configurar. As chaves são criadas com uma lista de allowed origins vazia, e uma lista vazia permite todas as origens — localhost incluído. Se o widget se recusar a iniciar, a causa é outra; verifique e.detail.code no evento veridia:error.
Dicas para a captura do documento
- Apoie o documento plano sobre uma superfície de cor contrastante (evite branco sobre branco)
- Não cubra nenhum canto com os dedos
- Evite luz direta refletindo no documento — isso levanta a flag
heavy_glare - Garanta que o documento esteja inteiramente no enquadramento
- Segure o celular firme; frames tremidos são rejeitados pela checagem de qualidade antes do upload
Dicas para a selfie
- Fique de frente para a câmera
- Boa iluminação e uniforme (sem contraluz)
- Tire óculos escuros e bonés que cubram o rosto
- Fique parado durante a captura
Inspecione o payload do evento
Adicione listeners para ver exatamente o que o widget emite. Estes dois são os únicos eventos que o widget dispara:
<script>
const w = document.querySelector('veridia-widget');
w.addEventListener('veridia:complete', (e) => {
console.log('verification complete:', e.detail);
});
w.addEventListener('veridia:error', (e) => {
console.error('verification error:', e.detail);
});
</script>
Quando o usuário termina, seu console mostra exatamente dois campos:
{
"verificationId": "vf_AG07CDWRRFQV4T05ZXG2",
"status": "queued"
}
É isso. Não há userRef neste evento, e nenhum veredito.
- Sem
userRef: o widget não o copia para o evento, eGET /v1/verify/{id}também não o retorna. Só o webhook o devolve. PersistaverificationId → seu id de usuárioa partir deste handler, ou você terá um veredito que não consegue atribuir a ninguém. - Sem veredito:
status: "queued"descreve o pipeline, não a pessoa. Busque o veredito a partir do seu servidor (passo 3) ou receba-o por webhook.
Veja no seu painel
Vá ao seu painel da Veridia e abra a Review queue. Você verá sua verificação com:
- Informações de quem enviou (user ref, timestamp de envio)
- As seis pontuações: confiança do OCR, correspondência facial, prova de vida (liveness), qualidade do documento, validade da MRZ e correspondência de nome
- Flags, cada uma com um nível e um texto (ex.:
heavy_glare,possible_screen_capture) - A confiança geral e o veredito final
Clique em uma verificação para ver o detalhamento completo e as imagens capturadas.
O que acontece nos bastidores
| Passo | Onde | O quê |
|---|---|---|
| 1 | Navegador | Checagens de qualidade (Laplacian, Tenengrad, Brenner) antes de qualquer envio |
| 2 | Navegador | Um PUT por imagem para /v1/verify/upload/{verificationId}/{role} na API da Veridia |
| 3 | Worker | Valida o token de upload, confere se os bytes são JPEG de verdade, armazena |
| 4 | Worker | OCR via Workers AI — extrai nome, número do documento, datas |
| 5 | Worker | Encaminha ao backend com os dados extraídos |
| 6 | Backend | Correspondência facial (insightface buffalo_s) |
| 7 | Backend | Pontuação de prova de vida (liveness) |
| 8 | Backend | Checksums da MRZ e consistência entre MRZ e zona visual |
| 9 | Backend | Triagem AML / sanções |
| 10 | Backend | Pontuação de confiança ponderada e, então, o veredito |
| 11 | Backend | Persiste no MySQL com trilha de auditoria |
| 12 | Backend | Enfileira o webhook, se houver um configurado |
Você pode encontrar material antigo descrevendo uploads pré-assinados direto para o Cloudflare R2. Não é isso que acontece. Toda imagem é enviada via PUT para a própria API da Veridia, autenticada por um X-Veridia-Upload-Token de vida curta que /v1/verify/init retorna dentro dos headers de cada slot de upload. A API valida e armazena os bytes.
Isso importa em dois lugares. Se você está apertando uma Content Security Policy, o host que precisa liberar é api.xxuxe.online, não um domínio do R2 — colocar o R2 na allowlist vai bloquear seus uploads. E se algum dia você escrever um cliente à mão em vez de usar o widget, precisa encaminhar os headers do slot literalmente; sua chave de API não autentica esse endpoint, e montar a requisição por conta própria sem o token de upload retorna 400 em toda imagem.
O que o veredito significa
| Veredito | Aproximadamente quando | O que você deve fazer |
|---|---|---|
approved | Confiança ≥ 90 e nenhuma falha grave | Confie no usuário, conclua o onboarding |
review | Confiança entre 60 e 90, ou qualquer falha grave, ou um acerto em sanções | Envie para sua fila de revisão manual |
rejected | Confiança abaixo de 60 | Bloqueie, peça ao usuário que tente de novo ou escale |
Duas regras que vale internalizar, porque não são visíveis apenas pelo número de confiança:
- Uma falha grave nunca aprova automaticamente. Nenhum rosto no documento, nenhum rosto na selfie, um checksum de MRZ inválido, um spoof detectado — qualquer um desses força no mínimo
review, não importa o que a pontuação diga. - Uma correspondência em listas de sanções força
review, nunca uma rejeição automática. Espera-se que uma pessoa tome essa decisão.
Esses limiares são configurações de todo o deployment, não ajustes por tenant. Não reimplemente a faixa do seu lado a partir de confidence; leia verdict e aja com base nele.
Códigos de erro que o widget emite
Estes são os valores reais de e.detail.code em veridia:error. A lista inteira:
| Código | Significado | Resposta típica |
|---|---|---|
camera_denied | O usuário negou a permissão de câmera | Explique por que você precisa dela e ofereça uma nova tentativa |
camera_unavailable | Não há câmera, ou a página não está em HTTPS/localhost | Diga ao usuário para trocar de dispositivo ou navegador |
user_cancelled | O usuário apertou Cancelar e saiu do fluxo | Não é um erro. Registre — este é seu sinal de abandono no funil |
invalid_api_key | Chave ausente, digitada errado, revogada ou de ambiente errado | Corrija sua configuração. Não deve aparecer para o usuário |
insufficient_credits | Seu tenant está sem créditos | Recarregue. Crie um alerta para você mesmo — todo usuário fica bloqueado até você fazer isso |
rate_limited | Limite de taxa atingido | Recue e tente de novo |
api_unreachable | Falha de rede ou 5xx da API | Transitório. O widget já fez o reintento |
upload_failed | Um upload de imagem falhou após três reintentos com backoff | Mostre ao usuário; normalmente é uma conexão móvel ruim |
no_face_in_selfie | Nenhum rosto detectado na selfie | Reservado. Normalmente tratado inline como um pedido de nova foto |
blurry_image | Imagem muito tremida | Reservado. Normalmente tratado inline como um pedido de nova foto |
internal_error | Qualquer coisa inesperada, incluindo erros de API não mapeados | Registre o e.detail inteiro e investigue |
Duas coisas nessa tabela são fáceis de entender errado:
camera_denied e user_cancelled são os que você mais vai ver de fato. Juntos, eles respondem pela maior parte dos fluxos abandonados em tráfego real. Nenhum dos dois é um bug, e ambos pedem uma resposta de produto em vez de uma tela de erro.
Borrão e "nenhum rosto" geralmente não são eventos. O widget trata isso inline: pede ao usuário para refazer a foto e, após duas falhas consecutivas na mesma tomada, deixa a foto passar mesmo assim em vez de prender o usuário em um loop. Então não construa sua telemetria de qualidade de imagem em cima desses códigos — ela vai ficar vazia. upload_failed, por outro lado, chega ao seu handler quando os reintentos se esgotam, então configure um alerta para ele.
Próximo passo
Você tem um resultado de verificação. Agora aprenda como ler o veredito.