Guias de Desenvolvimento

Signing Sessions

Guias dos SDKs

Política Customizada — CUSTOM

Crie sua própria sequência de etapas de verificação para integrações avançadas.

1. O que é

O perfil CUSTOM permite definir sua própria lista ordenada de etapas de verificação. Útil quando nenhum perfil pré-definido atende exatamente seus requisitos. Os campos obrigatórios do signatário variam de acordo com as etapas escolhidas.


2. Criar a sessão

Defina o array customSteps com as etapas desejadas, na ordem de execução.

import { readFileSync } from 'fs';

const pdfBase64 = readFileSync('contrato.pdf').toString('base64');

const session = await client.signingSessions.create({
  purpose: 'DOCUMENT_SIGNATURE',
  policy: {
    profile: 'CUSTOM',
    customSteps: ['CLICK_ACCEPT', 'OTP_CHALLENGE', 'OTP_VERIFY', 'BIOMETRIC_LIVENESS', 'BIOMETRIC_MATCH'],
  },
  signer: {
    name: 'Lucas Almeida',
    cpf: '12345678901',
    email: 'lucas@example.com',
    userExternalId: 'user-020',
  },
  document: { content: pdfBase64, filename: 'contrato.pdf' },
  returnUrl: 'https://app.example.com/done',
  locale: 'pt-BR',
  expiresInMinutes: 60,
});

console.log('Session ID:', session.sessionId);
console.log('Client Secret:', session.clientSecret);

const result = await client.signingSessions.waitForCompletion(session.sessionId);
console.log('Status:', result.status);
console.log('Evidence ID:', result.evidenceId);
import base64

with open('contrato.pdf', 'rb') as f:
    pdf_base64 = base64.b64encode(f.read()).decode()

session = client.signing_sessions.create(CreateSigningSessionRequest(
    purpose='DOCUMENT_SIGNATURE',
    policy=Policy(
        profile='CUSTOM',
        custom_steps=['CLICK_ACCEPT', 'OTP_CHALLENGE', 'OTP_VERIFY', 'BIOMETRIC_LIVENESS', 'BIOMETRIC_MATCH'],
    ),
    signer=Signer(
        name='Lucas Almeida', cpf='12345678901',
        email='lucas@example.com', user_external_id='user-020',
    ),
    document=InlineDocument(content=pdf_base64, filename='contrato.pdf'),
    return_url='https://app.example.com/done',
    locale='pt-BR',
    expires_in_minutes=60,
))

print('Session ID:', session.session_id)
print('Client Secret:', session.client_secret)

result = client.signing_sessions.wait_for_completion(session.session_id)
print('Status:', result.status)
print('Evidence ID:', result.evidence_id)
pdfBytes, _ := os.ReadFile("contrato.pdf")
pdfBase64 := base64.StdEncoding.EncodeToString(pdfBytes)

session, err := client.SigningSessions.Create(ctx, &signdocs.CreateSigningSessionRequest{
    Purpose: signdocs.PurposeDocumentSignature,
    Policy: signdocs.Policy{
        Profile:     "CUSTOM",
        CustomSteps: []string{"CLICK_ACCEPT", "OTP_CHALLENGE", "OTP_VERIFY", "BIOMETRIC_LIVENESS", "BIOMETRIC_MATCH"},
    },
    Signer: signdocs.Signer{
        Name: "Lucas Almeida", CPF: "12345678901",
        Email: "lucas@example.com", UserExternalID: "user-020",
    },
    Document:         &signdocs.DocumentInline{Content: pdfBase64, Filename: "contrato.pdf"},
    ReturnURL:        "https://app.example.com/done",
    Locale:           "pt-BR",
    ExpiresInMinutes: 60,
})
if err != nil { log.Fatal(err) }
fmt.Println("Session ID:", session.SessionID)
fmt.Println("Client Secret:", session.ClientSecret)
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Base64;
import java.util.List;

String pdfBase64 = Base64.getEncoder().encodeToString(Files.readAllBytes(Path.of("contrato.pdf")));
CreateSigningSessionRequest request = new CreateSigningSessionRequest();
request.purpose = "DOCUMENT_SIGNATURE";
request.policy = new Policy("CUSTOM");
request.policy.customSteps = List.of("CLICK_ACCEPT", "OTP_CHALLENGE", "OTP_VERIFY", "BIOMETRIC_LIVENESS", "BIOMETRIC_MATCH");
request.signer = new Signer("Lucas Almeida", "user-020");
request.signer.cpf = "12345678901";
request.signer.email = "lucas@example.com";
request.document = new CreateSigningSessionRequest.InlineDocument(pdfBase64, "contrato.pdf");
request.returnUrl = "https://app.example.com/done";
request.locale = "pt-BR";
request.expiresInMinutes = 60;
SigningSession session = client.signingSessions().create(request);
$pdfBase64 = base64_encode(file_get_contents('contrato.pdf'));

$session = $client->signingSessions->create(new CreateSigningSessionRequest(
    purpose: 'DOCUMENT_SIGNATURE',
    policy: new Policy(
        profile: 'CUSTOM',
        customSteps: ['CLICK_ACCEPT', 'OTP_CHALLENGE', 'OTP_VERIFY', 'BIOMETRIC_LIVENESS', 'BIOMETRIC_MATCH'],
    ),
    signer: new Signer(
        name: 'Lucas Almeida', cpf: '12345678901',
        email: 'lucas@example.com', userExternalId: 'user-020',
    ),
    document: ['content' => $pdfBase64, 'filename' => 'contrato.pdf'],
    returnUrl: 'https://app.example.com/done',
    locale: 'pt-BR',
    expiresInMinutes: 60,
));
using SignDocsBrasil.Api.Models;

var pdfBase64 = Convert.ToBase64String(await File.ReadAllBytesAsync("contrato.pdf"));

var session = await client.SigningSessions.CreateAsync(new CreateSigningSessionRequest
{
    Purpose = "DOCUMENT_SIGNATURE",
    Policy = new Policy
    {
        Profile = "CUSTOM",
        CustomSteps = new[] { "CLICK_ACCEPT", "OTP_CHALLENGE", "OTP_VERIFY", "BIOMETRIC_LIVENESS", "BIOMETRIC_MATCH" },
    },
    Signer = new Signer
    {
        Name = "Lucas Almeida", Cpf = "12345678901",
        Email = "lucas@example.com", UserExternalId = "user-020",
    },
    Document = new InlineDocument { Content = pdfBase64, Filename = "contrato.pdf" },
    ReturnUrl = "https://app.example.com/done",
    Locale = "pt-BR",
    ExpiresInMinutes = 60,
});

3. Etapas disponíveis

9 tipos de etapas que podem ser combinadas:


4. Regras de dependência

Regra Restrição
Par OTP OTP_CHALLENGE e OTP_VERIFY devem estar ambos presentes ou ambos ausentes. OTP_VERIFY deve vir depois de OTP_CHALLENGE.
Par biométrico BIOMETRIC_MATCH requer BIOMETRIC_LIVENESS antes.
SERPRO SERPRO_IDENTITY_CHECK requer BIOMETRIC_LIVENESS antes.
Foto de documento DOCUMENT_PHOTO_MATCH requer BIOMETRIC_LIVENESS antes.
Assinatura digital DIGITAL_SIGN_A1 deve ser a última etapa.
Divulgação de finalidade PURPOSE_DISCLOSURE deve vir antes de BIOMETRIC_LIVENESS.

5. Exemplos de combinações

// Aceite + Biometria (sem OTP)
customSteps: ['CLICK_ACCEPT', 'BIOMETRIC_LIVENESS', 'BIOMETRIC_MATCH']

// Apenas OTP (sem aceite, sem biometria)
customSteps: ['OTP_CHALLENGE', 'OTP_VERIFY']

// Divulgação + Biometria + Certificado Digital
customSteps: ['PURPOSE_DISCLOSURE', 'BIOMETRIC_LIVENESS', 'BIOMETRIC_MATCH', 'CLICK_ACCEPT', 'DIGITAL_SIGN_A1']

6. Quando usar CUSTOM vs perfis nomeados

Use perfis nomeados quando eles correspondem exatamente ao seu fluxo — são validados com mais rigor e podem ganhar otimizações futuras. Use CUSTOM quando precisar de uma combinação não-padrão.

Dica: Consulte os guias dos perfis nomeados (CLICK_ONLY, BIOMETRIC, BIOMETRIC_SERPRO, etc.) para ver as combinações mais comuns.


← NT65 Consignado
Voltar para Visão Geral
Receitas copy-paste →