Guias de Desenvolvimento

Signing Sessions

Guias dos SDKs

Aceite Simples — CLICK_ONLY

O perfil mais simples. O signatário visualiza o documento e aceita com um clique.

1. O que é

CLICK_ONLY gera uma única etapa CLICK_ACCEPT. O signatário visualiza o PDF e clica "Aceitar". Sem OTP, sem biometria, sem certificado.

Ideal para termos de uso, políticas de privacidade e contratos simples.

Signatário clica "Aceitar" ──> COMPLETED

2. Requisitos

Campo Obrigatório Notas
name Sim Nome completo
userExternalId Sim ID do usuário no seu sistema
cpf ou cnpj Sim (um) CPF: 11 dígitos, CNPJ: 14 dígitos, sem pontuação
email Não Opcional para CLICK_ONLY

3. Criar a sessão

Crie a sessão no backend. A página hospedada cuida de tudo.

import { readFileSync } from 'fs';

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

const session = await client.signingSessions.create({
  purpose: 'DOCUMENT_SIGNATURE',
  policy: { profile: 'CLICK_ONLY' },
  signer: { name: 'João Silva', email: 'joao@example.com', userExternalId: 'user-001' },
  document: { content: pdfBase64, filename: 'contrato.pdf' },
  returnUrl: 'https://app.example.com/done',
  locale: 'pt-BR',
  expiresInMinutes: 60,
});

// Envie session.clientSecret para o frontend
console.log('Session ID:', session.sessionId);
console.log('Client Secret:', session.clientSecret);

// Aguarde a conclusão (server-side polling)
const result = await client.signingSessions.waitForCompletion(session.sessionId);
console.log('Status:', result.status); // COMPLETED
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='CLICK_ONLY'),
    signer=Signer(name='João Silva', email='joao@example.com', user_external_id='user-001'),
    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)  # COMPLETED
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: signdocs.PolicyProfileClickOnly},
    Signer:           signdocs.Signer{Name: "João Silva", Email: "joao@example.com", UserExternalID: "user-001"},
    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)

result, err := client.SigningSessions.WaitForCompletion(ctx, session.SessionID)
if err != nil { log.Fatal(err) }
fmt.Println("Status:", result.Status)       // COMPLETED
fmt.Println("Evidence ID:", result.EvidenceID)
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Base64;

String pdfBase64 = Base64.getEncoder().encodeToString(Files.readAllBytes(Path.of("contrato.pdf")));

CreateSigningSessionRequest request = new CreateSigningSessionRequest();
request.purpose = "DOCUMENT_SIGNATURE";
request.policy = new Policy("CLICK_ONLY");
request.signer = new Signer("João Silva", "joao@example.com", "user-001");
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);
System.out.println("Session ID: " + session.sessionId);
System.out.println("Client Secret: " + session.clientSecret);

SigningSessionStatusResponse result = client.signingSessions().waitForCompletion(session.sessionId);
System.out.println("Status: " + result.status);       // COMPLETED
System.out.println("Evidence ID: " + result.evidenceId);
$pdfBase64 = base64_encode(file_get_contents('contrato.pdf'));

$session = $client->signingSessions->create(new CreateSigningSessionRequest(
    purpose: 'DOCUMENT_SIGNATURE',
    policy: new Policy(profile: 'CLICK_ONLY'),
    signer: new Signer(name: 'João Silva', email: 'joao@example.com', userExternalId: 'user-001'),
    document: ['content' => $pdfBase64, 'filename' => 'contrato.pdf'],
    returnUrl: 'https://app.example.com/done',
    locale: 'pt-BR',
    expiresInMinutes: 60,
));

echo "Session ID: " . $session->sessionId . "\n";
echo "Client Secret: " . $session->clientSecret . "\n";

$result = $client->signingSessions->waitForCompletion($session->sessionId);
echo "Status: " . $result->status . "\n";       // COMPLETED
echo "Evidence ID: " . $result->evidenceId . "\n";
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 = "CLICK_ONLY" },
    Signer = new Signer { Name = "João Silva", Email = "joao@example.com", UserExternalId = "user-001" },
    Document = new InlineDocument { Content = pdfBase64, Filename = "contrato.pdf" },
    ReturnUrl = "https://app.example.com/done",
    Locale = "pt-BR",
    ExpiresInMinutes = 60,
});

Console.WriteLine($"Session ID: {session.SessionId}");
Console.WriteLine($"Client Secret: {session.ClientSecret}");

var result = await client.SigningSessions.WaitForCompletionAsync(session.SessionId);
Console.WriteLine($"Status: {result.Status}");       // COMPLETED
Console.WriteLine($"Evidence ID: {result.EvidenceId}");

4. Experiência do signatário

O signatário vê o PDF e um botão "Aceitar". Um clique e a assinatura é concluída.

A página hospedada exibe o documento em um visualizador PDF embutido. Ao clicar em "Aceitar", a sessão é finalizada automaticamente e o signatário é redirecionado para a returnUrl configurada.


5. Alternativa programática (headless)

Para fluxos automatizados ou server-to-server. Crie a sessão e avance via API — sem frontend.

const session = await client.signingSessions.create({
  purpose: 'DOCUMENT_SIGNATURE',
  policy: { profile: 'CLICK_ONLY' },
  signer: { name: 'João Silva', email: 'joao@example.com', userExternalId: 'user-001' },
  document: { content: pdfBase64, filename: 'contrato.pdf' },
});

// Avançar: aceitar o documento
const result = await fetch(`${process.env.SIGNDOCS_BASE_URL}/v1/signing-sessions/${session.sessionId}/advance`, {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${session.clientSecret}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ action: 'accept' }),
});
const body = await result.json();
console.log('Status:', body.status); // COMPLETED
console.log('Evidence ID:', body.evidenceId);
import requests

session = client.signing_sessions.create(CreateSigningSessionRequest(
    purpose='DOCUMENT_SIGNATURE',
    policy=Policy(profile='CLICK_ONLY'),
    signer=Signer(name='João Silva', email='joao@example.com', user_external_id='user-001'),
    document=InlineDocument(content=pdf_base64, filename='contrato.pdf'),
))

result = requests.post(
    f"{os.environ['SIGNDOCS_BASE_URL']}/v1/signing-sessions/{session.session_id}/advance",
    headers={'Authorization': f'Bearer {session.client_secret}', 'Content-Type': 'application/json'},
    json={'action': 'accept'},
)
body = result.json()
print('Status:', body['status'])       # COMPLETED
print('Evidence ID:', body['evidenceId'])
session, err := client.SigningSessions.Create(ctx, &signdocs.CreateSigningSessionRequest{
    Purpose:  signdocs.PurposeDocumentSignature,
    Policy:   signdocs.Policy{Profile: signdocs.PolicyProfileClickOnly},
    Signer:   signdocs.Signer{Name: "João Silva", Email: "joao@example.com", UserExternalID: "user-001"},
    Document: &signdocs.DocumentInline{Content: pdfBase64, Filename: "contrato.pdf"},
})
if err != nil { log.Fatal(err) }

advanceBody, _ := json.Marshal(map[string]string{"action": "accept"})
req, _ := http.NewRequest("POST",
    fmt.Sprintf("%s/v1/signing-sessions/%s/advance", os.Getenv("SIGNDOCS_BASE_URL"), session.SessionID),
    bytes.NewReader(advanceBody))
req.Header.Set("Authorization", "Bearer "+session.ClientSecret)
req.Header.Set("Content-Type", "application/json")
resp, _ := http.DefaultClient.Do(req)
var body map[string]interface{}
json.NewDecoder(resp.Body).Decode(&body)
fmt.Println("Status:", body["status"])       // COMPLETED
fmt.Println("Evidence ID:", body["evidenceId"])
SigningSession session = client.signingSessions().create(request); // (ver hosted acima)

HttpClient http = HttpClient.newHttpClient();
HttpRequest advanceReq = HttpRequest.newBuilder()
    .uri(URI.create(System.getenv("SIGNDOCS_BASE_URL")
        + "/v1/signing-sessions/" + session.sessionId + "/advance"))
    .header("Authorization", "Bearer " + session.clientSecret)
    .header("Content-Type", "application/json")
    .POST(HttpRequest.BodyPublishers.ofString("{\"action\":\"accept\"}"))
    .build();
HttpResponse<String> resp = http.send(advanceReq, HttpResponse.BodyHandlers.ofString());
System.out.println(resp.body()); // {"status":"COMPLETED","evidenceId":"..."}
$session = $client->signingSessions->create(/* ... ver hosted acima ... */);

$ch = curl_init(getenv('SIGNDOCS_BASE_URL')
    . '/v1/signing-sessions/' . $session->sessionId . '/advance');
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . $session->clientSecret,
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode(['action' => 'accept']),
    CURLOPT_RETURNTRANSFER => true,
]);
$body = json_decode(curl_exec($ch));
echo "Status: " . $body->status . "\n";       // COMPLETED
echo "Evidence ID: " . $body->evidenceId . "\n";
var session = await client.SigningSessions.CreateAsync(/* ... ver hosted acima ... */);

using var http = new HttpClient();
http.DefaultRequestHeaders.Authorization =
    new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", session.ClientSecret);
var advanceRes = await http.PostAsync(
    $"{Environment.GetEnvironmentVariable("SIGNDOCS_BASE_URL")}/v1/signing-sessions/{session.SessionId}/advance",
    new StringContent("{\"action\":\"accept\"}", System.Text.Encoding.UTF8, "application/json"));
var body = await advanceRes.Content.ReadAsStringAsync();
Console.WriteLine(body); // {"status":"COMPLETED","evidenceId":"..."}

Total: 2 chamadas HTTP, sem frontend.


← Voltar para Visão Geral
Próximo: Aceite + OTP →
Receitas copy-paste →