From the Trenches: Composite templates and Advanced Recipient Routing

The composite templates model is a flexible model that allows users to implement a variety of workflows, both simple and complex. This post by Gil Vincent explains in detail what they are capable of, and why you should be using them.

Advanced Recipient Routing is used to automate tedious internal processes that require pauses in the signing workflow or to route to different recipients depending on data input. This post explains how to use advanced recipient routing along with some common use cases. 

As an example, if you had a template with two signers and you wanted to add a delay of three hours after the recipient with routing order 1 has finished signing, your envelope definition would look like this:

{
  "templateId": "55A80182-xxxx-xxxx-xxxx-FD1E1C0F9D74",
  "templateRoles": [
     {
        "roleName": "Signer1",
        "name": "Hank Scorpio",
  	  "email": "hscorpio@example.com",
        "routingOrder":"1"
     },{
	  "roleName": "Signer2",
        "name": "Hank Libra",
  	  "email": "hlibra@example.com",
        "routingOrder":"2"
       }],
  "workflow": {
    "workflowStatus": "in_progress",
    "workflowSteps": [
      {
        "action": "pause_before",
        "itemId": "2",
        "status": "pending",
        "triggerOnItem": "routing_order",
        "delayedRouting": { "rules": [{ "delay": "3.00:00:00" }] }
      }
    ]
  },
  "status": "Sent"
}

For the same template, the envelope definition using the composite template model would be modified to look like this:

{
    "compositeTemplates": [
        {
            "compositeTemplateId": "1",
            "inlineTemplates": [
                {
                    "recipients": {
                        "signers": [
                            {
                                "roleName": "Signer1",
                                "name": "Hank Scorpio",
                                "email": "hscorpio@example.com",
                                "routingOrder":"1"
                             },{
                                "roleName": "Signer2",
                                "name": "Hank Libra",
                                "email": "hlibra@example.com",
                                "routingOrder":"2"
                             }
                        ]
                    },
                    "sequence": "2"
                }
            ],
            "serverTemplates": [
                {
                    "sequence": "1",
                    "templateId": "55A80182-xxxx-xxxx-xxxx-FD1E1C0F9D74"
                }
            ]
        }
    ],
    "workflow": {
        "workflowStatus": "in_progress",
        "workflowSteps": [
          {
            "action": "pause_before",
            "itemId": "2",
            "status": "pending",
            "triggerOnItem": "routing_order",
            "delayedRouting": { "rules": [{ "delay": "3.00:00:00" }] }
          }
        ]
    },
    "status": "sent"
}

Currently, there is an issue affecting composite templates wherein a payload like the previous example will be successful and an envelope will be created. However, the workflow object will have no effect on the template and making a EnvelopeWorkflowDefinition:getEnvelopeWorkflowDefinition to the envelope will return a 404 response. 

While our engineering team works to get this fixed, we wanted to share a workaround that uses the combination of embedded signing with DocuSign Connect to implement your workflow.

The embedded recipient acts as a “workflow” recipient whose routing order should be a value where you want the envelope paused. As per design, DocuSign will wait until your app has the recipient sign via an embedded signing session. 

Your DocuSign Connect listener can act as a timer: upon receiving a recipient-completed event, it will check if it is the embedded workflow signer’s turn to sign. If it is, your app instead will perform whatever actions the workflow would do (changing recipients, waiting before routing to the next signer, and so on) and then it can delete the workflow recipient, which will automatically route the envelope to the next recipient in line.

A sample API request for this workaround would be:

{
    "compositeTemplates": [
        {
            "compositeTemplateId": "1",
            "inlineTemplates": [
                {
                    "recipients": {
                        "signers": [
                            {
                                "roleName": "Signer1",
                                "name": "Hank Scorpio",
                                "email": "hscorpio@example.com",
                                "routingOrder":"1"
                             },{
                                "name":"Workflow Recipient",
                                "email":"workflowemail@example.com",
                                "routingOrder":"2",
                                "clientUserId":"WorkflowClientUserId"
                             },{
                                "roleName": "Signer2",
                                "name": "Hank Libra",
                                "email": "hlibra@example.com",
                                "routingOrder":"3"
                             }
                        ]
                    },
                    "sequence": "2"
                }
            ],
            "serverTemplates": [
                {
                    "sequence": "1",
                    "templateId": "55A80182-xxxx-xxxx-xxxx-FD1E1C0F9D74"
                }
            ]
        }
    ],
    "eventNotification": {
        "events": [
          "recipient-completed"
        ],
        "eventData": { "format": "json", "includeData": [], "version": "restv2.1" },
        "requireAcknowledgment": "true",
        "url": "mywebhook.url",
        "deliveryMode": "SIM"
      },
    "status": "sent"
}

Once the envelope has been completed by recipient 1, the envelope will route to my embedded recipient 2 and simultaneously publish a recipient-completed event to my webhook. Once my webhook receives this message, it will internally start a timer for three (3) hours, which was how much I originally wanted it to be delayed. 

Once the three hours have passed, my webhook application will make an EnvelopeRecipients:List call (because recipient IDs are only consistent within each individual template) and, once it has the recipient Id of the embedded recipient, it can simply make an EnvelopeRecipients:Delete call to delete the embedded signer and resume the envelope by routing to the recipient with routing order 3.

Alternatively, instead of using an embedded signer, you can also use a “certifiedDeliveries” recipient. In this case, you'd need to provide an email address that is a black hole; that is emails sent to this email address will be received and silently swallowed and discarded (such as a no-reply email address).

While implementing this workaround, DocuSign recommends trying this out in your demo environment first to make sure that this would work for your use case. 

Additional resources

Karan Kaushik
Author
Karan Kaushik
Developer Support Engineer
Published