SDK C# (.NET)
Cliente oficial ForSign para .NET — do Framework 4.5 ao .NET 9.
Pacote ForSign.Sdk publicado no NuGet. Cobre o ciclo de vida completo de uma
operação — upload, criação, anexos, finalização e download — com tipagem
forte e suporte multi-target (Framework 4.5 → .NET 8).
Compatibilidade
- .NET 5, 6, 7, 8
- .NET Core 3.0+
- .NET Standard 2.0
- .NET Framework 4.5 → 4.8.1
Instalação
dotnet add package ForSign.SdkInstall-Package ForSign.Sdk<PackageReference Include="ForSign.Sdk" Version="2.0.11" />Configurando o cliente
O construtor padrão usa um HttpClient estático compartilhado — recomendado para
a maioria dos cenários. Em ambientes com IHttpClientFactory (ASP.NET Core),
passe sua própria instância.
using ForSign.Sdk;
// Padrão — HttpClient estático interno
var client = new ForSignClient();
// Ou com IHttpClientFactory (ASP.NET Core)
var client = new ForSignClient(httpClientFactory.CreateClient("forsign"));
// Credenciais via API Key
client.SetCredential(new ApiKeyCredential(
Environment.GetEnvironmentVariable("FORSIGN_API_KEY")!));A BaseUrl é fixa em https://api.forsign.digital — não há override exposto pelo
SDK. Para ambientes de staging entre em contato com o suporte. Nunca hardcode a
API key: use variáveis de ambiente, dotnet user-secrets ou Azure Key Vault.
Métodos disponíveis
Também: SetOperationManualCompletionAsync, SetOperationAutomaticCompletionAsync.
1. Upload + criação da operação
using ForSign.Sdk;
using ForSign.Sdk.DataTransferObjects;
using ForSign.Sdk.Requests;
var client = new ForSignClient();
client.SetCredential(new ApiKeyCredential(apiKey));
// Upload — três fontes suportadas
var fileReq = await UploadFileRequest.AddFileFromUrlAsync(
"https://exemplo.com/contrato.pdf", "contrato.pdf");
// ou: UploadFileRequest.AddFileFromPath("./contrato.pdf")
// ou: UploadFileRequest.AddFileFromBytes(pdfBytes, "contrato.pdf")
var upload = await client.UploadFileAsync(fileReq);
var fileInfo = new FileInformation(upload.Data.Id, upload.Data.FileName);
// Assinante com 2FA por email e posicionamento por coordenadas
var signer = new Signer
{
Name = "João Silva",
Email = "[email protected]",
Phone = "11987654321",
NotificationType = new EmailNotification("[email protected]"),
DoubleAuthenticationMethod = new EmailDoubleAuthentication("[email protected]"),
SignatureType = new DefaultSignatureType(SignatureType.UserChoice),
};
signer.AddSignatureInPosition(fileInfo, page: 1, x: "70%", y: "80%");
// Posicionamento alternativo via tag (procura `{{assinatura_cliente}}` no PDF)
// signer.SetTagSignaturePosition(new TagPosition(fileInfo, "assinatura_cliente"));
var operation = OperationRequestBuilder
.InitializeWithName("Contrato de prestação de serviços")
.SetLanguage(Language.Portuguese)
.SetExpirationDate(DateTime.UtcNow.AddDays(15))
.WithExternalId("CRM-12345")
.WithRedirectUrl("https://app.exemplo.com/sucesso/{operationId}")
.AddSigner(signer)
.Build();
var response = await client.CreateOperationAsync(operation);
foreach (var member in response.Members)
{
Console.WriteLine($"{member.Name}: {member.SignUrl}");
Console.WriteLine($"URL curta: {member.ShortenedSignatureUrl}");
}2. Aprovar (ou rejeitar) anexos
Depois que o assinante envia documentos solicitados, sua aplicação pode
inspecioná-los e decidir. O memberId vem de response.Members[i].Id ou do
webhook AttachmentFilled.
var attachments = await client.GetMemberAttachmentsAsync(memberId);
// Aprovar todos os anexos enviados
var ids = attachments
.Where(a => a.IsUploaded)
.Select(a => a.Id)
.ToList();
await client.ApproveAttachmentsAsync(memberId, ids);
// Rejeitar com motivo (motivo é obrigatório por anexo)
var rejected = new List<RejectedAttachment>
{
new() { Id = 4321, Reason = "Documento ilegível, reenvie em alta resolução" },
};
await client.RejectAttachmentsAsync(memberId, rejected);3. Download após a operação concluída
DownloadOperationZipAsync retorna o PDF assinado + a trilha de auditoria
empacotados em ZIP (Base64). Use os helpers para evitar manipular Base64
manualmente.
var zip = await client.DownloadOperationZipAsync(operationId);
// Helper: salva direto em diretório usando o nome sugerido pela API
var path = zip.SaveToDirectory("./downloads");
// Ou em bytes
byte[] bytes = zip.GetZipBytes();
// Anexos individuais
var file = await client.DownloadAttachmentAsync(attachmentId);
File.WriteAllBytes(file.FileName, file.Content);Tratamento de erros
Todos os métodos lançam ForSignApiException em respostas HTTP de erro. A
exceção carrega StatusCode (HttpStatusCode) e ErrorResponse com a lista
de validações por campo.
using ForSign.Sdk.Exceptions;
try
{
await client.CreateOperationAsync(operation);
}
catch (ForSignApiException ex) when (ex.StatusCode == HttpStatusCode.PaymentRequired)
{
// 402 — créditos insuficientes na conta
}
catch (ForSignApiException ex)
{
Console.WriteLine($"{(int)ex.StatusCode} {ex.StatusCode}: {ex.Message}");
if (ex.ErrorResponse?.Messages is { } messages)
{
foreach (var m in messages)
Console.WriteLine($" {m.Key}: {m.Value}");
}
}Códigos comuns: 401 (API key inválida), 402 (sem créditos), 403 (sem permissão),
404 (operação/membro não encontrado), 422 (validação).
Headers automáticos
O SDK adiciona em toda requisição: X-Api-Key, X-Client-Version, X-Correlation-Id
(GUID por instância do cliente) e User-Agent: ForSign.Sdk/{versão}. Útil para
rastrear chamadas no painel da ForSign.
Versões
- 2.0.11 —
ShortenedSignatureUrlexposto emOperationCreatedResponseMember - 2.0.9 — User-Agent passa a incluir nome e versão do SDK
- 2.0.8 — corrige deserialização de
GetMemberAttachmentsAsync, parsing de coordenadas decimais em locale pt-BR, e validação de download de URLs com erro HTTP
Release notes completas no NuGet.