ForSign.Sdk
2.0.6
dotnet add package ForSign.Sdk --version 2.0.6
NuGet\Install-Package ForSign.Sdk -Version 2.0.6
<PackageReference Include="ForSign.Sdk" Version="2.0.6" />
<PackageVersion Include="ForSign.Sdk" Version="2.0.6" />
<PackageReference Include="ForSign.Sdk" />
paket add ForSign.Sdk --version 2.0.6
#r "nuget: ForSign.Sdk, 2.0.6"
#:package ForSign.Sdk@2.0.6
#addin nuget:?package=ForSign.Sdk&version=2.0.6
#tool nuget:?package=ForSign.Sdk&version=2.0.6
Documentação Completa do SDK ForSign para .NET
📢 Novidade v2.0.6: Suporte completo a todos os canais de notificação (Email, SMS, WhatsApp) e nova classe
NoNotificationpara desabilitar notificações explicitamente. O padrão agora é não enviar notificação quandoNotificationTypenão é definido.
🚀 Introdução
Bem-vindo à documentação oficial do SDK ForSign para .NET! Este SDK oferece integração simples e completa com a plataforma ForSign de assinaturas eletrônicas digitais.
Principais Funcionalidades
- Múltiplos Tipos de Assinatura: Clique, desenho, texto, escolha do usuário e carimbo automático
- Posicionamento Flexível: Use coordenadas fixas ou tags dinâmicas no PDF
- Segurança Avançada: Duplo fator de autenticação por e-mail e selfie
- Workflows Personalizáveis: Ordem de assinatura, assinatura presencial, finalização manual/automática
- Formulários Dinâmicos: Campos de texto, seleção e checkbox com validação
- Anexos Avançados: Controle de tipos de arquivo, quantidade e métodos de captura
- Gerenciamento Completo: CRUD de operações, anexos e configurações
- Múltiplos Idiomas: Português, Inglês e Espanhol
- Templates e Grupos: Reutilize configurações e organize operações
- Observers: Adicione participantes que apenas monitoram
📋 Índice
- Configuração Inicial
- Upload de Documentos
- Criação de Operações
- Tipos de Posicionamento
- Tipos de Assinatura
- Autenticação (2FA)
- Canais de Notificação
- Formulários Dinâmicos
- Anexos
- Gerenciamento de Operações
- Download de Documentos
- Configurações Avançadas
- Exemplos Completos
- Referência Rápida
🔧 Configuração Inicial
Requisitos
- .NET Framework 4.5+ ou .NET Core/Standard 2.0+
- .NET 5, 6, 7 ou 8
- API Key da ForSign (obtenha no painel de desenvolvedor)
Instalação via NuGet
dotnet add package ForSign.Sdk
Ou
Install-Package ForSign.Sdk
Configuração Básica
using ForSign.Sdk;
// 1. Criar cliente
var client = new ForSignClient();
// 2. Configurar credencial com sua API Key
const string API_KEY = "SUA_API_KEY_AQUI";
var credential = new ApiKeyCredential(API_KEY);
client.SetCredential(credential);
// Pronto! O SDK já está configurado e pronto para uso
Console.WriteLine("SDK configurado com sucesso!");
⚠️ Segurança: Nunca exponha sua API Key em código front-end ou repositórios públicos. Use variáveis de ambiente ou cofres de segredos.
📤 Upload de Documentos
A ForSign aceita apenas arquivos PDF com tamanho máximo de 10 MB.
Método 1: Upload de Arquivo Local
var fileRequest = UploadFileRequest.AddFileFromPath("/caminho/completo/documento.pdf");
var upload = await client.UploadFileAsync(fileRequest);
var fileInfo = new FileInformation(upload.Data.Id, upload.Data.FileName);
Método 2: Upload de URL
var fileRequest = await UploadFileRequest.AddFileFromUrlAsync(
"https://exemplo.com/documento.pdf",
"documento.pdf"
);
var upload = await client.UploadFileAsync(fileRequest);
var fileInfo = new FileInformation(upload.Data.Id, upload.Data.FileName);
Método 3: Upload de Bytes
byte[] pdfBytes = File.ReadAllBytes("documento.pdf");
var fileRequest = await UploadFileRequest.AddFileFromBytesAsync(pdfBytes, "documento.pdf");
var upload = await client.UploadFileAsync(fileRequest);
var fileInfo = new FileInformation(upload.Data.Id, upload.Data.FileName);
Método 4: Upload de Base64
string base64Content = "JVBERi0xLjQKJ..."; // Base64 do PDF
var fileRequest = await UploadFileRequest.AddFileFromBase64Async("documento.pdf", base64Content);
var upload = await client.UploadFileAsync(fileRequest);
var fileInfo = new FileInformation(upload.Data.Id, upload.Data.FileName);
Método 5: Upload de Stream
using var memoryStream = new MemoryStream(pdfBytes);
var fileRequest = await UploadFileRequest.AddFileFromStreamAsync(memoryStream, "documento.pdf");
var upload = await client.UploadFileAsync(fileRequest);
var fileInfo = new FileInformation(upload.Data.Id, upload.Data.FileName);
🏗️ Criação de Operações
Use o OperationRequestBuilder para construir operações de forma fluente:
var operation = OperationRequestBuilder
.InitializeWithName("Título da Operação")
.SetExpirationDate(DateTime.Now.AddDays(30))
.WithExternalId("MEU-ID-123")
.SetSignersOrderRequirement(true)
.SetInPersonSigning(false)
.SetLanguage(Language.Portuguese)
.SetDisplayCover(true)
.EnableMemberActionNotifications(true)
.WithOptionalMessage("Mensagem aos signatários")
.WithRedirectUrl("https://seusite.com/sucesso/{operationId}")
.AddSigner(signer1)
.AddSigner(signer2)
.AddObserver("Nome", "email@exemplo.com")
.AddToGroup(groupId)
.SetManualFinish(true)
.Build();
var response = await client.CreateOperationAsync(operation);
// Obter URLs de assinatura
foreach (var member in response.Members)
{
Console.WriteLine($"{member.Name}: {member.SignUrl}");
}
📍 Tipos de Posicionamento
Opção 1: Assinaturas com Tags (Dinâmico) ⭐ RECOMENDADO
Tags permitem posicionamento dinâmico baseado em marcadores no PDF.
Preparar o PDF
Adicione marcadores no formato {{nome_da_tag}} no seu PDF:
┌────────────────────────────────────┐
│ CONTRATO │
│ │
│ Assinatura: {{assinatura_cliente}}│
│ Rubrica: {{rubrica_cliente}} │
└────────────────────────────────────┘
Configurar no SDK
var signer = new Signer
{
Name = "João Silva",
Email = "joao@exemplo.com",
SignatureType = new DefaultSignatureType(SignatureType.UserChoice)
};
// Assinatura por tag
var signatureTag = new TagPosition(fileInfo, "assinatura_cliente");
signer.SetTagSignaturePosition(signatureTag);
// Rubrica por tag (opcional)
var rubricTag = new TagPosition(fileInfo, "rubrica_cliente");
signer.SetTagRubricPosition(rubricTag);
Regras para nomes de tags:
- ✅ Use apenas:
a-z,A-Z,0-9,-,_ - ❌ Não use: espaços, pontos, caracteres especiais
- Formato no PDF:
{{nome_da_tag}} - Regex de validação:
^[a-zA-Z0-9_-]+$
Quando usar tags:
- ✅ Documentos gerados dinamicamente
- ✅ PDFs com conteúdo variável
- ✅ Contratos onde layout pode mudar
- ✅ Múltiplas assinaturas em páginas diferentes
Opção 2: Assinaturas com Coordenadas (Fixo)
Para posicionamento preciso em templates com layout fixo:
var signer = new Signer
{
Name = "Maria Souza",
Email = "maria@exemplo.com",
SignatureType = new DefaultSignatureType(SignatureType.UserChoice)
};
// Formato: (arquivo, página, X%, Y%)
signer.AddSignatureInPosition(fileInfo, 1, "50%", "80%");
signer.AddSignatureInPosition(fileInfo, 2, "50%", "20%");
// Rubricas
signer.AddRubricInPosition(fileInfo, 1, "10%", "90%");
signer.AddRubricInPosition(fileInfo, 2, "10%", "90%");
Sistema de coordenadas:
- X:
0%(esquerda) a100%(direita) - Y:
0%(topo) a100%(fundo) - Sempre use formato percentual:
"50%","80%"
Quando usar coordenadas:
- ✅ Templates de formulários fixos
- ✅ PDFs sempre com mesmo layout
- ✅ Controle pixel-perfect da posição
- ✅ Documentos de página única
✍️ Tipos de Assinatura
1. Assinatura Padrão (Escolha do Usuário)
signer.SignatureType = new DefaultSignatureType(SignatureType.UserChoice);
// Usuário pode escolher entre desenhar, clicar ou digitar
Opções disponíveis:
SignatureType.UserChoice- Usuário escolhe o métodoSignatureType.Click- Assinatura com um cliqueSignatureType.Draw- Desenhar a assinaturaSignatureType.Text- Digitar o nome
2. Certificado Digital (ICP-Brasil)
signer.SignatureType = new CertificateSignatureType();
Assinatura com certificado digital ICP-Brasil. Oferece o mais alto nível de validade jurídica no Brasil, equivalente à assinatura física.
Características:
- ✅ Validade jurídica máxima (equiparada à assinatura manuscrita)
- ✅ Conformidade com ICP-Brasil
- ✅ Não-repúdio garantido
- ✅ Ideal para contratos de alto valor
Quando usar:
- Contratos que exigem validade jurídica máxima
- Transações financeiras e imobiliárias
- Documentos que serão apresentados em cartórios ou órgãos públicos
- Operações que exigem conformidade regulatória
3. Certificado em Nuvem
signer.SignatureType = new CloudCertificateSignatureType();
Assinatura com certificado digital armazenado na nuvem. Combina a segurança do certificado digital com a conveniência de acesso remoto.
Características:
- ✅ Validade jurídica equivalente ao certificado físico
- ✅ Acesso de qualquer dispositivo
- ✅ Não requer token físico ou cartão
- ✅ Processo de assinatura simplificado
Quando usar:
- Assinaturas remotas com validade jurídica
- Equipes distribuídas geograficamente
- Alto volume de assinaturas
- Processos digitais end-to-end
🔐 Autenticação Dois Fatores (2FA)
Opção 1: Email
signer.DoubleAuthenticationMethod = new EmailDoubleAuthentication("email@exemplo.com");
Um código de segurança será enviado para o email antes da assinatura.
Opção 2: SMS
signer.DoubleAuthenticationMethod = new SmsDoubleAuthentication("11987654321");
Um código de segurança será enviado via SMS para o telefone antes da assinatura.
Opção 3: WhatsApp
signer.DoubleAuthenticationMethod = new WhatsAppDoubleAuthentication("11987654321");
Um código de segurança será enviado via WhatsApp para o telefone antes da assinatura.
Fluxo do 2FA:
- Signatário acessa URL de assinatura
- Sistema solicita código (Email/SMS/WhatsApp)
- Após validação, libera assinatura
📢 Canais de Notificação
Configure como os signatários receberão as notificações:
Opção 1: Sem Notificação (Padrão)
// Opção 1: Não definir (padrão = sem notificação)
// signer.NotificationType permanece null
// Opção 2: Explicitamente sem notificação
signer.NotificationType = new NoNotification();
O signatário não receberá notificações automáticas. Use quando você mesmo irá enviar o link de assinatura.
Opção 2: Email
signer.NotificationType = new EmailNotification("email@exemplo.com");
O signatário receberá notificações por email.
Opção 3: SMS
signer.NotificationType = new SmsNotification("+5511987654321");
O signatário receberá notificações via SMS.
Nota: Use o formato internacional com código do país (+55 para Brasil).
Opção 4: WhatsApp
signer.NotificationType = new WhatsAppNotification("+5511987654321");
O signatário receberá notificações via WhatsApp.
Nota: Use o formato internacional com código do país (+55 para Brasil).
Resumo dos Canais
| Canal | Classe | Exemplo |
|---|---|---|
| Sem notificação | NoNotification ou null |
new NoNotification() |
EmailNotification |
new EmailNotification("email@ex.com") |
|
| SMS | SmsNotification |
new SmsNotification("+5511999999999") |
WhatsAppNotification |
new WhatsAppNotification("+5511999999999") |
Tipos de notificações enviadas:
- URL de assinatura
- Lembretes
- Status da operação
- Conclusão do processo
📝 Formulários Dinâmicos
Campo de Texto
var textField = TextFormField.WithName("Nome Completo")
.WithInstructions("Digite seu nome completo")
.IsRequired()
.WithMaxLength(100)
.WithTextFormat(FrontTypeFormField.Text)
.WithSize(2.5f, 25f) // altura, largura em %
.OnPosition(new FormFieldPosition(fileInfo, 1, "30%", "40%"))
.WithValue("Valor Padrão");
signer.AddFormField(textField);
Formatos de texto disponíveis:
FrontTypeFormField.Text- Texto livreFrontTypeFormField.Number- Apenas númerosFrontTypeFormField.Email- EmailFrontTypeFormField.Phone- TelefoneFrontTypeFormField.Date- Data (DD/MM/YYYY)FrontTypeFormField.DateUs- Data (MM/DD/YYYY)
Campo de Checkbox
var checkbox = CheckboxFormField.WithName("Aceito Termos")
.WithInstructions("Marque se aceita")
.IsRequired()
.WithOptions(new List<string> { "Aceito", "Não aceito" })
.WithSize(2.5f, 25f)
.OnPosition(new FormFieldPosition(fileInfo, 1, "20%", "30%"))
.WithValue("Aceito");
signer.AddFormField(checkbox);
Campo de Seleção (Dropdown)
var selectField = SelectFormField.WithName("Estado")
.WithInstructions("Selecione seu estado")
.IsRequired()
.WithOptions(new List<string> { "SP", "RJ", "MG", "RS" })
.WithSize(2.5f, 25f)
.OnPosition(new FormFieldPosition(fileInfo, 1, "40%", "50%"))
.WithValue("SP");
signer.AddFormField(selectField);
Título e Descrição do Formulário
signer.FormTitle = "Dados Cadastrais";
signer.FormDescription = "Preencha as informações abaixo para prosseguir";
📎 Anexos
Solicitar Anexos
var attachment = new Attachment(
"RG ou CNH",
"Envie foto do documento de identidade",
isRequired: true
);
// Tipos de arquivo permitidos
attachment.PermitFileType(AttachmentFileType.PNG);
attachment.PermitFileType(AttachmentFileType.JPEG);
attachment.PermitFileType(AttachmentFileType.JPG);
attachment.PermitFileType(AttachmentFileType.PDF);
attachment.PermitFileType(AttachmentFileType.DOC);
attachment.PermitFileType(AttachmentFileType.DOCX);
// Métodos de captura/envio
attachment.PermitAttachmentByInput(InputAttachmentType.CameraSideBack);
attachment.PermitAttachmentByInput(InputAttachmentType.CameraSideFront);
attachment.PermitAttachmentByInput(InputAttachmentType.UploadFile);
// Limitar quantidade de arquivos
attachment.MaxFilesAllowed = 2;
signer.RequestAttachment(attachment);
Tipos de input disponíveis:
InputAttachmentType.CameraSideBack- Câmera traseiraInputAttachmentType.CameraSideFront- Câmera frontal (selfie)InputAttachmentType.UploadFile- Upload de arquivo
Listar Anexos de um Membro
long memberId = 12345;
var attachments = await client.GetMemberAttachmentsAsync(memberId);
foreach (var att in attachments)
{
Console.WriteLine($"Anexo: {att.Name} - Enviado: {att.IsUploaded}");
}
Aprovar Anexos
long memberId = 12345;
var attachmentIds = new List<long> { 67890, 98765 };
await client.ApproveAttachmentsAsync(memberId, attachmentIds);
Rejeitar Anexos
long memberId = 12345;
var rejectedList = new List<RejectedAttachment>
{
new RejectedAttachment { Id = 67890, Reason = "Documento ilegível" },
new RejectedAttachment { Id = 98765, Reason = "Formato inválido" }
};
await client.RejectAttachmentsAsync(memberId, rejectedList);
Baixar Anexo
long attachmentId = 67890;
var download = await client.DownloadAttachmentAsync(attachmentId);
// Salvar arquivo
File.WriteAllBytes(download.FileName, download.Content);
Console.WriteLine($"ContentType: {download.ContentType}");
🔧 Gerenciamento de Operações
Finalizar Operação Manualmente
long operationId = 12345;
await client.CompleteOperationAsync(operationId);
Console.WriteLine("Operação finalizada!");
Nota: Todos os signatários obrigatórios devem ter assinado antes.
Cancelar Operação
long operationId = 12345;
await client.CancelOperationAsync(operationId, "Cancelamento solicitado pelo cliente");
Configurar Finalização Automática
long operationId = 12345;
DateTime endDate = DateTime.Now.AddDays(7);
await client.SetOperationAutomaticCompletionAsync(operationId, endDate);
Nota: A data deve ser pelo menos 1 hora no futuro.
Configurar Finalização Manual
long operationId = 12345;
await client.SetOperationManualCompletionAsync(operationId);
Isso altera uma operação de finalização automática para manual.
📥 Download de Documentos
Download do ZIP da Operação
long operationId = 12345;
var zipResponse = await client.DownloadOperationZipAsync(operationId);
O ZIP contém:
- Documento(s) assinado(s)
- Trilha de auditoria (audit trail)
- Anexos enviados pelos signatários
- Formulários preenchidos (CSV)
Forma 1: Converter Base64 Manualmente
byte[] zipBytes = Convert.FromBase64String(zipResponse.Base64File);
File.WriteAllBytes("operacao.zip", zipBytes);
Forma 2: Usar Método de Extensão (RECOMENDADO)
byte[] zipBytes = zipResponse.GetZipBytes();
File.WriteAllBytes("operacao.zip", zipBytes);
Forma 3: Salvar Diretamente em Arquivo
zipResponse.SaveToFile("/caminho/completo/arquivo.zip");
Forma 4: Salvar em Diretório (Nome Automático)
string savedPath = zipResponse.SaveToDirectory("/caminho/diretorio");
Console.WriteLine($"Arquivo salvo em: {savedPath}");
⚙️ Configurações Avançadas
1. Idioma da Interface
.SetLanguage(Language.Portuguese)
// Opções: Portuguese, English, Spanish
Define o idioma da interface de assinatura e notificações.
2. Exibir/Ocultar Capa Inicial
.SetDisplayCover(true) // ou false
A capa mostra informações da operação antes de iniciar.
3. Ordem de Assinatura
.SetSignersOrderRequirement(true)
true= signatários devem assinar na ordem adicionadafalse= podem assinar em qualquer ordem
4. Assinatura Presencial
.SetInPersonSigning(true)
true= todos assinam no mesmo dispositivo simultaneamentefalse= assinam remotamente
5. URL de Redirecionamento
.WithRedirectUrl("https://seusite.com/sucesso/{operationId}/{externalId}")
Parâmetros dinâmicos:
{operationId}- Substituído pelo ID da operação{externalId}- Substituído pelo ID externo (se definido)
Segurança: Sempre use HTTPS.
6. ID Externo
.WithExternalId("SEU-CODIGO-123")
Útil para correlacionar com seu sistema interno.
7. Adicionar a Grupos
.AddToGroup(groupId)
// ou adicionar a múltiplos grupos
.AddToGroups(new List<long> { group1, group2, group3 })
Organize operações em grupos para melhor gestão.
8. Adicionar Observadores
.AddObserver("Nome do Monitor", "monitor@empresa.com")
Observadores recebem notificações mas não precisam assinar.
9. Notificações de Ações dos Membros
.EnableMemberActionNotifications(true)
Receba notificações quando signatários:
- Visualizam o documento
- Completam assinatura
- Rejeitam documento
- Enviam formulários
10. Mensagem Opcional
.WithOptionalMessage("Por favor, revise e assine até o dia 30/01.")
Mensagem personalizada exibida aos signatários.
11. Finalização Manual
.SetManualFinish(true)
true= você deve chamarCompleteOperationAsync()para finalizarfalse= finaliza automaticamente quando todos assinarem
12. Data de Expiração
.SetExpirationDate(DateTime.Now.AddDays(30))
Após essa data, a operação expira se não for finalizada.
13. Metadados Personalizados
.AddMetadata("chave", "valor")
.AddMetadata("departamento", "vendas")
.AddMetadata("contrato_tipo", "locacao")
Adicione dados customizados à operação.
📚 Exemplos Completos
Exemplo 1: Contrato Simples com Tags
using ForSign.Sdk;
var client = new ForSignClient();
client.SetCredential(new ApiKeyCredential("SUA_API_KEY"));
// Upload do documento que contém {{assinatura_cliente}}
var fileRequest = await UploadFileRequest.AddFileFromUrlAsync(
"https://exemplo.com/contrato-tags.pdf",
"contrato.pdf"
);
var upload = await client.UploadFileAsync(fileRequest);
var fileInfo = new FileInformation(upload.Data.Id, upload.Data.FileName);
// Configurar signatário com tag
var signer = new Signer
{
Name = "João Cliente",
Email = "joao@cliente.com",
SignatureType = new DefaultSignatureType(SignatureType.UserChoice),
DoubleAuthenticationMethod = new EmailDoubleAuthentication("joao@cliente.com")
};
var signTag = new TagPosition(fileInfo, "assinatura_cliente");
signer.SetTagSignaturePosition(signTag);
// Criar operação
var operation = OperationRequestBuilder
.InitializeWithName("Contrato de Serviços - João")
.SetLanguage(Language.Portuguese)
.SetExpirationDate(DateTime.Now.AddDays(15))
.AddSigner(signer)
.Build();
var response = await client.CreateOperationAsync(operation);
Console.WriteLine($"URL: {response.Members[0].SignUrl}");
Exemplo 2: Workflow Completo com Formulários e Anexos
var client = new ForSignClient();
client.SetCredential(new ApiKeyCredential("SUA_API_KEY"));
// Upload
var upload = await client.UploadFileAsync(
await UploadFileRequest.AddFileFromUrlAsync(
"https://exemplo.com/cadastro.pdf",
"cadastro.pdf"
)
);
var fileInfo = new FileInformation(upload.Data.Id, upload.Data.FileName);
// Signatário com tudo
var signer = new Signer
{
Name = "Maria Silva",
Email = "maria@exemplo.com",
Phone = "11987654321",
SignatureType = new DefaultSignatureType(SignatureType.UserChoice),
DoubleAuthenticationMethod = new EmailDoubleAuthentication("maria@exemplo.com"),
FormTitle = "Dados Pessoais",
FormDescription = "Preencha suas informações"
};
// Assinatura
signer.AddSignatureInPosition(fileInfo, 1, "50%", "80%");
// Formulário - CPF
var cpfField = TextFormField.WithName("CPF")
.IsRequired()
.WithMaxLength(14)
.WithTextFormat(FrontTypeFormField.Number)
.OnPosition(new FormFieldPosition(fileInfo, 1, "30%", "40%"));
signer.AddFormField(cpfField);
// Formulário - Estado
var estadoField = SelectFormField.WithName("Estado")
.IsRequired()
.WithOptions(new List<string> { "SP", "RJ", "MG" })
.OnPosition(new FormFieldPosition(fileInfo, 1, "30%", "50%"));
signer.AddFormField(estadoField);
// Anexo - RG
var rg = new Attachment("RG", "Envie foto do RG", true);
rg.PermitFileType(AttachmentFileType.JPEG);
rg.PermitFileType(AttachmentFileType.PNG);
rg.PermitAttachmentByInput(InputAttachmentType.UploadFile);
signer.RequestAttachment(rg);
// Criar operação
var operation = OperationRequestBuilder
.InitializeWithName("Cadastro Completo - Maria")
.SetExpirationDate(DateTime.Now.AddDays(7))
.WithRedirectUrl("https://meusite.com/sucesso/{operationId}")
.SetLanguage(Language.Portuguese)
.AddSigner(signer)
.Build();
var response = await client.CreateOperationAsync(operation);
// Aguardar assinatura e anexos...
// Depois, baixar documentos
await Task.Delay(TimeSpan.FromMinutes(5)); // Simulando espera
var zip = await client.DownloadOperationZipAsync(response.Id);
zip.SaveToDirectory("./downloads");
Exemplo 3: Assinatura com Certificado Digital
var client = new ForSignClient();
client.SetCredential(new ApiKeyCredential("SUA_API_KEY"));
var upload = await client.UploadFileAsync(
await UploadFileRequest.AddFileFromUrlAsync(
"https://exemplo.com/contrato-alto-valor.pdf",
"contrato.pdf"
)
);
var fileInfo = new FileInformation(upload.Data.Id, upload.Data.FileName);
// Assinatura com Certificado Digital ICP-Brasil
var signerCertificado = new Signer
{
Name = "Dr. Ricardo Oliveira",
Email = "ricardo@oliveira.com",
SignatureType = new CertificateSignatureType(), // ← Certificado Digital
DoubleAuthenticationMethod = new EmailDoubleAuthentication("ricardo@oliveira.com")
};
signerCertificado.AddSignatureInPosition(fileInfo, 1, "50%", "70%");
// Assinatura com Certificado em Nuvem
var signerNuvem = new Signer
{
Name = "Ana Paula Santos",
Email = "ana@santos.com",
SignatureType = new CloudCertificateSignatureType(), // ← Certificado Nuvem
};
signerNuvem.AddSignatureInPosition(fileInfo, 1, "50%", "85%");
// Criar operação
var operation = OperationRequestBuilder
.InitializeWithName("Contrato com Certificado Digital")
.SetExpirationDate(DateTime.Now.AddDays(30))
.AddSigner(signerCertificado)
.AddSigner(signerNuvem)
.Build();
var response = await client.CreateOperationAsync(operation);
foreach (var member in response.Members)
{
Console.WriteLine($"{member.Name}: {member.SignUrl}");
}
Exemplo 4: Múltiplos Signatários com Ordem
var client = new ForSignClient();
client.SetCredential(new ApiKeyCredential("SUA_API_KEY"));
var upload = await client.UploadFileAsync(
await UploadFileRequest.AddFileFromUrlAsync(
"https://exemplo.com/contrato.pdf",
"contrato.pdf"
)
);
var fileInfo = new FileInformation(upload.Data.Id, upload.Data.FileName);
// Primeiro signatário: Empresa
var empresa = new Signer
{
Name = "Empresa XYZ Ltda",
Email = "contato@empresa.com",
SignatureType = new DefaultSignatureType(SignatureType.UserChoice)
};
empresa.AddSignatureInPosition(fileInfo, 1, "30%", "80%");
// Segundo signatário: Cliente
var cliente = new Signer
{
Name = "João Silva",
Email = "joao@silva.com",
SignatureType = new DefaultSignatureType(SignatureType.UserChoice),
DoubleAuthenticationMethod = new EmailDoubleAuthentication("joao@silva.com")
};
cliente.AddSignatureInPosition(fileInfo, 1, "70%", "80%");
// Operação com ordem de assinatura
var operation = OperationRequestBuilder
.InitializeWithName("Contrato Bilateral")
.SetSignersOrderRequirement(true) // Empresa assina primeiro
.SetExpirationDate(DateTime.Now.AddDays(30))
.AddSigner(empresa)
.AddSigner(cliente)
.Build();
var response = await client.CreateOperationAsync(operation);
foreach (var member in response.Members)
{
Console.WriteLine($"{member.Name}: {member.SignUrl}");
}
🚨 Tratamento de Erros
try
{
var response = await client.CreateOperationAsync(operation);
}
catch (ForSignApiException ex)
{
Console.WriteLine($"Erro da API ForSign: {ex.Message}");
Console.WriteLine($"Status Code: {ex.StatusCode}");
// Detalhes adicionais
if (ex.ErrorResponse?.Messages != null)
{
foreach (var msg in ex.ErrorResponse.Messages)
{
Console.WriteLine($" {msg.Key}: {msg.Value}");
}
}
}
catch (Exception ex)
{
Console.WriteLine($"Erro inesperado: {ex.Message}");
}
Códigos de status comuns:
400 Bad Request- Dados inválidos401 Unauthorized- API Key inválida402 Payment Required- Créditos insuficientes403 Forbidden- Sem permissão404 Not Found- Operação não encontrada500 Internal Server Error- Erro no servidor
📋 Referência Rápida
Tipos de Assinatura
SignatureType.UserChoice- Usuário escolheSignatureType.Click- CliqueSignatureType.Draw- DesenhoSignatureType.Text- TextoCertificateSignatureType- Certificado Digital (ICP-Brasil)CloudCertificateSignatureType- Certificado em Nuvem
Tipos de Formulário
TextFormField- Campo de textoSelectFormField- Lista de seleçãoCheckboxFormField- Checkbox
Formatos de Campo de Texto
FrontTypeFormField.Text- Texto livreFrontTypeFormField.Number- NúmeroFrontTypeFormField.Email- EmailFrontTypeFormField.Phone- TelefoneFrontTypeFormField.Date- Data (DD/MM/YYYY)FrontTypeFormField.DateUs- Data (MM/DD/YYYY)
Tipos de Arquivo para Anexos
AttachmentFileType.PNGAttachmentFileType.JPEGAttachmentFileType.JPGAttachmentFileType.PDFAttachmentFileType.DOCAttachmentFileType.DOCX
Métodos de Input de Anexos
InputAttachmentType.CameraSideBack- Câmera traseiraInputAttachmentType.CameraSideFront- Câmera frontalInputAttachmentType.UploadFile- Upload
Idiomas
Language.Portuguese- Português (pt-BR)Language.English- Inglês (en)Language.Spanish- Espanhol (es)
Canais de Notificação (Classes)
NoNotification- Sem notificação (padrão)EmailNotification- E-mailSmsNotification- SMSWhatsAppNotification- WhatsApp
Canais de Autenticação
AuthenticationChannel.Email- E-mailAuthenticationChannel.SMS- SMSAuthenticationChannel.WhatsApp- WhatsApp
⚠️ Regras e Limitações
Arquivos
- Formato: Apenas PDF
- Tamanho: Máximo 10 MB
Tags
- Formato:
{{nome_da_tag}} - Caracteres permitidos:
a-z,A-Z,0-9,-,_ - Não use: espaços, pontos, caracteres especiais
Coordenadas
- Formato: Sempre percentual (
"50%","80%") - X: 0% (esquerda) a 100% (direita)
- Y: 0% (topo) a 100% (fundo)
URLs de Redirecionamento
- Devem começar com
http://ouhttps:// - Parâmetros dinâmicos:
{operationId},{externalId} - Recomendado: sempre use HTTPS
🔐 Boas Práticas
Segurança
- Nunca exponha API Key em código front-end
- Use variáveis de ambiente ou cofres de segredos
- Sempre use HTTPS para redirect URLs
- Habilite 2FA para operações importantes
Performance
- Reutilize a mesma instância de
ForSignClient - Use upload por URL quando possível (evita tráfego)
- Configure timeouts adequados para operações longas
Confiabilidade
- Configure webhooks para atualizações em tempo real
- Sempre trate exceções
ForSignApiException - Use
ExternalIdpara correlação com seu sistema - Configure data de expiração adequada
UX
- Configure mensagens personalizadas
- Use redirect URLs para melhor experiência
- Escolha idioma adequado ao público
- Forneça instruções claras em formulários
🌐 Webhooks
A forma mais eficiente de monitorar operações é através de Webhooks.
Como funciona:
- Configure uma URL no painel de desenvolvedor
- ForSign enviará POST para essa URL em eventos importantes
- Sua aplicação recebe notificações em tempo real
Eventos comuns:
- Operação criada
- Signatário visualizou documento
- Signatário assinou
- Operação finalizada
- Operação cancelada
- Anexo enviado
Isso elimina necessidade de polling (consultar status repetidamente).
📞 Suporte
- Documentação da API: https://api.forsign.digital/docs
- Email: suporte@forsign.digital
- Issues: GitHub Issues
- Painel: Acesse o painel de desenvolvedor para obter API Key
📝 Changelog
v2.0.6 (2025-12-29)
- ✨ NOVO: Classe
NoNotificationpara desabilitar notificações explicitamente - ✨ NOVO: Suporte completo para
SmsNotification - ✨ NOVO: Suporte completo para
WhatsAppNotification - 🐛 FIX: Correção do mapeamento de NotificationType para NotificationChannel
- 🐛 FIX: SMS e WhatsApp agora são processados corretamente
- ⚠️ BREAKING: Padrão de notificação alterado de Email para None
- 📚 DOCS: Documentação de canais de notificação atualizada
v2.0.5
- 🔐 SDK agora usa apenas autenticação via API Key
- 🗑️ Removido suporte a JWT/Bearer token
- ⚡ Melhorias de performance
v2.0.4
- ✨ Certificado Digital (ICP-Brasil)
- ✨ Certificado em Nuvem
- ✨ SelfieDoubleAuthentication
v2.0.0
- Versão inicial pública do SDK
📄 Licença
Este projeto está licenciado sob a MIT License.
<p align="center"> <strong>Desenvolvido com ❤️ pela equipe ForSign</strong><br> <a href="https://forsign.digital">forsign.digital</a> </p>
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 is compatible. net5.0-windows was computed. net6.0 is compatible. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 is compatible. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. 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 was computed. 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. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 is compatible. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net45 is compatible. net451 is compatible. net452 is compatible. net46 is compatible. net461 is compatible. net462 is compatible. net463 was computed. net47 is compatible. net471 was computed. net472 is compatible. net48 is compatible. net481 is compatible. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETCoreApp 3.0
- Newtonsoft.Json (>= 13.0.3)
-
.NETFramework 4.5
- Newtonsoft.Json (>= 13.0.3)
- System.Net.Http (>= 4.3.4)
-
.NETFramework 4.5.1
- Newtonsoft.Json (>= 13.0.3)
- System.Net.Http (>= 4.3.4)
-
.NETFramework 4.5.2
- Newtonsoft.Json (>= 13.0.3)
- System.Net.Http (>= 4.3.4)
-
.NETFramework 4.6
- Newtonsoft.Json (>= 13.0.3)
- System.Net.Http (>= 4.3.4)
-
.NETFramework 4.6.1
- Newtonsoft.Json (>= 13.0.3)
- System.Net.Http (>= 4.3.4)
-
.NETFramework 4.6.2
- Newtonsoft.Json (>= 13.0.3)
- System.Net.Http (>= 4.3.4)
-
.NETFramework 4.7
- Newtonsoft.Json (>= 13.0.3)
- System.Net.Http (>= 4.3.4)
-
.NETFramework 4.7.2
- Newtonsoft.Json (>= 13.0.3)
- System.Net.Http (>= 4.3.4)
-
.NETFramework 4.8
- Newtonsoft.Json (>= 13.0.3)
- System.Net.Http (>= 4.3.4)
-
.NETFramework 4.8.1
- Newtonsoft.Json (>= 13.0.3)
- System.Net.Http (>= 4.3.4)
-
.NETStandard 2.0
- Newtonsoft.Json (>= 13.0.3)
-
net5.0
- Newtonsoft.Json (>= 13.0.3)
-
net6.0
- Newtonsoft.Json (>= 13.0.3)
-
net7.0
- Newtonsoft.Json (>= 13.0.3)
-
net8.0
- Newtonsoft.Json (>= 13.0.3)
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 |
|---|---|---|
| 2.0.6 | 89 | 12/29/2025 |
| 2.0.5 | 172 | 12/23/2025 |
| 2.0.4 | 269 | 12/18/2025 |
| 2.0.3 | 267 | 12/18/2025 |
| 2.0.2 | 277 | 9/19/2025 |
| 2.0.1 | 253 | 9/19/2025 |
| 2.0.0 | 248 | 9/19/2025 |
| 1.0.6 | 304 | 2/2/2024 |
| 1.0.5 | 191 | 1/26/2024 |
| 1.0.4 | 164 | 1/26/2024 |
| 1.0.3 | 178 | 1/19/2024 |
| 1.0.2 | 171 | 1/19/2024 |
| 1.0.1 | 174 | 1/18/2024 |
| 0.1.4 | 174 | 1/26/2024 |
Version 2.0.6 - Notification Channel Improvements
**New Features:**
- NoNotification: Explicit class to disable notifications for a signer
- SmsNotification: Full support for SMS notifications
- WhatsAppNotification: Full support for WhatsApp notifications
**Bug Fixes:**
- Fixed: NotificationType not being properly converted to NotificationChannel
- Fixed: SMS and WhatsApp notification types were not being processed
- Fixed: Default notification behavior now correctly defaults to None (no notification)
**Breaking Changes:**
- Default NotificationChannel changed from Email to None
- If you relied on automatic Email notifications without setting NotificationType,
you now need to explicitly set: signer.NotificationType = new EmailNotification("email@example.com")
**Migration Guide:**
- If you want NO notification: signer.NotificationType = null (or new NoNotification())
- If you want Email: signer.NotificationType = new EmailNotification("email@example.com")
- If you want SMS: signer.NotificationType = new SmsNotification("+5511999999999")
- If you want WhatsApp: signer.NotificationType = new WhatsAppNotification("+5511999999999")
For full documentation, visit: https://github.com/forsign/sdk-dotnet