---
title: "Cadastrar ou atualizar enrollment biométrico"
method: PUT
path: "/v1/users/{userExternalId}/enrollment"
tags: ["Users"]
---

# Cadastrar ou atualizar enrollment biométrico

`PUT /v1/users/{userExternalId}/enrollment`

## Request

- Base URL: `https://api.signdocs.com.br`
- URL: `https://api.signdocs.com.br/v1/users/{userExternalId}/enrollment`
- Auth: HTTP bearer

Registra ou atualiza a imagem de referência biométrica de um usuário.
A imagem deve ser enviada em base64 (JPEG). O enrollment é versionado —
cada chamada incrementa a versão.

### Fontes de enrollment

- **ORGANIZATION_PROVIDED** (padrão): foto vinda dos registros da organização — crachá,
  ficha de RH. O antigo `BANK_PROVIDED` continua aceito e é normalizado na gravação.
- **FIRST_LIVENESS**: Imagem capturada na primeira sessão de liveness.
- **DOCUMENT_PHOTO**: Foto de documento (CNH/RG/passaporte). O rosto é extraído automaticamente.
  Requer a feature flag `documentExtractionEnabled` habilitada no tenant.

### CPF obrigatório

O campo `cpf` é obrigatório e utilizado para vincular o enrollment à identidade do titular.

Requer scope `transactions:write`.

## Path parameters

- `userExternalId` string, required

## Request body

- EnrollmentRequest: Requisição de enrollment biométrico. Todas as imagens são validadas via DetectFaces para garantir presença de exatamente um rosto. Quando `source` é `DOCUMENT_PHOTO`, o rosto é extraído automaticamente do documento e armazenado como imagem de enrollment. Requer `documentExtractionEnabled` no tenant.
  - `dryRun` boolean: Inspeciona sem gravar. Devolve o mesmo veredito que o endpoint de lote — `usable` / `marginal` / `rejected` com as métricas — e **não persiste nada**: nenhuma imagem no S3, nenhum registro, e o prazo de 90 dias não começa a correr. Mesma função dos dois lados, de propósito: uma foto não pode ser julgada de um jeito no lote e de outro aqui.
  - `image` string, byte, required: Imagem facial de referência codificada em base64 (JPEG).
  - `cpf` string, required: CPF do titular (11 dígitos, sem pontuação).
  - `source` 'ORGANIZATION_PROVIDED' | 'FIRST_LIVENESS' | 'DOCUMENT_PHOTO' | 'BANK_PROVIDED': Origem da imagem de enrollment — quem responde por aquele rosto e se o titular estava presente na captura. É o que separa, numa auditoria anos depois, a foto que a organização entregou da captura ao vivo e da que veio de um documento oficial. - `ORGANIZATION_PROVIDED` (padrão): foto vinda dos registros da própria organização — crachá, ficha de RH, folha. O titular não estava presente; quem responde pela imagem é a organização. - `FIRST_LIVENESS`: imagem capturada na primeira sessão de liveness do titular. Captura ao vivo, com o titular presente. - `DOCUMENT_PHOTO`: foto de documento (CNH/RG/passaporte). O rosto é extraído automaticamente. Requer `documentExtractionEnabled`. `BANK_PROVIDED` continua **aceito** como sinônimo de `ORGANIZATION_PROVIDED` e é normalizado na gravação — o valor devolvido e o que vai para a evidência são sempre o canônico. O nome antigo é de quando o único cliente era um banco; quem cadastra operadores de fábrica não deveria precisar enviá-lo.

## Response `200`

Enrollment realizado com sucesso.

- EnrollmentResponse: Resposta de enrollment biométrico.
  - `userExternalId` string, required
  - `enrollmentHash` string, required: Hash SHA-256 da imagem de enrollment (face crop quando DOCUMENT_PHOTO).
  - `enrollmentVersion` integer, required: Versão do enrollment (incrementada a cada atualização).
  - `enrollmentSource` 'BANK_PROVIDED' | 'FIRST_LIVENESS' | 'DOCUMENT_PHOTO', required: Origem do enrollment.
  - `enrolledAt` string, date-time, required
  - `cpf` string, required: CPF do titular.
  - `faceConfidence` number, required: Confiança da detecção facial (0-100%).
  - `documentImageHash` string: Hash SHA-256 do documento original. Presente apenas quando `enrollmentSource` é `DOCUMENT_PHOTO`.
  - `referenceQuality` 'usable' | 'marginal' | 'rejected': **A foto serve como referência?** É este o campo a ler — não deduza do array `warnings`. `usable` limpa; `marginal` guardou normalmente mas é referência fraca; `rejected` não seria guardada. Numa gravação bem-sucedida só aparecem `usable` e `marginal`. Deliberadamente **não** é o `status`: no lote, `status` diz o que aconteceu com a gravação (`enrolled`/`failed`), que é outra pergunta. Uma foto ruim que gravou bem é `status: enrolled` com `referenceQuality: marginal` — e é essa a combinação que interessa. É o mesmo campo que o `dryRun` devolve, então um único trecho de código julga a foto tenha ela vindo de qual chamada for.
  - `quality` object: Medidas do Rekognition para o rosto detectado (0-100), da mesma chamada `DetectFaces` que o cadastro já faz. **`faceConfidence` sozinho engana aqui:** ele responde "isto é um rosto?", e uma foto escura e tremida marca 99,99 nele sendo uma referência ruim. São estes números que preveem se a comparação vai funcionar.
    - `brightness` number, double
    - `sharpness` number, double
  - `pose` object: Rotação da cabeça em graus.
    - `yaw` number, double
    - `pitch` number, double
    - `roll` number, double
  - `faceCoverage` number, double: Área do rosto como fração do quadro (0-1).
  - `warnings` string[]: Ressalvas de qualidade. Vêm também numa gravação bem-sucedida — a foto é guardada de qualquer jeito, e é melhor saber que ela é fraca agora do que por uma assinatura reprovada daqui a três meses. Array vazio quando não há ressalva.
  - `extractionConfidence` number: Confiança da extração facial do documento. Presente apenas quando `enrollmentSource` é `DOCUMENT_PHOTO`.

## 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`.
- `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)
