Pular para o conteúdo

Finger Contactless: onboarding e autenticação

O fluxo de finger permite validar a identidade de uma pessoa e cadastrar sua biometria no onboarding, para depois realizar a autenticação com uma nova captura de impressão digital.

EtapaRequisiçãoFinalidade
Gerar o token da aplicaçãoPOST /api/v1/app-credentials/tokenTrocar a key e o secret pelo token de acesso.
OnboardingPOST /api/v1/services/biometric/onboardingValidar a identidade pelo CPF e cadastrar a biometria, conforme a configuração do contrato da aplicação.
AutenticaçãoPOST /api/v1/services/biometric/authenticateComparar uma nova captura com o cadastro do CPF (1:1) ou identificar na galeria biométrica (1:N).

Teste local

Este roteiro reproduz as chamadas HTTP do app de exemplo: gerar o token, fazer o onboarding e autenticar com uma nova captura. O Postman roda no seu computador e chama o ambiente da API escolhido; ele não captura digitais nem executa o SDK de captura.

Preparação

Você precisa das credenciais de uma aplicação da API Online, de um contrato biométrico ativo vinculado a ela e das imagens de digitais de uma pessoa cujo CPF possa ser validado no provedor configurado. Para completar onboarding seguido de autenticação, o contrato também precisa habilitar o armazenamento e configurar o provedor de comparação.

Use a mesma aplicação, o mesmo ambiente e o mesmo contrato durante o teste. Um cadastro feito em outro ambiente ou aplicação não fica automaticamente disponível na comparação 1:1. As credenciais dos provedores são configuradas no contrato pela equipe responsável pelo ambiente.

Baixe e importe a coleção Postman — Finger. Ela contém geração de token, onboarding, autenticação 1:1 e identificação 1:N. Abra as variáveis da coleção e preencha os valores usados localmente:

VariávelValor
base_urlURL fornecida para seu ambiente, sem barra final e sem /api/v1. O app de exemplo está configurado para https://api-staging.techtrue.com.br. Use esse endereço somente com credenciais e contrato habilitados nesse ambiente.
key / secretCredenciais da aplicação nesse ambiente.
tokenPreenchido automaticamente pela requisição de geração de token.
cpfCPF da pessoa capturada, com 11 dígitos.
onboarding_collection_id / authentication_collection_id / identification_collection_idPreencha com um identificador único por coleta (por exemplo, um UUID). Mantenha-o para reenvios da mesma coleta e substitua-o antes de uma nova coleta ou comparação.

Os dados pessoais, as imagens e as credenciais devem ser preenchidos somente na sua cópia local da coleção e do ambiente. Os arquivos para download não contêm esses dados.

Em cada requisição biométrica, abra Body → raw → JSON. O array fingers já está no corpo, com a estrutura abaixo para um indicador esquerdo. O campo image referencia a variável de ambiente da respectiva captura; ajuste position conforme o dedo capturado. O campo nfiq2 começa em 55, como valor de exemplo; substitua-o pela qualidade real retornada pelo SDK quando disponível. Acrescente objetos ao array para enviar mais dedos. Este fragmento mostra apenas fingers; mantenha os demais campos que já estão no body:

{
"fingers": [
{
"position": 7,
"nfiq2": 55,
"image": "{{finger_image_onboarding}}"
}
]
}

Preencha as variáveis de ambiente com o Base64 real, sem aspas adicionais nem prefixo data:image/png;base64,, e mantenha as referências {{finger_image_onboarding}} e {{finger_image_authentication}} no body. Se usar mais dedos, acrescente um objeto por dedo e crie uma variável de imagem para cada dedo, preservando a posição e a qualidade correspondentes. Não use o nome de um arquivo nem uma foto da mão inteira no campo image.

Executar o fluxo

  1. Envie 01 — Gerar token. O script salva o campo token da resposta na coleção. As outras chamadas usam esse valor em Authorization → Bearer Token.
  2. Envie 02 — Onboarding com o CPF e a primeira captura. Confira status: "APPROVED" e templateStatus: "STORED" ou "ALREADY_EXISTS" antes de seguir. Se já existir cadastro, a nova captura não substitui automaticamente as digitais cadastradas.
  3. Faça uma nova captura dos dedos cadastrados, atualize finger_image_authentication no ambiente selecionado e envie 03 — Autenticação 1:1. A coleção envia o mesmo CPF com mode: "ONE_TO_ONE". Confira resultCode, status e decision.
  4. Opcionalmente, envie 04 — Identificação 1:N, que usa a imagem de finger_image_authentication do ambiente selecionado. Essa chamada usa mode: "ONE_TO_N" e omite o CPF, buscando na galeria configurada para o provedor de comparação.

Execute as etapas manualmente, conferindo cada resposta. Os testes da coleção verificam o formato do retorno e exibem status, resultCode e decision; passar nesses testes não significa aprovação biométrica.

Para repetir exatamente uma requisição, mantenha os dados e seu identificador. Para testar uma nova captura, outro CPF ou outra comparação, atualize os dados e substitua o identificador correspondente por um novo valor. O identificador é preenchido manualmente nas variáveis da coleção, permitindo testar também a duplicidade.

Se montar as chamadas manualmente, use Body → raw → JSON e os corpos das seções seguintes. Todos os valores entre {{ e }} devem estar definidos no Postman; ao executar cURL no terminal, substitua-os pelos valores reais.

Autenticação das rotas

As duas rotas da API Online exigem o token da aplicação gerado com a key e o secret, conforme explicado em Autenticação — Gerar um token.

Terminal window
curl --request POST '{{base_url}}/api/v1/app-credentials/token' \
--header 'Content-Type: application/json' \
--data '{"key": "{{key}}", "secret": "{{secret}}"}'

Resposta esperada:

{
"token": "{{token}}"
}

Use o valor de token no cabeçalho de todas as chamadas de onboarding e autenticação:

Authorization: Bearer {{token}}
Content-Type: application/json

Use o token da aplicação Online desse ambiente; o token de login do dashboard e o token de uma aplicação on-premise não são intercambiáveis com ele. No app de exemplo, o token é informado nas configurações; o fluxo de captura não gera esse token automaticamente.

A rota /biometric/authenticate realiza a comparação biométrica; ela não gera o token de acesso. A key e o secret são enviados à rota de geração do token, e não no corpo das requisições biométricas.

A aplicação identificada pelo token precisa ter um contrato biométrico ativo configurado. O contrato define os provedores, o armazenamento e o limiar de comparação. Não envie contractId: a API resolve esse vínculo pela credencial autenticada e rejeita o envio de um valor para esse campo.

Dados da captura

O app configura o SDK AirSnap para retornar uma imagem PNG por dedo segmentado. Ele usa os bytes de primaryImage (com fallback para displayImage quando necessário), converte para Base64 sem quebras de linha e envia cada dedo em fingers. A captura padrão é dos quatro dedos da mão esquerda, posições 7 a 10; o usuário pode selecionar outros modos de captura.

Para reproduzir esse envio, utilize imagens individuais produzidas pela captura, com as posições corretas. Não envie a imagem da mão inteira, caminho de arquivo, URL, prefixo de Data URL ou Base64 de um template no campo image.

Envie o corpo em JSON, com pelo menos um dedo. Este fragmento mostra apenas fingers; os corpos completos estão nas seções de cada rota:

{
"fingers": [
{
"position": 7,
"nfiq2": 55,
"image": "{{finger_image_onboarding}}"
}
]
}
CampoTipoObrigatórioO que enviar
collectionIdstringSim, nas duas rotasIdentificador da coleta, não vazio, com até 128 caracteres. Use um novo identificador para cada nova coleta.
fingersarray de objetosNo fluxo com imagensPelo menos um objeto com position e image. Não envie uma lista vazia.
fingers[].positionintegerSim, em cada dedoPosição do dedo na tabela NIST, de 1 a 10.
fingers[].imagestringSim, em cada dedoImagem individual da impressão digital codificada em Base64, não vazia. Para reproduzir o app, use o PNG retornado pelo SDK, sem prefixo e sem quebras de linha.
fingers[].nfiq2integerNãoO app envia a qualidade nist2Quality retornada pelo SDK. Esse campo adicional não é declarado nem validado pelo DTO atual da API; não é requisito para chamar as rotas nem garantia de aprovação. Se não tiver esse valor da captura, omita-o.
templatestringSe fingers não for enviadoTemplate biométrico gerado pelo SDK, não vazio e compatível com o provedor configurado.
templateFormatstringSe fingers não for enviadoIdentificador do formato/provedor do template, não vazio, com até 32 caracteres. Exemplo: TECH5.
metadataobjectNãoMetadados opcionais da integração, como canal, dispositivo e versão do SDK.

Posições dos dedos

positionDedopositionDedo
1Polegar direito6Polegar esquerdo
2Indicador direito7Indicador esquerdo
3Médio direito8Médio esquerdo
4Anelar direito9Anelar esquerdo
5Mínimo direito10Mínimo esquerdo

O mínimo de um dedo é a validação estrutural da API. A aprovação também depende das imagens, da disponibilidade de referência no provedor e das regras do contrato. Para a autenticação 1:1, recapture dedos presentes no cadastro.

Qualidade e liveness no app

Além da imagem, o app envia nfiq2 por dedo. A configuração atual pede ao SDK o cálculo dessa qualidade. O campo não deve ser confundido com score da comparação ou threshold do contrato.

Quando o liveness está habilitado no app, ele avalia os scores retornados pelo SDK antes de liberar o envio. Scores ausentes ou abaixo do limiar configurado bloqueiam o botão de envio. O corpo HTTP não envia esses scores nem um campo de aprovação de liveness. Portanto, um teste no Postman valida a integração com a API e a resposta biométrica, mas não reproduz essa verificação local da captura.

Os exemplos usam marcadores para substituição. Envie a imagem ou o template completo produzido pela captura; os marcadores não são dados biométricos válidos.

Onboarding de finger

POST /api/v1/services/biometric/onboarding

O onboarding valida a identidade no provedor configurado usando o CPF e as digitais. Quando a validação é aprovada e o contrato habilita o armazenamento, o fluxo cadastra a biometria para comparações posteriores. Se já houver cadastro ativo, a resposta informa essa condição.

Além dos dados da captura, esta rota aceita:

CampoTipoObrigatórioO que enviar
cpfstringSimCPF com 11 dígitos, com ou sem a máscara 000.000.000-00.
personExternalIdstringNãoIdentificador externo opcional da pessoa, com até 128 caracteres. O cadastro usado na comparação 1:1 é localizado pelo CPF.

Exemplo de requisição

Exemplo com um indicador esquerdo. O app envia um objeto para cada dedo capturado e inclui também nfiq2 em cada objeto. metadata e personExternalId são opcionais da API e não são enviados pelo app nesse fluxo.

Terminal window
curl --request POST '{{base_url}}/api/v1/services/biometric/onboarding' \
--header 'Authorization: Bearer {{token}}' \
--header 'Content-Type: application/json' \
--data '{
"cpf": "{{cpf}}",
"collectionId": "onboarding-coleta-001",
"fingers": [
{
"position": 7,
"nfiq2": 55,
"image": "{{finger_image_onboarding}}"
}
]
}'

Exemplo de resposta aprovada — HTTP 200

Exemplo ilustrativo com validação de identidade e armazenamento concluídos. Os identificadores, provedores e códigos técnicos variam conforme a configuração e o resultado da operação.

{
"transactionId": "5c9faac7-706c-4de6-8af5-f5ec895ee42f",
"collectionId": "onboarding-coleta-001",
"flow": "ONBOARDING",
"status": "APPROVED",
"resultCode": "ONBOARDING_APPROVED",
"message": "Onboarding approved.",
"decision": "MATCH",
"biometricAlreadyRegistered": false,
"billingStatus": "REGISTERED",
"templateStatus": "STORED",
"provider": "VALID_ID_CHECK",
"providerRawStatus": "VALID_ID_CHECK_MATCH",
"matcherProvider": "TECH5_OMNIMATCH",
"matcherRawStatus": "TECH5_ENROLL_OK",
"createdAt": "2026-09-11T12:00:00.000Z"
}

Antes de seguir para a autenticação 1:1, confira templateStatus: STORED indica armazenamento e ALREADY_EXISTS indica cadastro existente. Uma identidade aprovada com templateStatus: "NOT_STORED" não confirma que houve cadastro para autenticação. Se o cadastro falhar, o retorno será PENDING com TEMPLATE_REGISTRATION_FAILED, mesmo que decision seja MATCH.

Autenticação de finger

POST /api/v1/services/biometric/authenticate

Envie uma nova captura e um novo collectionId. O modo padrão é ONE_TO_ONE: a API busca o cadastro ativo do CPF no contexto da aplicação e do contrato e compara a captura com esse cadastro.

Além dos dados da captura, esta rota aceita:

CampoTipoObrigatórioO que enviar
modestringNãoONE_TO_ONE (padrão) ou ONE_TO_N.
cpfstringEm ONE_TO_ONE, inclusive quando mode é omitidoCPF do cadastro, com 11 dígitos, com ou sem máscara. Em ONE_TO_N, pode ser omitido.
transactionContextstringNãoContexto opcional da transação, com até 128 caracteres.
operationTypestringNãoTipo opcional de operação, com até 64 caracteres.

Exemplo de requisição 1:1

Terminal window
curl --request POST '{{base_url}}/api/v1/services/biometric/authenticate' \
--header 'Authorization: Bearer {{token}}' \
--header 'Content-Type: application/json' \
--data '{
"cpf": "{{cpf}}",
"mode": "ONE_TO_ONE",
"collectionId": "autenticacao-coleta-002",
"fingers": [
{
"position": 7,
"nfiq2": 55,
"image": "{{finger_image_authentication}}"
}
]
}'

Alternativa por template

O app deste roteiro envia imagens em fingers, não template. Use a alternativa abaixo somente se sua integração já produzir um template compatível e o provedor configurado suportar esse envio. templateFormat: "TECH5" é um identificador, não converte PNG, WSQ ou outro arquivo em template. Para testar o mesmo fluxo do app, mantenha os exemplos com imagens.

Exemplo de corpo para a mesma rota:

{
"cpf": "{{cpf}}",
"mode": "ONE_TO_ONE",
"collectionId": "autenticacao-coleta-003",
"template": "{{template_gerado_pelo_sdk}}",
"templateFormat": "TECH5"
}

Exemplo de resposta aprovada — HTTP 200

Os valores de score e threshold abaixo são ilustrativos; o limiar vem do contrato, e a escala do score depende do provedor.

{
"transactionId": "c5a95adc-8e34-4eaf-85ee-a27c01b276d1",
"collectionId": "autenticacao-coleta-002",
"flow": "AUTHENTICATION",
"authenticationMode": "ONE_TO_ONE",
"status": "APPROVED",
"resultCode": "AUTHENTICATION_APPROVED",
"message": "Authentication approved.",
"decision": "MATCH",
"score": 0.92,
"threshold": 0.85,
"billingStatus": "REGISTERED",
"provider": "TECH5_OMNIMATCH",
"providerRawStatus": "TECH5_MATCH_OK",
"createdAt": "2026-09-11T12:05:00.000Z"
}

Identificação 1:N

Para buscar uma correspondência na galeria do provedor de comparação configurado, envie mode: "ONE_TO_N". Esse modo dispensa o CPF e requer suporte à identificação no contrato.

Terminal window
curl --request POST '{{base_url}}/api/v1/services/biometric/authenticate' \
--header 'Authorization: Bearer {{token}}' \
--header 'Content-Type: application/json' \
--data '{
"mode": "ONE_TO_N",
"collectionId": "identificacao-coleta-004",
"fingers": [
{
"position": 7,
"nfiq2": 55,
"image": "{{finger_image_authentication}}"
}
]
}'

A busca usa a galeria do provedor configurado no contrato; ela não consulta a base de validação de CPF do onboarding.

Uma identificação aprovada retorna authenticationMode: "ONE_TO_N", status: "APPROVED", resultCode: "IDENTIFICATION_APPROVED" e decision: "MATCH". Quando disponível, providerExternalId contém o identificador do candidato selecionado no provedor; ele não é o CPF. A resposta pública não inclui uma lista de candidatos.

Como interpretar as respostas

HTTP 200 não significa, por si só, aprovação biométrica. O app considera sucesso HTTP 2xx acompanhado de status: "APPROVED". Confira status, resultCode e decision no JSON. Use resultCode para tratar o resultado na integração; message é uma descrição legível.

resultCodestatus esperadoSignificado
ONBOARDING_APPROVEDAPPROVEDIdentidade aprovada; consulte templateStatus para saber se houve armazenamento.
BIOMETRIC_ALREADY_REGISTEREDAPPROVEDIdentidade aprovada e cadastro biométrico já existente.
AUTHENTICATION_APPROVEDAPPROVEDComparação 1:1 aprovada.
IDENTIFICATION_APPROVEDAPPROVEDIdentificação 1:N aprovada.
BIOMETRIC_NO_MATCHREJECTEDBiometria sem correspondência (NO_MATCH).
BIOMETRIC_NOT_FOUNDREJECTEDBiometria não encontrada pelo provedor (NOT_FOUND).
BIOMETRIC_NOT_ENROLLEDREJECTEDNenhum cadastro ativo encontrado para o CPF na autenticação 1:1 (NOT_FOUND).
PROVIDER_UNAVAILABLEPENDINGProvedor indisponível ou com erro; consulte os campos de erro.
TEMPLATE_REGISTRATION_FAILEDPENDINGValidação de identidade aprovada, mas cadastro biométrico pendente ou com falha.
DUPLICATE_COLLECTIONConforme a decisão armazenada, ou PENDINGColeta já recebida; nenhuma nova validação ou comparação é executada.

Campos de retorno

Campos opcionais podem não aparecer no JSON, conforme o fluxo e as informações disponíveis.

CampoTipoDescrição
transactionIdstringIdentificador da transação para rastreamento.
collectionIdstringIdentificador de coleta enviado na requisição.
flowstringONBOARDING ou AUTHENTICATION.
authenticationModestringModo usado na autenticação: ONE_TO_ONE ou ONE_TO_N.
statusstringResultado do fluxo: APPROVED, REJECTED ou PENDING.
resultCode / messagestringCódigo do resultado e sua descrição.
decisionstringDecisão biométrica, como MATCH, NO_MATCH, NOT_FOUND ou UNAVAILABLE.
score / thresholdnumberScore retornado pela comparação, quando disponível, e limiar configurado.
biometricAlreadyRegisteredbooleanNo onboarding, indica se o cadastro já existia.
templateStatusstringNo onboarding: STORED, ALREADY_EXISTS, NOT_STORED ou FAILED.
billingStatusstringEstado do registro de cobrança: REGISTERED ou SKIPPED_DUPLICATE nos retornos usuais. Não indica aprovação biométrica.
provider / providerRawStatusstringProvedor e código técnico da validação de identidade ou comparação.
providerExternalIdstringIdentificador externo retornado pelo provedor, quando disponível.
matcherProvider / matcherRawStatus / matcherExternalIdstringDados do provedor de cadastro biométrico, quando disponíveis no onboarding.
errorSourcestringOrigem do erro: IDENTITY_PROVIDER, TECH5 ou FIDUCIA_API.
errorCode / errorMessagestringCódigo técnico e descrição do erro, quando aplicável.
createdAtstringData/hora da transação no formato ISO 8601.

Exemplo de autenticação sem cadastro — HTTP 200

{
"transactionId": "b231bf42-003b-4d1b-9a1a-c7569ed38ce8",
"collectionId": "autenticacao-coleta-005",
"flow": "AUTHENTICATION",
"authenticationMode": "ONE_TO_ONE",
"status": "REJECTED",
"resultCode": "BIOMETRIC_NOT_ENROLLED",
"message": "No active biometric enrollment was found for this person.",
"decision": "NOT_FOUND",
"threshold": 0.85,
"billingStatus": "REGISTERED",
"provider": "TECH5_OMNIMATCH",
"providerRawStatus": "BIOMETRIC_ENROLLMENT_NOT_FOUND",
"createdAt": "2026-09-11T12:10:00.000Z"
}

Reenvios e duplicidade

A API identifica duplicidade pela combinação de collectionId, aplicação e fluxo (ONBOARDING ou AUTHENTICATION). Ao reenviar a mesma coleta, mantenha seu identificador. Para uma nova captura ou uma nova comparação, inclusive ao mudar o modo de autenticação, gere outro collectionId.

Uma duplicata retorna resultCode: "DUPLICATE_COLLECTION" e billingStatus: "SKIPPED_DUPLICATE", com os dados armazenados da coleta. Esse retorno não reproduz necessariamente todos os campos da primeira resposta: por exemplo, pode não incluir score, threshold ou templateStatus. O status é calculado a partir da decisão armazenada; não interprete a duplicidade como uma nova aprovação ou confirmação de armazenamento.

Erros HTTP

HTTPO que esperar
200Fluxo processado, inclusive recusa, indisponibilidade do provedor ou duplicidade. Leia o resultado no corpo.
400Corpo inválido, campo obrigatório ausente ou configuração inválida/ausente do contrato ou provedor.
401Token ausente, inválido ou expirado. Gere um token válido com a key e o secret e envie Authorization: Bearer {{token}}.
500Erro interno da API.

Na geração de token, credenciais inválidas podem retornar HTTP 400 com Invalid credential. Isso é diferente do HTTP 401 ao chamar as rotas biométricas com token ausente ou inválido.

Erros capturados durante a execução do fluxo usam resultCode: "API_ERROR". Exemplo de HTTP 400 para uma aplicação sem contrato biométrico:

{
"statusCode": 400,
"resultCode": "API_ERROR",
"errorSource": "FIDUCIA_API",
"errorCode": "FIDUCIA_API_REQUEST_ERROR",
"errorMessage": "Biometric contract not configured for app",
"message": "Biometric contract not configured for app"
}

Erros de autenticação e de validação do corpo ocorrem antes da execução do fluxo e podem usar o formato padrão abaixo, sem resultCode. Em erros de validação, message pode ser uma lista de mensagens.

{
"statusCode": 401,
"message": "Unauthorized",
"error": "Unauthorized"
}