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

Request Demo
Enhance Your eSignature Workflow with Customized SMS Notification using BoldSign API​

Enhance Your eSignature Workflow with Customized SMS Notification using BoldSign API

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.

Setting up the project

First, we create a project and install the necessary packages.

  1. Create an ASP.NET Core project.

        
    dotnet new webapp --framework "netcoreapp6.0" -o ASPCoreEsignApp
        
    
  2. 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
        
    
  3. Install the Twilio package for sending the SMS message.

        
    dotnet add package Twilio
        
    

Add BoldSign services through dependency injection

To communicate with the BoldSign API, you need to add authentication details such as headers and a base path to the HttpClient.

Include the following code in the ConfigureServices() method in your startup.cs file.
    
var apiClient = new ApiClient("https://api.boldsign.com/"," ***API Key***");
services.AddSingleton(apiClient);
services.AddSingleton(new DocumentClient(apiClient));
services.AddSingleton(new TemplateClient(apiClient));
    

Send a document for signing

You can initiate the signing process using the following code in your ASP.NET Core app. The code will create a document ID for the document to be signed. I have disabled the email sending process by setting the DisableEmails property in the SendForSign class since we are going to send the URL in an SMS message instead of email.

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);
}
    

Configure the webhook

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.

For my demonstration, I have subscribed to all the document events in BoldSign. The URL is https://mydomainname.com/home/webhook and the endpoint is webhook in the HomeController class.
SMS Webhook
The webhook endpoint will be triggered for the completion of all the subscribed events.

Build the document link and send SMS

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}");
    }

In the previous code, you can see that I am checking for the WebHookEventType.Sent event. Once I confirm the , I send the link to the signer.

Update the status for signature completion

Now that the signer has signed the document, we must return the signature completion status to the sender. To do this, I am using the same webhook post action in HomeController. In the following code, refer to the WebHookEventType.Completed event    
    
[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.

Multiple signers

To message multiple signers, you need to do the following:

  1. Add multiple DocumentSigner fields in the collection.

  2. Add separate signature fields for each signer.

  3. 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);

Update the webhook endpoint to handle multiple signers

To handle multiple signers, we have to make the following changes:

  1. Send the individual document links as SMS messages to all signers.

  2. Send an SMS message to the document sender when any of the signers complete the signing.

  3. Send an SMS message to the document sender when all the signers have completed signing.

All we need to do is update the endpoint to handle this. We are going to add the WebHookEventType.Signed event.

Send individual document links as SMS messages to all signers

In the following code snippet, I iterate the SignerDetails collection and send the signing links.  In the WebHookEventType.Signed event, I find out which signers have signed and update the document sender accordingly.
    
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)
        );
    }

Conclusion

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.

Share this blog

Subscribe RSS feed
Meikanda Nayanar

Meikanda Nayanar

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.

Share this blog

Meikanda Nayanar

Meikanda Nayanar

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.

Subscribe RSS feed

Leave a Reply

Your email address will not be published. Required fields are marked *