Crie sua própria sequência de etapas de verificação para integrações avançadas.
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.
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,
});
9 tipos de etapas que podem ser combinadas:
CLICK_ACCEPTOTP_CHALLENGEOTP_VERIFYBIOMETRIC_LIVENESSBIOMETRIC_MATCHDIGITAL_SIGN_A1SERPRO_IDENTITY_CHECKDOCUMENT_PHOTO_MATCHPURPOSE_DISCLOSURE| 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. |
// 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']
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 →