
The Black Friday Deal for 2023 is live now. Get Flat 30% OFF on all plans!Learn More
Black Friday Deal - Flat 30% OFF! Learn More
Traditionally, when collecting eSignatures, signers receive documents via email. This requires them to access their email inbox, download the document, and then proceed with the signing process. However, in certain situations, such as time-sensitive agreements or when recipients have limited access to email, delivering the document through SMS becomes the preferred approach.
BoldSign allows users to send documents through SMS. To employ this feature, the document sender needs to have a third-party SMS service provider to send the message. In this blog, I demonstrate this feature using Twilio to send the SMS message. You can choose any other SMS service for your own needs.
Let’s get started.
First, we create a project and install the necessary packages.
Create an ASP.NET Core project.
dotnet new webapp --framework "netcoreapp6.0" -o ASPCoreEsignApp
Install the BoldSign.API package for creating, sending, and completing the eSignature contract. This package is the heart of the application.
dotnet add package BoldSign.Api
Install the Twilio package for sending the SMS message.
dotnet add package Twilio
To communicate with the BoldSign API, you need to add authentication details such as headers and a base path to the HttpClient.
var apiClient = new ApiClient("https://api.boldsign.com/"," ***API Key***");
services.AddSingleton(apiClient);
services.AddSingleton(new DocumentClient(apiClient));
services.AddSingleton(new TemplateClient(apiClient));
Refer to the following code example.
private readonly IDocumentClient documentClient;
private readonly ITemplateClient templateClient;
public IndexModel(IDocumentClient documentClient, ITemplateClient templateClient, ILogger logger)
{
this.documentClient = documentClient;
this.templateClient = templateClient;
}
public void SignDocument()
{
// Read the document from local path as stream.
using var fileStream = System.IO.File.OpenRead("doc-2.pdf");
var documentStream = new DocumentFileStream
{
ContentType = "application/pdf",
FileData = fileStream,
FileName = "doc.pdf",
};
// Creating collection with the loaded document.
var filesToUpload = new List<IDocumentFile>
{
documentStream,
};
// Creating signature field.
var signatureField = new FormField(
id: "Sign",
type: FieldType.Signature,
pageNumber: 1,
isRequired: true,
bounds: new Rectangle(x: 50, y: 50, width: 200, height: 30));
// Adding the field to the collection.
List<FormField> formFields = new List<FormField>();
formFields.Add(signatureField);
// Creating signer field.
var signer = new DocumentSigner(
name: "Signer Name 1",
emailAddress: "signer@cubeflakes.com",
signerOrder: 1,
authenticationCode: "851321",
signerType: SignerType.Signer,
privateMessage: "This is private message for signer",
// Assign the created form fields to the signer.
formFields: formFields);
// Adding the signer to the collection.
var documentSigners = new List<DocumentSigner>
{
signer
};
// Create send for sign request object.
var sendForSign = new SendForSign
{
Title = "Sent from API SDK",
Message = "This is document message sent from API SDK",
EnableSigningOrder = false,
// Assign the signers collection.
Signers = documentSigners,
// Assign the loaded files collection.
Files = filesToUpload,
// Disable sending the emails.
DisableEmails = true,
};
// Send the document for signing.
var createdDocumentResult = this.documentClient.SendDocument(sendForSign);
// Pass the document ID to build the URL for the Signer.
DocumentViewModel model = new DocumentViewModel()
{
DocumentId = createdDocumentResult.DocumentId,
};
return View(model);
}
So now we have assigned the document to the signer, but we have disabled the email sending process. The problem now is that we have to identify whether the document sending process has been completed by the BoldSign application without any errors so that we can initiate the SMS message to the signer.
To solve this problem, we rely on the webhooks of the BoldSign application. In them, we can subscribe to a variety of events like Sent, Signed, Completed, Declined, Revoked, Reassigned, Expired, and so on. The controller endpoint, , will trigger when the subscribed events are completed.
To learn more about how to create and configure the webhooks, check the BoldSign API documentation: Webhooks Introduction. You can create your own webhooks here – BoldSign API Webhooks.
We have configured the webhook endpoint, and in that endpoint I can now check whether the document sending process is completed as shown in the following code.
[HttpPost]
// Action for Webhook
public async Task<IActionResult> Webhook()
{
var sr = new StreamReader(this.Request.Body);
var json = await sr.ReadToEndAsync();
if (this.Request.Headers[WebhookUtility.BoldSignEventHeader] == "Verification")
{
return this.Ok();
}
var SECRET_KEY = "***SECRET_KEY***";
try
{
WebhookUtility.ValidateSignature(json, this.Request.Headers[WebhookUtility.BoldSignSignatureHeader], SECRET_KEY);
}
catch (BoldSignSignatureException ex)
{
Console.WriteLine(ex);
return this.Forbid();
}
var eventPayload = WebhookUtility.ParseEvent(json);
var doc = eventPayload.Data as DocumentEvent;
// Check whether the send evet is completed
if (eventPayload.Event.EventType == WebHookEventType.Sent)
{
var signerDetailsList = (eventPayload.Data as DocumentEvent)?.SignerDetails;
if (signerDetailsList != null)
{
this. SendLinkToSigner(doc.DocumentId, signerDetailsList[0].SignerEmail);
}
}
return this.Ok();
}
public async Task<IActionResult> SendLinkToSigner(string id, string signerEmail)
{
// Generate the embedded signing link
EmbeddedSigningLink embeddedSigningLink = await documentClient
.GetEmbeddedSignLinkAsync(id, signerEmail, DateTime.Now.AddDays(30),
"https://boldsign.com/").ConfigureAwait(false);
this.SendSmsToSigner(embeddedSigningLink.SignLink);
return this.Ok();
}
private async Task SendSmsToSigner(string signLink)
{
// Replace these with your actual Twilio credentials
string accountSid = "";
string authToken = "";
// Replace these with the phone numbers
string twilioNumber = "";
string recipientNumber = "";
// Initialize Twilio client
TwilioClient.Init(accountSid, authToken);
// Send SMS
var message = MessageResource.Create(
body: $"You can sign the document from this link: {signLink}",
from: new Twilio.Types.PhoneNumber(twilioNumber),
to: new Twilio.Types.PhoneNumber(recipientNumber)
);
Console.WriteLine($"Sent SMS to signer with link: {signLink}");
}
[HttpPost]
// Action for Webhook
public async Task<IActionResult> Webhook()
{
// Same code as above.
var eventPayload = WebhookUtility.ParseEvent(json);
var doc = eventPayload.Data as DocumentEvent;
// Check whether the send evet is completed
if (eventPayload.Event.EventType == WebHookEventType.Sent)
{
// Send the SMS to signer
}
else if (eventPayload.Event.EventType == WebHookEventType.Completed)
{
this.UpdateCompletionStatus();
}
return this.Ok();
}
private async Task UpdateCompletionStatus()
{
// Replace these with your actual Twilio credentials
string accountSid = "";
string authToken = "";
// Replace these with the phone numbers
string twilioNumber = "";
string recipientNumber = "";
// Initialize Twilio client
TwilioClient.Init(accountSid, authToken);
// Send SMS
var message = MessageResource.Create(
body: $"The document is signed successfully.",
from: new Twilio.Types.PhoneNumber(twilioNumber),
to: new Twilio.Types.PhoneNumber(recipientNumber)
);
}
This should work for the test case scenario for sending document via SMS.
If we want to extend the SMS feature, we can send the same document as an SMS message to multiple signers.
To message multiple signers, you need to do the following:
Add multiple DocumentSigner fields in the collection.
Add separate signature fields for each signer.
Specify the signing order. This is optional.
In the following sample code, I have added two signers.
// Creating signature field.
var signatureField1 = new FormField(
id: "Sign1",
type: FieldType.Signature,
pageNumber: 1,
isRequired: true,
bounds: new Rectangle(x: 50, y: 50, width: 200, height: 30));
// Creating signature field.
var signatureField2 = new FormField(
id: "Sign2",
type: FieldType.Signature,
pageNumber: 1,
isRequired: true,
bounds: new Rectangle(x: 150, y: 150, width: 200, height: 30));
// Creating signer field.
var signer1 = new DocumentSigner(
name: "Signer1",
emailAddress: "signer1@cubeflakes.com",
signerOrder: 1,
authenticationCode: "12345",
signerType: SignerType.Signer,
privateMessage: "This is private message for signer",
// Assign the created form fields to the signer.
formFields: new List<FormField>() {signatureField1});
// Create signer field
var signer2 = new DocumentSigner(
name: "Signer2",
emailAddress: "signer2@cubeflakes.com",
signerOrder: 2,
authenticationCode: "12345",
signerType: SignerType.Signer,
privateMessage: "This is private message for signer",
// Assign the created form fields to the signer.
formFields: new List<FormField>() {signatureField2});
// Adding the signer to the collection.
var documentSigners = new List<DocumentSigner>
{
signer1,
signer2
};
// Create send for sign request object.
var sendForSign = new SendForSign
{
Title = "Sent from API SDK",
Message = "This is document message sent from API SDK",
EnableSigningOrder = true,
// Assign the signers collection.
Signers = documentSigners,
// Assign the loaded files collection.
Files = filesToUpload,
DisableEmails = true,
};
// Send the document for signing.
var createdDocumentResult = documentClient.SendDocument(sendForSign);
To handle multiple signers, we have to make the following changes:
Send the individual document links as SMS messages to all signers.
Send an SMS message to the document sender when any of the signers complete the signing.
Send an SMS message to the document sender when all the signers have completed signing.
public async Task<IActionResult> Webhook()
{
var sr = new StreamReader(this.Request.Body);
var json = await sr.ReadToEndAsync();
if (this.Request.Headers[WebhookUtility.BoldSignEventHeader] == "Verification")
{
return this.Ok();
}
// TODO: Update your webhook secret key
var SECRET_KEY = "***SECRET_KEY***";
try
{
WebhookUtility.ValidateSignature(json, this.Request.Headers[WebhookUtility.BoldSignSignatureHeader],
SECRET_KEY);
}
catch (BoldSignSignatureException ex)
{
Console.WriteLine(ex);
return this.Forbid();
}
var eventPayload = WebhookUtility.ParseEvent(json);
var doc = eventPayload.Data as DocumentEvent;
switch (eventPayload.Event.EventType)
{
case WebHookEventType.Sent:
{
var signerDetailsList = (eventPayload.Data as DocumentEvent)?.SignerDetails;
if (signerDetailsList != null)
{
foreach (var signer in signerDetailsList)
{
this.SendLinkToSigner(doc.DocumentId, signer.SignerEmail);
}
}
break;
}
case WebHookEventType.Signed:
{
var signerList = (eventPayload.Data as DocumentEvent)?.SignerDetails;
if (signerList != null)
{
var signerDetail = signerList.Where(x=>x.Status == SignerStatus.Completed && x.LastActivityDate!=null).OrderByDescending(x=>x.LastActivityDate).FirstOrDefault();
if (signerDetail != null)
{
this.UpdateSignerStatus(signerDetail.SignerName);
}
}
break;
}
case WebHookEventType.Completed:
this.UpdateCompletionStatus();
break;
}
return this.Ok();
}
private async Task UpdateSignerStatus(string signerName)
{
// Replace these with your actual Twilio credentials
string accountSid = "";
string authToken = "";
// Replace these with the phone numbers
string twilioNumber = "";
string recipientNumber = "";
// Initialize Twilio client
TwilioClient.Init(accountSid, authToken);
// Send SMS
var message = MessageResource.Create(
body: $"Document was now signed by : { signerName }",
from: new Twilio.Types.PhoneNumber(twilioNumber),
to: new Twilio.Types.PhoneNumber(recipientNumber)
);
}
We hope this blog helps you handle eSignature requests in SMS messages instead of email. We would love to hear your feedback! Let us know how BoldSign has contributed to enhancing your development experience or workflows. If you have any suggestions or questions, please feel free to share them in the comments section below or reach out to us through our support portal.
A veteran product manager at BoldSign, boasting a decade-long journey as a .NET developer. With a rich history of leading product development across diverse technologies like Windows Forms, WPF, UWP, Xamarin.Forms, Flutter, and MAUI, Meikandan brings a unique blend of technical expertise and strategic insight to the table.
A veteran product manager at BoldSign, boasting a decade-long journey as a .NET developer. With a rich history of leading product development across diverse technologies like Windows Forms, WPF, UWP, Xamarin.Forms, Flutter, and MAUI, Meikandan brings a unique blend of technical expertise and strategic insight to the table.
Latest Articles
Best Black Friday Software Deals in 2023
Why BoldSign is a better Alternative to DocuSign