Lexion improves envelope visibility and contract repository completeness with DocuSign Connect

DocuSign Developer Lexion

“With DocuSign Recipient Connect, Lexion is able to ingest not only first-party documents, but third-party documents as well, which helps ensure that a customer’s contract repository is as complete as possible. Our DocuSign integration ensures that our customers have a single source of truth for all of their contracts and obligations with as little manual work as possible. That’s crucial for businesses and the lean legal teams that support them.”  — Paxton Wiers - Senior Product Marketing Manager, Lexion

Intro to Lexion

Lexion is a contract management system that helps businesses streamline and accelerate their contract management processes. It provides an AI-powered repository that keeps all of a company’s contracts in one place for easy search and organization. Lexion’s artificial intelligence (AI) technology scans contracts and extracts information such as dates, terms, parties, and more than 120+ clauses and terms. Armed with this information, Lexion can automatically organize and file contracts, send automatic email reminders for upcoming renewal dates, and generate reports for in-house legal teams and stakeholders in sales, procurement, finance, marketing, HR, and other teams. In addition to its AI repository, Lexion Workflow helps legal teams manage tasks related to the contract lifecycle including intake, redlining, and negotiation, and approval. Workflow works with email, meaning that when an internal collaborator outside of the legal team sends an email with a request for contract review, that email automatically becomes a task on Lexion's Dashboard. Stakeholders can continue collaborating from email, too. This enables members of the company to collaborate seamlessly with the legal team without having to change the way they work.

Of course, no contract is complete without a signature. In recent years, more and more businesses have moved away from printed contracts and towards electronic signatures. Before Lexion built their integration, many of their customers were already using DocuSign, making the integration a natural next step. With the DocuSign integration, Lexion’s users can send documents for signature directly from the associated task in Lexion. Contracts that have already been completed in the customer’s DocuSign account will appear in Lexion as well, saving users the headache of scanning and importing old printed documents, or compiling and manually uploading old electronic copies. Lexion users can also receive updates about the status of their contracts within the tasks without leaving the platform. As shown in Figure 1, when a user views a task in Lexion, they see all changes to the documents associated with that task, including the document’s status in real time, messages related to that task, information about who is collaborating on the document, and more.

A Lexion task showing updates to DocuSign envelopes

Figure 1: A Lexion task showing updates to DocuSign envelopes

Connecting with DocuSign

Lexion’s journey with DocuSign development began in 2021 when they became a DocuSign partner. To start building their first integration, they began at the DocuSign Developer Center, where they found the documentation needed to get up and running. In the rare cases where the Developer Center didn’t have what they needed, the developers referred to Stack Overflow, where they could get answers directly from DocuSign employees. In some instances, they even found the edge cases that they encountered documented on the DocuSign developer blog

Lexion’s developers built their integration with the DocuSign C# SDK using JSON Web Token (JWT) Grant authentication. They found the DocuSign go-live process (moving from development to production) to be surprisingly smooth and were able to migrate to production in less than two hours. Once the integration was live, Lexion users could send documents for signature without leaving the Lexion app. 

A key part of the original integration with DocuSign centered around polling to retrieve envelope statuses and reporting them in Lexion tasks. Users loved the updates on their contracts, but polling comes with its own unique challenges. DocuSign helps to prevent excessive network traffic by limiting polling in a few ways. First, DocuSign only allows GET requests to a given URL every 15 minutes. This means that if the API is used to retrieve the status of a specific envelope with the Envelopes:get endpoint, that same endpoint cannot be called again for that envelope for at least 15 minutes. Additionally, for all apps associated with a DocuSign account, the default maximum number of requests that can be made in an hour is 3,000. Frequent polling can quickly drive up the number of API calls made in an account. These limits meant that Lexion’s users weren’t able to receive instant status updates and could be left waiting for a notification on their envelope for up to 15 minutes after it was signed.

Strengthening the connection

Lexion was able to address DocuSign polling limitations with the DocuSign webhook notification feature, DocuSign Connect. Connect is a webhook service that enables your application to receive updates when specific triggering events occur in your eSignature workflows. After a year of maintaining their DocuSign integration with the polling solution, Lexion jumped at the chance to work with the DocuSign team to unlock more value for customers and improve their integration with Connect. Unlike polling, which requires that an application make calls to DocuSign to get status updates, Connect sends notifications to an application when events happen. There’s no need to continuously send GET requests to find out if an envelope has been completed (meaning that all parties have signed all documents contained within the envelope); Connect will log when the envelope is complete and send the notification at that time. Implementing Connect means that Lexion developers no longer need to implement a polling solution to get envelope updates, and they are no longer constrained by the 15-minute polling limit. This unlocks new value for users, who can now get real-time notifications for their contracts. Not only that, but with the many event triggers supported by Connect, users are able to get richer updates beyond envelope status, such as notifications when an envelope has been viewed or reassigned. 

Connect was already a game changer for Lexion users, but the introduction of Recipient Connect unlocked even more value. Recipient Connect works similarly to Connect in that it is a webhook service that pushes notifications to your app when certain events occur. The difference is that Recipient Connect enables your app to track events on envelopes that you have received, not just those envelopes you have sent. This gives Lexion the ability to track statuses on third-party envelopes and not just envelopes sent from within their platform (first-party envelopes). Before implementing Recipient Connect, any third-party agreements signed via DocuSign would need to be manually uploaded. With Recipient Connect, as long as those third-party agreements live in a DocuSign account that is integrated with Lexion, updates to those envelopes will be recorded in Lexion as well. Recipient Connect supports many of the same event triggers as Connect, including envelope completion, email notifications sent to recipients letting them know that it’s their turn to sign, and failures of recipient authentication.

Putting the C# in Connect

While migrating away from their original polling solution, Lexion developers worked with members of the DocuSign team to increase the efficiency of their integration. Lexion’s developers built the new Connect solution into their existing integration, which was built on ASP.NET Core with the DocuSign C# SDK. When a Lexion user links their DocuSign account to their Lexion account, a new Connect configuration is created in the back end by calling the ConnectionConfigurations::Create endpoint through the DocuSign C# SDK. As events happen in DocuSign, they are sent to a Lexion webhook listener, which is also built in C# using ngrok. The events will then appear to the customer in their Workflow task. 

In developing this solution, the Lexion team determined that they would sometimes need to support multiple configurations for a single customer: for example, if a customer has multiple DocuSign accounts or when an account is using Recipient Connect and needs an additional configuration to track the third-party envelopes. The developers built their webhook listener to process events from multiple Connect configurations, streamlining all of the information into one workflow for the customer. The listener is also programmed with custom logic that determines whether the envelope is being processed by the correct user’s account when one integration has multiple different users.

If at first you don’t succeed, try, try again

Even after incorporating Connect and Recipient Connect to eliminate excessive polling, Lexion’s DocuSign integration makes a lot of API calls. With such a large volume of API calls, it’s inevitable that there are going to be some errors. The Lexion development team handles this by making DocuSign API calls inside a function that handles authentication issues including refreshing tokens, throttling, retrying errors when possible, and logging errors that can’t be retried. The CallWithRetries task shown in Figure 2 is the piece of that function that attempts the API call and retries it asynchronously if needed.The API call is represented in the return statement by the function f, which is passed to the function as a parameter. Depending on which API call is being made, f will vary—it can be any function that performs an action using the authenticated API client, such as one containing a DocuSign C# SDK method that calls an endpoint from the DocuSign eSignature REST API.

async Task<T> CallWithRetries(ApiClient apiClient) {
  return await Policy.Handle<ApiException>(ex => ex.ErrorMessage?
    .Contains("timed out", StringComparison.InvariantCultureIgnoreCase) ?? false)
    .WaitAndRetryAsync(RetryLimit, i => TimeSpan.FromMilliseconds((Math.Pow(2, i) 
      * 100) + this.random.Next(100, 120)), (exp, timespan, retryCount, context) => {
      this.Logger.LogWarning(exp, $"DocuSign Api timed out, retry {retryCount} 
      of {RetryLimit}");
    })
    .ExecuteAsync(async () => {
      return await f(apiClient);
    });
}

Figure 2: The CallWithRetries Task that handles making API calls with retriable errors

Within the function that makes API calls, there is a try statement and multiple catch blocks that handle different types of API exceptions. Figure 3 shows the catch block that handles throttling errors. When encountering throttling, the app will either throw an error or sleep for a specified period of time before retrying. This is one instance where the CallWithRetries task is used to make the API call rather than using the C# SDK method itself in this try-catch block.

catch (ApiException apiException) when (apiException.HasErrorCode(DocuSignError.ThrottlingError))
{
  if (!sleepOnThrottle)
  {
    this.Logger.LogInformation($"Sleep on Throttle is not enabled, we'll just throw");
    throw;
  }

  // Sleeps for a specified amount + 2 minutes buffer to account for clock drift
  async Task Sleep(TimeSpan period)
  {
    await Task.Delay(period + TimeSpan.FromMinutes(2));
  }
  this.Logger.LogWarning($"We got throttled by DocuSign, we'll wait for the reset 
    before retrying the API request");
  if (!apiException.Headers.TryGetValue("X-RateLimit-Reset", out string value))
  {
    this.Logger.LogWarning($"Didn't find reset header, will sleep for ~1 hr to be 
      safe");
    await Sleep(TimeSpan.FromHours(1));
  }
  else if (!long.TryParse(value, out var epochTime))
  {
    this.Logger.LogWarning($"Failed to parse epoch time: {epochTime} from reset 
      header, will sleep for ~1 hr to be safe");
    await Sleep(TimeSpan.FromHours(1));
  }
  else
  {
    var epochOffset = DateTimeOffset.FromUnixTimeSeconds(epochTime);
    this.Logger.LogInformation($"Reset Time computed is: {epochOffset.UtcDateTime}");
    var timeLeft = epochOffset.UtcDateTime - DateTime.UtcNow;
    this.Logger.LogInformation($"Time left till reset: {timeLeft}, will sleep this 
      much");
    await Sleep(timeLeft);
  }

  try
  {
    return await CallWithRetries(apiClient);
  }
  catch (ApiException apiException2) when (apiException2.ErrorCode == 
    (int)HttpStatusCode.Unauthorized)
  {
    apiClient = await TryRefreshCredentials();
    return apiClient == null ? defaultValue : await CallWithRetries(apiClient);
  }
}

Figure 3: The catch block that handles throttling errors from the DocuSign API

Customers are [web-]hooked

Lexion has found Connect to be invaluable for its customers who want richer and more frequent updates on the status of their envelopes. In this case, a win for customers is also a win for Lexion. As Lexion migrates all of their customers to Connect, they will no longer need to maintain the polling solution, alleviating the headaches that come with managing that older code. 

Check out the DocuSign Developer Center to learn more about how a DocuSign integration can provide value to your customers. You can also try MyConnectWebhook, a sample app that demonstrates Connect in action.

Paige Rossi
Author
Paige Rossi
Sr. Programmer Writer
Published