Common API Tasks - Locking and unlocking envelopes

Common API Tasks

Welcome to another post of the Common API Tasks blog series for developers! This blog series is focused on simple, yet useful pieces of functionality that can be accomplished using one of the DocuSign APIs. In past posts I helped you with things like how to void an envelope or how to retrieve tab data. In my last post, I showed you how you can add more users to a DocuSign account using the eSignature REST API. In this issue I’ll be showing you a very useful technique to make your applications more robust by locking and unlocking envelopes as needed.

As developers who use various systems of source control, I’m sure you’re familiar with the concept of merge conflicts: two (or more) developers making changes to the same file and ending up with the wrong version that someone has to go and resolve.

Similarly, in DocuSign, when you have more than one user (or sometimes the same user using two instances of your application) accessing the system and trying to make changes to the same envelope, you may run into trouble.

To help developers with this problem, the eSignature REST API provides a mechanism to lock envelopes such that only a particular user of a particular integration can modify them. While the envelope is locked, any other requests to modify it are denied and result in an error. Note that opening an envelope for signing is considered modifying it, even if you don’t actually sign it. That is because the DocuSign system records each interaction with the envelope and changes the certificate of completion, which is part of the envelope.

In this blog post, I’ll cover how to lock an envelope, how to check if an envelope is locked and how to unlock the envelope. The code snippets that I show do the following:

  1. Check if envelope is locked or not
  2. If it is unlocked, lock it
  3. If it is locked, unlock it

When you lock an envelope, you have to provide some information, including which app is locking the envelope and the duration of the lock. You may also provide a password. That is useful if you are locking a template and want to make sure that it is not changed.

Your application gets back a lockToken, which must later be used to unlock the envelope using an HttpHeader. You cannot unlock an envelope without this lockToken (the lock will expire when the LockDurationInSeconds has passed). 

OK, so let’s get down to some code...

C#

// You will need to obtain an accessToken using your chosen authentication flow 

var config = new Configuration(new ApiClient(basePath));

config.AddDefaultHeader("Authorization", "Bearer " + accessToken);

var envelopesApi = new EnvelopesApi(config);

try

{

   LockInformation lockInfo = envelopesApi.GetLock(accountId, envelopeId);

   // check if this app locked it

    if (lockInfo.LockedByApp == "C.A.T. App")

   {

       // add a header with the LockToken to ensure this app has the right to unlock 

        string LockHeader = $"{{\"lockToken\":\"{lockInfo.LockToken}\"}}";

        envelopesApi.Configuration.AddDefaultHeader("X-DocuSign-Edit", LockHeader);

       envelopesApi.DeleteLock(accountId, envelopeId);

   }

}

catch (ApiException exp)

{

   // GetLock would throw an ApiException with error 404 if the envelope is unlocked

    if (exp.ErrorCode == 404)

   {

        var lockRequest = new LockRequest

       { 

            LockedByApp = "C.A.T. App",

            LockDurationInSeconds = "300",

            LockType = "edit"

       };

       envelopesApi.CreateLock(accountId, envelopeId, lockRequest);

   }

}

Java

// You will need to obtain an accessToken using your chosen authentication flow 

Configuration config = new Configuration(new ApiClient(basePath));

config.addDefaultHeader("Authorization", "Bearer " + accessToken);

EnvelopesApi envelopesApi = new EnvelopesApi(config);

try

{

   LockInformation lockInfo = envelopesApi.getLock(accountId, envelopeId);

   // check if this app locked it

    if (lockInfo.getLockedByApp() == "C.A.T. App")

   {

       // add a header with the LockToken to ensure this app has the right to unlock 

        String LockHeader = String.Format("{{\"lockToken\":\"%s\"}}",   

           lockInformation.getLockToken());

        envelopesApi.getConfiguration().addDefaultHeader("X-DocuSign-Edit", LockHeader);

       envelopesApi.deleteLock(accountId, envelopeId);

   }

}

catch (ApiException exp)

{

   // GetLock would throw an ApiException with error 404 if the envelope is unlocked

    if (exp.getCode() == 404)

   {

        LockRequest lockRequest = new LockRequest();

       lockRequest.setLockedByApp("C.A.T. App");

        lockRequest.setLockDurationInSeconds("300");

        lockRequest.setLockType("edit");

       envelopesApi.createLock(accountId, envelopeId, lockRequest);

   }

}

 

Node.js

// You will need to obtain an accessToken using your chosen authentication flow 


let apiClient = new ApiClient(basePath);

let config = new docusign.Configuration(apiClient);

config.addDefaultHeader('Authorization', 'Bearer ' + accessToken);

let envelopesApi = new docusign.EnvelopesApi(config);

try

{

    let lockInfo = envelopesApi.getLock(accountId, envelopeId);

   // check if this app locked it

    if (lockInfo.lockedByApp === 'C.A.T. App')

   {

       // add a header with the LockToken to ensure this app has the right to unlock 

        let lockHeader = '{{"lockToken":"${lockInfo.lockToken}"}}';

        envelopesApi.configuration.addDefaultHeader('X-DocuSign-Edit', lockHeader);

       envelopesApi.deleteLock(accountId, envelopeId);

   }

}

catch (exp)

{

   // GetLock would throw an ApiException with error 404 if the envelope is unlocked

    if (exp.status == 404)

   {

        let lockRequest = new docusign.lockRequest.constructFromObject({

        LockedByApp : 'C.A.T. App',

        lockDurationInSeconds : '300',

        lockType : 'edit' });

       envelopesApi.createLock(accountId, envelopeId, lockRequest);

   }

}
 

PHP

# You will need to obtain an accessToken using your chosen authentication flow 


$api_client = new \DocuSign\eSign\client\ApiClient($base_path);

$config = new \DocuSign\eSign\Model\Configuration($api_client);

$config->addDefaultHeader('Authorization', 'Bearer ' + $access_token);

$envelopes_api = new \DocuSign\Api\EnvelopesApi($config);

try

{

   $lock_info = $envelopes_api->getLock($account_id, $envelope_id);

   # check if this app locked it

    if ($lock_info->getLockedByApp() == 'C.A.T. App')

   {

       # add a header with the LockToken to ensure this app has the right to unlock 

        $lock_header = sprintf('{{"lockToken":"%s"}}', $lock_info->getLockToken());

        $envelopes_api->configuration->addDefaultHeader('X-DocuSign-Edit', $lock_header);

       $envelopes_api->deleteLock(accountId, envelopeId);

   }

}

catch (ApiException $exp)

{

   # GetLock would throw an ApiException with error 404 if the envelope is unlocked

    if ($exp->getCode() == 404)

   {

        $lock_request = new \DocuSign\eSign\Model\lockRequest();

        $lock_request->setLockedByApp('C.A.T. App');

        $lock_request->setlockDurationInSeconds('300');

        $lock_request->setlockType('edit');

       $envelopes_api->createLock($account_id, $envelope_id, $lock_request);

   }

}

 

Python

# You will need to obtain an accessToken using your chosen authentication flow 


api_client = ApiClient()

api_client.set_default_header('Authorization', 'Bearer ' + access_token)

envelopes_api = EnvelopesApi(config)

try:

   lock_info = envelopes_api.get_lock(account_id, envelope_id)

   # check if this app locked it

    if lockInfo.locked_by_app == 'C.A.T. App':

       # add a header with the LockToken to ensure this app has the right to unlock 

        lock_header = '{{"lockToken":"{0}"}}'.format(lock_info.lock_token)

        envelopes_api.configuration.set_default_header('X-DocuSign-Edit', lock_header)

       envelopes_api.delete_lock(account_id, envelope_id)

except ApiException as exp:

   # GetLock would throw an ApiException with error 404 if the envelope is unlocked

    if exp.status == 404:

        lock_request = LockRequest()

        lock_request.locked_by_app = 'C.A.T. App'

        lock_request.lock_duration_in_seconds = '300'

        lock_request.lock_type = 'edit'

        envelopes_api.create_lock(account_id, envelope_id, lock_request)
 

Ruby


# You will need to obtain an accessToken using your chosen authentication flow 


config = DocuSign_eSign::Configuration.new

config.host = base_path

api_client = DocuSign_eSign::ApiClient.new config

api_client.DefaultHeader['Authorization'] = 'Bearer ' + access_token

envelopes_api = DocuSign_eSign::EnvelopesApi.new api_client

begin

   lock_info = envelopes_api.get_lock(account_id, envelope_id)

   # check if this app locked it

    if lockInfo.locked_by_app == 'C.A.T. App'

       # add a header with the LockToken to ensure this app has the right to unlock 

        lock_header = '{{"lockToken":"%s"}}' % lock_info.lock_token

        envelopes_api.Configuration..DefaultHeader['X-DocuSign-Edit'] = lock_header

       envelopes_api.delete_lock(account_id, envelope_id)

   end

rescue DocuSign_eSign::ApiError => exp

   # GetLock would throw an ApiException with error 404 if the envelope is unlocked

    if exp.status == 404

        lock_request = DocuSign_eSign::LockRequest.new

        lock_request.locked_by_app = 'C.A.T. App'

        lock_request.lock_duration_in_seconds = '300'

        lock_request.lock_type = 'edit'

       envelopes_api.create_lock(account_id, envelope_id, lock_request)

    end

end

 

I hope you found this useful. As usual, if you have any questions, comments, or suggestions for topics for future Common API Tasks posts, feel free to email me. Until next time...

Additional resources

Author

Inbar Gazit

Published
Share this post