---
title: "Concluir etapa de verificação"
method: POST
path: "/v1/transactions/{transactionId}/steps/{stepId}/complete"
tags: ["Steps"]
---

# Concluir etapa de verificação

`POST /v1/transactions/{transactionId}/steps/{stepId}/complete`

## Request

- Base URL: `https://api.signdocs.com.br`
- URL: `https://api.signdocs.com.br/v1/transactions/{transactionId}/steps/{stepId}/complete`
- Auth: HTTP bearer

Submete os dados para conclusão de uma etapa de verificação. O corpo da requisição
varia conforme o tipo da etapa:

- **BIOMETRIC_LIVENESS / BIOMETRIC_MATCH**: `{ "livenessSessionId": "..." }`
- **BIOMETRIC_MATCH com referência por transação**: `{ "referenceImage": { "source": "BASE64_IMAGE", "data": "<base64>" } }` — compara o liveness com a imagem enviada em vez do enrollment do usuário. Requer a flag `perTransactionReferenceEnabled` no tenant. Exclusivo deste endpoint: em sessões de assinatura, a imagem por transação é enviada em `referenceImage.content` na criação da sessão.
- **OTP_VERIFY**: `{ "code": "123456" }`
- **CLICK_ACCEPT**: `{ "accepted": true }`
- **DOCUMENT_PHOTO_MATCH**: `{ "documentImage": "<base64>", "documentType": "CNH" }` — Envia a foto do documento (base64, máx. 5MB). O tipo aceito é `RG`, `CNH`, `PASSPORT` ou `OTHER`. A face é extraída e comparada com a referência biométrica. Retorna `similarity` score.
- **SERPRO_IDENTITY_CHECK**: `{ "cpf": "12345678901", "name": "João da Silva", "birthDate": "1990-01-15" }` — Valida identidade via SERPRO DataValid. Disponível apenas quando o tenant possui `serpro.enabled`.
- **DIGITAL_SIGN_A1**: Não requer corpo (use o fluxo `/signing`).

### Geolocalização condicional

Quando o tenant possui a flag `biometricRequired` habilitada, o campo `geolocation`
é **obrigatório** para etapas biométricas (`BIOMETRIC_LIVENESS`, `BIOMETRIC_MATCH`, `DOCUMENT_PHOTO_MATCH`).
Formato: `{ "latitude": -23.5505, "longitude": -46.6333 }`.

Requer scope `steps:write`.

## Path parameters

- `transactionId` string, required
- `stepId` string, required

## Request body

- StepCompleteRequest: Dados para conclusão da etapa. Os campos variam conforme o tipo: - `BIOMETRIC_LIVENESS` / `BIOMETRIC_MATCH`: envie `livenessSessionId`. - `BIOMETRIC_MATCH` com referência por transação: envie `referenceImage`. - Em sandbox: `sandboxSimilarity` simula o score de `BIOMETRIC_MATCH` e `DOCUMENT_PHOTO_MATCH`. - `OTP_VERIFY`: envie `code`. - `CLICK_ACCEPT`: envie `accepted`. - `DOCUMENT_PHOTO_MATCH`: envie `documentImage` e `documentType`. - `SERPRO_IDENTITY_CHECK`: envie `cpf`, `name` e `birthDate`.
  - `livenessSessionId` string: ID da sessão de prova de vida (para etapas biométricas).
  - `referenceImage` object: Imagem de referência por transação para a etapa `BIOMETRIC_MATCH`, usada no lugar do enrollment do usuário. Requer a flag `perTransactionReferenceEnabled` habilitada no tenant — caso contrário, 422. A imagem é validada no envio (exatamente um rosto detectável) e usada apenas nesta comparação: não é armazenada e não cria enrollment. Só o hash SHA-256 fica na evidência, em `enrollmentRef.imageHash`, junto de `enrollmentRef.capturedFrom: STEP_COMPLETE`. Aceito apenas neste endpoint. Em sessões de assinatura (`POST /v1/signing-sessions`), envie a imagem em `referenceImage.content` na criação da sessão.
    - `source` 'BASE64_IMAGE', required: Formato da imagem enviada. Único valor aceito.
    - `data` string, byte, required: Imagem JPEG codificada em base64.
  - `sandboxBrightness` number, double: Brilho simulado da captura, para ensaiar a reprovação por qualidade (`DOCUMENT_QUALITY_LOW`). Mesmo enquadramento do `sandboxSimilarity`: só vale em sandbox. Antes destes campos as ramificações de sandbox fixavam 80/80 e nunca avaliavam o piso de qualidade — ou seja, o erro que mais aparece em campo (luz ruim, reflexo no visor, sujeito em movimento) era o único que o integrador não conseguia reproduzir sob demanda.
  - `sandboxSharpness` number, double: Nitidez simulada da captura. Ver `sandboxBrightness`.
  - `sandboxLivenessConfidence` number, double: Confiança de liveness simulada, para ensaiar a reprovação. Mesmo enquadramento do `sandboxSimilarity`: só vale em sandbox, e nunca aprova uma verificação real. Substitui o truque antigo de escrever `fail` no `livenessSessionId`, que só produzia 99.5 ou 30.0 — nenhum dos dois perto do limiar, que é justamente onde as capturas reais caem. A convenção antiga continua valendo quando nada é informado.
  - `sandboxSimilarity` number, double: Similaridade simulada para as etapas `BIOMETRIC_MATCH` e `DOCUMENT_PHOTO_MATCH` em sandbox, usada para exercitar o caminho de reprovação. Padrão 99.5, que aprova; abaixo do limiar do tenant, a etapa reprova como reprovaria em produção. Só é lida com credenciais de sandbox (`credentialMode: SANDBOX`) e quando não existe frame real de liveness. Se houve captura real, a comparação real acontece e este campo é ignorado — ele nunca faz uma comparação real passar. Um valor fora de 0-100 ou não numérico retorna 400. No fluxo de sessões de assinatura, o equivalente é `metadata.sandboxSimilarity` na criação da sessão (ou `sandboxSimilarity` no corpo do advance, em integrações headless).
  - `code` string: Código OTP de 6 dígitos (para etapa OTP_VERIFY).
  - `accepted` boolean: Aceite do termo (para etapa CLICK_ACCEPT).
  - `documentImage` string, byte: Foto do documento codificada em base64 (máx. 5MB). Para etapa `DOCUMENT_PHOTO_MATCH`.
  - `documentType` 'RG' | 'CNH' | 'PASSPORT' | 'OTHER': Tipo do documento enviado.
  - `cpf` string: CPF do signatário (para etapa `SERPRO_IDENTITY_CHECK`).
  - `name` string: Nome completo (para etapa `SERPRO_IDENTITY_CHECK`).
  - `birthDate` string, date: Data de nascimento no formato `YYYY-MM-DD` (para etapa `SERPRO_IDENTITY_CHECK`).
  - `geolocation` object: Geolocalização do dispositivo. Obrigatório quando o tenant possui `biometricRequired` habilitado e a etapa é biométrica.
    - `latitude` number, double: Latitude em graus decimais.
    - `longitude` number, double: Longitude em graus decimais.

## Response `200`

Etapa concluída (ou falhou). Verifique o campo `status` na resposta.

- StepCompleteResponse: Resposta de conclusão de etapa.
  - `stepId` string, required
  - `type` 'CLICK_ACCEPT' | 'OTP_CHALLENGE' | 'OTP_VERIFY' | 'BIOMETRIC_LIVENESS' | 'BIOMETRIC_MATCH' | 'DOCUMENT_PHOTO_MATCH' | 'SERPRO_IDENTITY_CHECK' | 'DIGITAL_SIGN_A1' | 'PURPOSE_DISCLOSURE', required: Tipos de etapa de verificação de identidade. Em `policy.customSteps` a ordem é validada na criação: BIOMETRIC_MATCH, SERPRO_IDENTITY_CHECK e DOCUMENT_PHOTO_MATCH exigem BIOMETRIC_LIVENESS antes de si, OTP_CHALLENGE e OTP_VERIFY vêm sempre em par e nessa ordem, e DIGITAL_SIGN_A1 tem de ser a última etapa.
  - `status` 'PENDING' | 'STARTED' | 'COMPLETED' | 'FAILED' | 'SKIPPED' | 'DORMANT', required: Status possíveis de uma etapa. `SKIPPED` e `DORMANT` aparecem nos perfis com fallback: a etapa dormente é criada junto com a transação e só entra em `PENDING` se a etapa que ela substitui for pulada.
  - `attempts` integer, required: Número de tentativas realizadas.
  - `result` StepResult: Resultado detalhado da etapa de verificação.
    - `liveness` object: Resultado da verificação de prova de vida.
      - `confidence` number, double: Nível de confiança da verificação (0-100).
      - `provider` string: Provedor de biometria utilizado.
      - `captureMode` 'BANK_APP' | 'HOSTED_PAGE': Modo de captura biométrica.
    - `match` object: Resultado da comparação facial.
      - `similarity` number, double: Similaridade facial (0-100).
      - `threshold` number, double: Limiar mínimo configurado.
    - `otp` object: Resultado da verificação OTP.
      - `verified` boolean: Se o código OTP foi verificado com sucesso.
      - `channel` 'email' | 'sms' | 'whatsapp' | 'telegram': Canal de entrega do OTP, escolhido por signatário. Independente do canal usado para entregar o link de assinatura: um convite por WhatsApp pode ter OTP por e-mail, e um convite por e-mail pode ter OTP por WhatsApp. `sms` e `whatsapp` exigem `signer.phone` e o canal habilitado para o tenant (`sms.enabled` / `whatsapp.enabled`); caso contrário o passo de OTP falha com **422**. No WhatsApp, um número que pediu para não receber mensagens também falha com 422, com uma mensagem que orienta a escolher outro canal. `telegram` exige `telegram.enabled` no tenant. O código chega pelo bot da SignDocs quando o signatário já registrou o próprio CPF nele; sem registro, é enviado por telefone (Telegram Gateway) se o tenant tiver essa opção habilitada, e caso contrário o passo falha com **422** de imediato. Ao criar a sessão, `otpChannel: telegram` ainda exige `signer.email` quando a política tem OTP. Um OTP por WhatsApp ou pelo Telegram Gateway consome a cota de mensagens do tenant; esgotada, o envio é recusado com **429**.
    - `click` object: Resultado do aceite por clique.
      - `accepted` boolean: Se o termo foi aceito.
      - `textVersion` string: Versão do texto do termo aceito.
    - `digitalSignature` object: Resultado da assinatura digital.
      - `certificateSubject` string: Subject do certificado digital.
      - `certificateSerial` string: Número serial do certificado.
      - `certificateIssuer` string: Emissor do certificado.
      - `algorithm` string: Algoritmo de assinatura utilizado.
      - `signedAt` string, date-time: Momento da assinatura.
      - `signedPdfHash` string: Hash SHA-256 do PDF assinado.
      - `signedPdfS3Key` string: Chave S3 do PDF assinado.
      - `signatureFieldName` string: Nome do campo de assinatura no PDF.
      - `signatureTimestamp` SignatureTimestamp: Carimbo do tempo ICP-Brasil embutido na assinatura (token RFC 3161 emitido por uma ACT credenciada, gravado como `id-aa-signatureTimeStampToken`). Presente apenas quando o recurso está habilitado no tenant. `signedAt` continua sendo a hora do servidor SignDocs; `genTime` é a hora atestada pela ACT.
        - `genTime` string, date-time, required: Data e hora atestadas pela ACT.
        - `tsaName` string, required: Nome distinto (DN) do certificado do servidor de carimbo do tempo.
        - `serial` string, required: Número de série do carimbo (hexadecimal).
        - `policyOid` string, required: OID da política de carimbo do tempo ICP-Brasil.
        - `tokenSha256` string, required: SHA-256 (hex) do token de carimbo do tempo, para conferência com o embutido no documento.
    - `documentPhotoMatch` object: Resultado da comparação facial com foto de documento.
      - `similarity` number, double: Similaridade facial entre documento e referência (0-100).
      - `documentType` 'RG' | 'CNH' | 'PASSPORT' | 'OTHER': Tipo do documento utilizado.
      - `extractionConfidence` number, double: Confiança da extração facial do documento (0-100).
    - `serproIdentityCheck` object: Resultado da verificação de identidade via SERPRO DataValid.
      - `verified` boolean: Se a identidade foi verificada com sucesso.
      - `cpfMatch` boolean: Se o CPF corresponde ao nome informado.
      - `nameMatch` boolean: Se o nome corresponde ao cadastro.
      - `birthDateMatch` boolean: Se a data de nascimento corresponde ao cadastro.
      - `governmentDatabase` 'SERPRO_DATAVALID': Base de dados governamental utilizada para validação de identidade.
    - `governmentDbValidation` GovernmentDbValidation: Resultado da validação contra base de dados governamental.
      - `database` 'SERPRO_DATAVALID': Base de dados governamental utilizada para validação de identidade.
      - `validatedAt` string, date-time: Momento da validação original.
      - `cpfHash` string: Hash SHA-256 do CPF validado.
      - `biometricScore` number, double: Score de similaridade biométrica (0-1).
      - `cached` boolean: Se true, uma validação anterior foi reutilizada após verificação de similaridade facial.
      - `cacheVerifySimilarity` number, double: Score do CompareFaces utilizado para aceitar o cache. Presente apenas quando cached é true.
    - `enrollmentRef` EnrollmentRef: Referência ao enrollment biométrico utilizado.
      - `source` 'ENROLLMENT' | 'TRANSACTION_PROVIDED': Origem da imagem de referência utilizada.
      - `capturedFrom` 'ORGANIZATION_PROVIDED' | 'BANK_PROVIDED' | 'FIRST_LIVENESS' | 'DOCUMENT_PHOTO' | 'SESSION_CREATE' | 'STEP_COMPLETE': Como a imagem de referência foi originalmente capturada. Para `source: ENROLLMENT`, repete o `source` do enrollment cadastrado (`ORGANIZATION_PROVIDED`, `FIRST_LIVENESS` ou `DOCUMENT_PHOTO`). Evidências seladas antes de setembro de 2026 trazem `BANK_PROVIDED`, o nome anterior de `ORGANIZATION_PROVIDED`; como o pacote de evidências é assinado, esse valor não pode ser reescrito e um verificador precisa resolver os dois para sempre. Para `source: TRANSACTION_PROVIDED`, identifica a requisição que trouxe a imagem: `SESSION_CREATE` (campo `referenceImage` na criação da sessão) ou `STEP_COMPLETE` (campo `referenceImage` no complete da etapa). Ausente em evidências geradas antes da introdução do campo.
      - `enrolledAt` string, date-time: Momento do enrollment.
      - `enrollmentHash` string: Hash da imagem de enrollment.
      - `version` integer: Versão do enrollment.
      - `imageHash` string: Hash da imagem utilizada na comparação.
    - `providerTimestamp` string, date-time: Timestamp do provedor externo.

## Other responses

- `400`: Requisição inválida — parâmetros ausentes ou malformados.
- `401`: Autenticação ausente ou inválida.
- `403`: Permissões insuficientes para a operação solicitada. Inclui `purpose: "ACTION_AUTHENTICATION"` sem `featureFlags.trustSessionsEnabled`. A verificação é pelo `purpose`, não pela rota: vale em `/v1/transactions`, `/v1/signing-sessions` e `/v1/envelopes/{envelopeId}/sessions`, além de `/v1/trust-sessions`. O remédio é habilitar a flag para o tenant e provisionar a cota `monthlyTrustSessions`.
- `404`: Recurso não encontrado.
- `409`: Conflito de estado — a operação não pode ser realizada no estado atual do recurso.
- `422`: Entidade não processável — a requisição é sintaticamente válida mas semanticamente incorreta. Inclui o perfil de política não autorizado para o tenant. As rotas de criação (`/v1/transactions`, `/v1/signing-sessions` e `/v1/envelopes/{envelopeId}/sessions`) verificam a mesma regra, antes de cota, convite e gravação — a recusa não consome documento. As flags envolvidas são `featureFlags.customPolicyEnabled` (perfil `CUSTOM`), `serpro.enabled` (perfis SERPRO), `featureFlags.documentExtractionEnabled` (fallback por documento; `BIOMETRIC_SERPRO_AUTO_FALLBACK` exige as duas últimas) e `featureFlags.biometricRequired`. O remédio é habilitar a flag para o tenant. `signer.cpf` e `signer.birthDate`, exigidos pelos perfis SERPRO, são validados como **400** e não aqui: requisição malformada, corrigível na mesma chamada.
- `500`: Erro interno do servidor.

---

[API](https://skmtc.dev/signdocs/apis/signdocs-brasil-external-api.md) · [All operations](https://skmtc.dev/signdocs/apis/signdocs-brasil-external-api/llms.txt) · [OpenAPI document](https://skmtc.dev/signdocs/apis/signdocs-brasil-external-api/revisions/2d3805aed161?raw)
