Skip to content

Fluxo de Liveness

O fluxo de liveness (prova de vida) tem quatro passos e roda em dois lugares diferentes: parte no seu backend, parte no dispositivo do usuário. É essa divisão que explica quase tudo o que existe aqui — o token JWT, o SDK de captura e o identificador que amarra as duas chamadas à API.

As páginas de referência descrevem cada endpoint isoladamente. Esta página responde o que elas não respondem: em que ordem chamar, quem chama o quê e como os identificadores se encadeiam.

‼️ Duas armadilhas, antes de qualquer coisa

Cada uma delas já quebrou integração em produção, e as duas falham em silêncio, com 200 na resposta.

  1. Chame /liveness/v2, sempre com a versão no caminho. É o envelope da v2 — com o resultado em data.isAlive — que o passo seguinte lê. Uma URL sem versão não garante essa resposta, e o face match responde matched: false para sempre, sem erro nenhum, quando não encontra data.isAlive.
  2. O /face-match-for-liveness devolve só {"matched": true} ou {"matched": false}. Sem id, sem version, sem data, sem metadata. É a exceção ao envelope padrão da API, e um cliente que espera data recebe undefined.

Visão geral

#Quem chamaO quêO que recebe de volta
1Seu backendPOST /auth-jwtaccessToken
2Seu backend → SDKentrega o token ao dispositivo
3SDK, no dispositivoPOST /liveness/v2 com a selfie capturadaid da sessão e data.isAlive
4Seu backendPOST /face-match-for-liveness/{id}/v2 com o documentomatched

Entre o passo 3 e o passo 4, o id da sessão de liveness precisa voltar do dispositivo para o seu backend — é o único fio que liga as duas chamadas.

 Seu backend           SDK no dispositivo           API Nextcode
      │                         │                         │
      │  1. POST /auth-jwt      │                         │
      ────────────────────────────────────────────────────▶
      │                { accessToken }                    │
      ◀────────────────────────────────────────────────────
      │                         │                         │
      │  2. entrega o token     │                         │
      ──────────────────────────▶                         │
      │                         │                         │
      │             3. captura a selfie e chama           │
      │                 POST /liveness/v2                 │
      │                         ──────────────────────────▶
      │                         │   { id, data.isAlive }  │
      │                         ◀──────────────────────────
      │                         │                         │
      │  o id da sessão volta para o backend              │
      ◀──────────────────────────                         │
      │                         │                         │
      │  4. POST /face-match-for-liveness/{id}/v2         │
      │     + a foto do documento                         │
      ────────────────────────────────────────────────────▶
      │                { "matched": true }                │
      ◀────────────────────────────────────────────────────
      │                         │                         │

A linha divisória importa

Tudo o que acontece na coluna do meio roda em código que o usuário final pode inspecionar. É por isso que a chave de API nunca desce até lá, e por isso o passo 1 existe.

Passo 1 — o backend gera o token

O SDK de captura roda dentro do seu aplicativo ou no navegador do usuário. Colocar a chave de API ali seria entregá-la a qualquer pessoa disposta a abrir o inspetor do navegador ou a descompilar o APK.

A saída é um token JWT de curta duração: o seu backend chama o /auth-jwt com a chave de API e recebe um accessToken que pode descer com segurança até o dispositivo. Ele carrega as mesmas permissões da chave que o emitiu e expira sozinho.

Referência completa dos parâmetros e das respostas: Token JWT.

Três decisões que valem para este passo:

  • A chamada parte sempre do seu backend. O /auth-jwt é o único endpoint da API que não aceita o próprio token JWT: é ele que emite o token, e só a chave de API o autentica.
  • Gere o token imediatamente antes de entregá-lo ao SDK. O ttl deve cobrir a janela de captura, não a sessão inteira do usuário. Um token emitido no login e usado dez minutos depois costuma chegar ao SDK já expirado.
  • O ttl é uma string com unidade"15m", não 900 nem "900". Essa é a causa mais comum de 500 neste endpoint, e ela está detalhada na página de referência.

Passo 2 — capturar com o SDK

O SDK conduz o liveness no dispositivo, autentica-se com o token no header Authorization: Bearer <accessToken> e chama o /liveness/v2 diretamente. A selfie não passa pelo seu backend.

PlataformaRepositório de exemplo
Androidliveness-sdk-android-sample
iOSliveness-sdk-ios-sample
Webliveness-sdk-web-sample

Confirme que a versão chamada é a v2. Este é o ponto exato em que a primeira armadilha se instala: sem a versão no caminho, a resposta parece normal, e o problema só aparece no passo 4 — como um matched: false que nunca vira true.

Passo 3 — ler o resultado do liveness

data.isAlive responde a uma única pergunta: há uma pessoa viva, presente no momento da captura? Ele não identifica ninguém e não compara com documento algum — essa é a função do passo 4.

isAliveO que aconteceuEncaminhamento usual
truePessoa viva, captura legítima.Siga para o passo 4.
falseA análise rodou e não aprovou.Repetir a captura costuma resolver: luz fraca, foco ou enquadramento derrubam o resultado tanto quanto uma fraude.

Formato completo da resposta: Liveness.

Guarde o id da resposta. Ele é o livenessRequestId do passo seguinte, e sem ele a sessão não é recuperável. Ele também vem no header Nextid-ReqId de toda resposta.

Passo 4 — comparar com o documento

Aqui a pergunta muda: já sabemos que há uma pessoa viva; falta saber se é a pessoa do documento.

O endpoint é o Face Match for Liveness, e o encadeamento acontece pela URL:

bash
curl -i -X POST 'https://api-homolog.nxcd.app/face-match-for-liveness/13cfec7c-b238-4820-a4d1-5173e4c1418e/v2' \
  --header 'Authorization: ApiKey SUA_CHAVE_AQUI' \
  --form 'documento=@./documento-frente.jpg'

O 13cfec7c-… no caminho é o id que veio do passo 3. Você envia apenas o documento — a selfie já está guardada na sessão de liveness, e reenviá-la seria comparar a imagem com ela mesma.

A resposta é o corpo mais curto de toda a API:

json
{ "matched": true }

Sem envelope, sem id, sem confidence. O identificador desta requisição está no header Nextid-ReqId.

Chame este passo só quando isAlive for true

Uma sessão reprovada devolve matched: false sem executar comparação alguma — e uma resposta 200 é tarifada do mesmo jeito. Verificar o resultado do passo 3 antes economiza uma chamada e evita interpretar como "faces diferentes" o que foi apenas "não havia o que comparar".

E se a selfie não veio de uma sessão de liveness?

Então o endpoint é outro: o Face Match recebe as duas imagens na mesma requisição e devolve o envelope completo, com confidence. Use o /face-match-for-liveness quando a selfie já foi capturada pelo SDK, e o /face-match quando você tem os dois arquivos em mãos.

Erros comuns no fluxo

SintomaCausa provávelO que fazer
401 no SDK, no meio da capturaToken expirado. O ttl é curto demais, ou o token foi emitido muito antes da captura começar.Emitir o token logo antes de entregá-lo ao SDK e dimensionar o ttl pela janela de captura.
500 no /auth-jwtttl enviado como número (900) ou como string sem unidade ("900", lido como 900 milissegundos).Enviar "15m", "1h", "30s".
401 no /auth-jwtChave de API ausente, inválida, ou sem permissão de emissão de token.Conferir a chave e o ambiente. O token herda as permissões da chave: se ela não tem o produto, ele também não terá.
matched: false sempre, mesmo com a pessoa certaA sessão de liveness não devolveu data.isAlive — quase sempre por chamar /liveness sem a versão no caminho.Conferir o campo version da resposta do passo 3. Se não for v2, corrigir a URL do SDK.
matched: false logo após um isAlive: falseComportamento esperado: sem sessão aprovada, nada é comparado.Não interpretar como "faces diferentes". Repetir a captura.
matched: false com sessão aprovada e pessoa certalivenessRequestId errado — id de outra requisição, id do Nextid-ReqId da chamada errada — ou nenhum arquivo enviado.Um livenessRequestId inexistente não devolve 404: devolve 200 com matched: false. Confira o id e o arquivo.
404 no /face-match-for-livenessVersão inexistente na URL, ou a imagem da sessão não está mais disponível.Chamar /face-match-for-liveness/{id}/v2 resolve o primeiro caso: a v2 é a única versão.

A lista completa de códigos e o formato das respostas de erro estão em Códigos HTTP das respostas.

Os identificadores, de ponta a ponta

IdentificadorNasce emVai para
accessTokenresposta do POST /auth-jwtheader Authorization: Bearer das chamadas feitas pelo SDK
id da sessãoresposta do POST /liveness/v2caminho do POST /face-match-for-liveness/{id}/v2
Nextid-ReqIdheader de todas as respostasseus logs — é por ele que o suporte localiza uma chamada

Próximos passos

Nextcode | Soluções em Verificação de Identidade