Clicksign.NET 0.1.5

dotnet add package Clicksign.NET --version 0.1.5
                    
NuGet\Install-Package Clicksign.NET -Version 0.1.5
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Clicksign.NET" Version="0.1.5" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Clicksign.NET" Version="0.1.5" />
                    
Directory.Packages.props
<PackageReference Include="Clicksign.NET" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Clicksign.NET --version 0.1.5
                    
#r "nuget: Clicksign.NET, 0.1.5"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Clicksign.NET@0.1.5
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Clicksign.NET&version=0.1.5
                    
Install as a Cake Addin
#tool nuget:?package=Clicksign.NET&version=0.1.5
                    
Install as a Cake Tool

Clicksign .NET SDK

NuGet CI .NET licença documentação API v3

Cliente .NET para a Clicksign API v3 (JSON:API). Requer .NET 8+, zero dependências de runtime — apenas System.Net.Http (stdlib).


Índice


Fluxo completo: docs/WORKFLOW.md — envelope → documento → signatário → requisitos → ativação passo a passo.

Exemplos: docs/examples/ — exemplos prontos para retry, bulk, webhooks, multi-conta e limitações de produção.

Contrato do SDK: docs/SDK_CONTRACT.md — timeouts, retry, JSON:API, erros e paginação.

Observabilidade: docs/OBSERVABILITY.md — hooks, MEL, OpenTelemetry, métricas.


Instalação

dotnet add package Clicksign.NET

Ou via NuGet Package Manager:

Install-Package Clicksign.NET

Configuração

using Clicksign;

var client = new ClicksignClient(new ClicksignClientOptions
{
    ApiKey      = Environment.GetEnvironmentVariable("CLICKSIGN_API_KEY")!,
    Environment = ClicksignEnvironment.Sandbox,
    MaxRetries  = 3,
    ConnectTimeout = TimeSpan.FromSeconds(2),
    ReadTimeout    = TimeSpan.FromSeconds(10),
});
Opção Tipo Padrão Descrição
ApiKey string — Access token (obrigatório)
Environment string Production Define URL base
BaseUrl string? null Sobrescreve URL (WireMock, proxy, testes)
ConnectTimeout TimeSpan 2s Timeout de conexão TCP
ReadTimeout TimeSpan 10s Timeout de leitura da resposta
MaxRetries int 0 Retentativas em erros retryable

Segurança: nunca commite tokens. Use variáveis de ambiente, IConfiguration ou secret manager.


Início rápido

using Clicksign;
using Clicksign.Resources.Notarial;
using Clicksign.Types;

var client = new ClicksignClient(new ClicksignClientOptions
{
    ApiKey      = Environment.GetEnvironmentVariable("CLICKSIGN_API_KEY")!,
    Environment = ClicksignEnvironment.Sandbox,
});

// Criar envelope
var envelope = await client.Envelopes.CreateAsync(new EnvelopeCreateParams
{
    Name      = "Contrato de prestação de serviços",
    AutoClose = true,
});

// Adicionar documento
var document = await client.Documents.CreateAsync(new DocumentCreateParams
{
    EnvelopeId    = envelope.Id,
    Filename      = "contrato.pdf",
    ContentBase64 = Convert.ToBase64String(File.ReadAllBytes("contrato.pdf")),
});

// Adicionar signatário
var signer = await client.Signers.CreateAsync(new SignerCreateParams
{
    EnvelopeId = envelope.Id,
    Name       = "João Silva",
    Email      = "joao@example.com",
});

// Requisitos em lote (atômico)
await client.BulkRequirements.CreateAsync(envelope.Id, ops => ops
    .AddAgree(signer.Id, document.Id, RequirementRole.Sign)
    .AddProvideEvidence(signer.Id, document.Id, RequirementAuth.Email));

// Ativar (internamente usa PATCH /envelopes/{id} com status=running)
await client.Envelopes.ActivateAsync(envelope.Id);

Fluxo de assinatura (notarial)

1. Envelope

var envelope = await client.Envelopes.CreateAsync(new EnvelopeCreateParams
{
    Name       = "Proposta comercial #1042",
    AutoClose  = true,
    DeadlineAt = DateTimeOffset.UtcNow.AddDays(30),
});

2. Documento

Envie o PDF em Base64 ou a partir de um template:

// Upload Base64
var document = await client.Documents.CreateAsync(new DocumentCreateParams
{
    EnvelopeId    = envelope.Id,
    Filename      = "contrato.pdf",
    ContentBase64 = Convert.ToBase64String(File.ReadAllBytes("contrato.pdf")),
});

// A partir de template (.doc/.docx)
var fromTemplate = await client.Documents.CreateAsync(new DocumentCreateParams
{
    EnvelopeId = envelope.Id,
    Filename   = "contrato.docx",
    Template   = new DocumentTemplate
    {
        Id     = "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
        Fields = new Dictionary<string, string> { ["nome_cliente"] = "Empresa XYZ" },
    },
});

3. Signatário

var signer = await client.Signers.CreateAsync(new SignerCreateParams
{
    EnvelopeId   = envelope.Id,
    Name         = "Maria Silva",
    Email        = "maria@example.com",
    PhoneNumber  = "11999998888",
    CommunicateEvents = new CommunicateEvents
    {
        SignatureRequest  = NotificationChannel.Email,
        SignatureReminder = NotificationChannel.WhatsApp,
    },
});

Assinatura presencial — configure SignatureHost:

var signer = await client.Signers.CreateAsync(new SignerCreateParams
{
    EnvelopeId = envelope.Id,
    Name       = "João Silva",
    Email      = "joao@example.com",
    SignatureHost = new SignatureHost
    {
        Name  = "Maria Recepcionista",
        Email = "maria@empresa.com",
        CommunicateEvents = new CommunicateEvents
        {
            SignatureRequest = NotificationChannel.Email,
        },
    },
});

4. Requisitos de assinatura

Pré-requisito para ativar: ao menos um Agree (com Role) e um ProvideEvidence (com Auth) por par signatário/documento.

4.1 Endpoint padrão (um por chamada)
// Concordância
await client.Requirements.CreateAsync(new RequirementCreateParams
{
    EnvelopeId = envelope.Id,
    Action     = RequirementAction.Agree,
    Role       = RequirementRole.Sign,
    SignerId   = signer.Id,
    DocumentId = document.Id,
});

// Autenticação
await client.Requirements.CreateAsync(new RequirementCreateParams
{
    EnvelopeId = envelope.Id,
    Action     = RequirementAction.ProvideEvidence,
    Auth       = RequirementAuth.Email,
    SignerId   = signer.Id,
    DocumentId = document.Id,
});
4.2 Bulk atômico (múltiplos em uma chamada)
var response = await client.BulkRequirements.CreateAsync(envelope.Id, ops => ops
    .AddAgree(signer.Id, document.Id, RequirementRole.Sign)
    .AddProvideEvidence(signer.Id, document.Id, RequirementAuth.Email)
    .AddRubricate(signer.Id, document.Id, RubricateKind.Initials));

if (!response.IsSuccess)
{
    foreach (var failure in response.Failures)
        Console.Error.WriteLine($"slot {failure.Index}: {string.Join(", ", failure.Errors)}");
}
Abordagem Endpoint Quando usar
4.1 Padrão /requirements Criar requisitos um a um
4.2 Bulk /bulk_requirements Múltiplas ações; tratar sucesso/falha por slot

5. Ativar o envelope

Nota: O endpoint POST /envelopes/{id}/activate ainda não está disponível na API v3. ActivateAsync usa internamente PATCH /envelopes/{id} com status: running.

await client.Envelopes.ActivateAsync(envelope.Id);

// Equivalente via PATCH
await client.Envelopes.UpdateAsync(envelope.Id, new EnvelopeUpdateParams
{
    Status = EnvelopeStatus.Running,
});

6. Notificar signatários

// Todos
await client.Envelopes.NotifyAllAsync(envelope.Id, new NotificationParams
{
    Message            = "Por favor, assine o documento pendente.",
    EmailCustomization = new EmailCustomization { Subject = "Assinatura pendente" },
});

// Signatário específico
await client.Signers.NotifyAsync(signer.Id, envelope.Id, new NotificationParams
{
    Message = "Sua vez de assinar.",
});

7. Monitorar eventos

var events = await client.Events.ListForEnvelopeAsync(envelope.Id);
foreach (var evt in events)
    Console.WriteLine($"{evt.Name} @ {evt.CreatedAt}");

var docEvents = await client.Documents.ListEventsAsync(document.Id, envelope.Id);

Filtros, ordenação e paginação

// Uma página com filtros
var page = await client.Envelopes.Filter()
    .Where("status", "draft")
    .OrderBy("-created_at")
    .Page(1).PerPage(20)
    .FetchAsync();

// Todas as páginas (segue links.next)
var all = await client.Envelopes.Filter()
    .Where("status", "running")
    .FetchAllAsync();

// Filtro em sub-resource
var docs = await client.Documents.Filter(envelope.Id)
    .Where("status", "completed")
    .FetchAsync();

ResourceQuery<T> está disponível em Envelopes, Documents, Signers, Requirements, Memberships e AcceptanceTermWhatsapps via .Filter().


Outros recursos

ClicksignClient Resource Operações
Envelopes Envelope CRUD, Activate, NotifyAll, Filter
Documents Document CRUD, ListEvents, Filter
Signers Signer list, get, create, delete, Notify, Filter
Requirements Requirement list, get, create, delete, Filter
BulkRequirements BulkRequirement CreateAsync (atomic ops)
SignatureWatchers SignatureWatcher list, get, create, delete
Events Event ListForEnvelope, Create, CreateAddImage, CreateCustom
Webhooks Webhook CRUD
Folders Folder list, get, create
Users User list, get, Me, create
Templates Template CRUD, ListTemplateFields
TemplateFields TemplateField list, update, delete
Memberships Membership CRUD (update via PUT), Filter
Groups Group CRUD, AddUsers, RemoveUsers
AccessControlLists AccessControlList Create, Destroy
EnvelopeBulkCreations EnvelopeBulkCreation Create (job assíncrono)
AcceptanceTermWhatsapps AcceptanceTermWhatsapp list, CRUD, Cancel, Filter
AutoSignatureTerms AutoSignatureTerm get, create

Mapa completo de endpoints: docs/SPEC.md.


Tratamento de erros

Todos os erros HTTP lançam exceções que herdam de ClicksignException:

HTTP Exceção IsRetryable
401, 403 ClicksignAuthenticationException não
404 ClicksignNotFoundException não
400, 422 ClicksignValidationException não
409 ClicksignConflictException não
429 ClicksignRateLimitException sim
503 ClicksignServiceUnavailableException sim
5xx ClicksignServerException sim
Timeout ClicksignTimeoutException sim
using Clicksign.Errors;

try
{
    await client.Envelopes.GetAsync("id-inexistente");
}
catch (ClicksignNotFoundException e)
{
    Console.Error.WriteLine($"request_id={e.RequestId} body={e.ResponseBody}");
}
catch (ClicksignValidationException e)
{
    Console.Error.WriteLine($"status={e.StatusCode} body={e.ResponseBody}");
}
catch (ClicksignRateLimitException e)
{
    if (e.RetryAfter.HasValue)
        await Task.Delay(e.RetryAfter.Value);
}
catch (ClicksignException e)
{
    Console.Error.WriteLine(e.Message);
}

Propriedades comuns: StatusCode, RequestId (header x-request-id), ResponseBody, IsRetryable.

Guia detalhado: docs/TROUBLESHOOTING.md.


Ambientes

Constante URL base
ClicksignEnvironment.Sandbox https://sandbox.clicksign.com/api/v3
ClicksignEnvironment.Production https://app.clicksign.com/api/v3

O padrão é produção. Para desenvolvimento use Sandbox. Gere tokens no painel do ambiente correspondente.


Timeouts, retry e instrumentação

Retry automático

Com MaxRetries > 0, o SDK reenvia automaticamente em erros transitórios (429, 503, 5xx, timeout) com backoff exponencial full-jitter:

ceiling = min(0.5 × 2^(attempt−1), 30)s   espera em [0, ceiling)

Em 429/503 com header Retry-After, o SDK respeita o tempo indicado.

Hooks de instrumentação

var client = new ClicksignClient(new ClicksignClientOptions
{
    ApiKey     = apiKey,
    MaxRetries = 3,
    OnRequest = e => logger.LogInformation(
        "clicksign {Method} {Path} → {Status} ({Duration}ms tentativa {Attempt})",
        e.Method, e.Path, e.Status, (long)e.DurationMs, e.Attempt),
    OnRetry = e => logger.LogWarning(
        "clicksign retry {Attempt}/{MaxRetries} wait={Wait}ms error={Error}",
        e.Attempt, e.MaxRetries, e.WaitMs, e.Error.GetType().Name),
    OnError = e => logger.LogError(
        "clicksign failed {Method} {Path} status={Status}: {Message}",
        e.Method, e.Path, e.Status, e.Error.Message),
});

Detalhes e receitas para OpenTelemetry e System.Diagnostics.Metrics: docs/OBSERVABILITY.md.


Validação de webhook

using Clicksign.Webhook;

// Em ASP.NET Core
[HttpPost("/webhook")]
public async Task<IActionResult> Receive()
{
    Request.EnableBuffering();
    var payload   = await new StreamReader(Request.Body).ReadToEndAsync();
    var signature = Request.Headers["Content-HMAC"].ToString();
    var secret    = Environment.GetEnvironmentVariable("CLICKSIGN_WEBHOOK_SECRET")!;

    WebhookValidator.VerifySignature(payload, signature, secret); // lança se inválido
    // ...
    return Ok();
}

// Ou como bool
bool valid = WebhookValidator.IsValidSignature(payload, signature, secret);

Use sempre o corpo bruto da requisição — nunca re-serializar o JSON antes de validar.


ASP.NET Core e DI

// Program.cs
builder.Services.AddSingleton<ClicksignClient>(_ =>
    new ClicksignClient(new ClicksignClientOptions
    {
        ApiKey      = builder.Configuration["Clicksign:ApiKey"]!,
        Environment = ClicksignEnvironment.Production,
        MaxRetries  = 3,
    }));

// Controller / Service
public class EnvelopeService(ClicksignClient clicksign)
{
    public Task<Envelope> CreateAsync(string name, CancellationToken ct) =>
        clicksign.Envelopes.CreateAsync(new EnvelopeCreateParams { Name = name }, ct);
}

ClicksignClient é thread-safe após construção — registre sempre como singleton. Veja docs/ARCHITECTURE.md.


Limitações e produção

Tópico Detalhe
Async Todos os métodos de I/O são async/await — sem API síncrona exposta
Bulk retry Apenas timeout, não 5xx — operações atômicas não são idempotentes
Thread safety ClicksignClient imutável após construção; seguro para reuso entre threads
Multi-conta Uma instância por token — use múltiplas instâncias para múltiplas contas

Detalhes: docs/examples/08-production-limitations.md.


Desenvolvimento

dotnet test                                       # todos os testes
dotnet test --filter "FullyQualifiedName~Envelope"  # classe específica
dotnet format --verify-no-changes                 # lint
dotnet format                                     # formatar
dotnet build                                      # compilar
dotnet pack src/Clicksign --configuration Release --output ./dist  # gerar Clicksign.NET.*.nupkg

Licença

MIT — veja LICENSE.

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net8.0

    • No dependencies.
  • net9.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.1.5 181 6/4/2026
0.1.4 153 6/4/2026
0.1.3 153 6/3/2026
0.1.2 153 6/3/2026
0.1.1 153 6/3/2026