From the Trenches: Composite templates
Composite templates are the most extensible model for integration development and can save you much re-engineering time on app updates.
Table of contents
There is an unlimited variety of use cases for sending envelopes using the Docusign eSignature REST API. The composite template is one of the most powerful tools in a developer’s toolkit for creating envelopes using the API, and along with that power comes a good deal of complexity. In this article I will describe a common use case and give JSON and C# (using our SDK) examples of how to use composite templates to code a solution. Composite templates give you more power when creating an envelope, including the ability to:
Apply multiple templates to a single envelope.
Replace the documents on your saved Docusign server templates when creating the envelope, but still have the server template apply all the tabs to the recipients in your envelope.
Write values at run time into the text tabs and other data fields on the server template.
Add additional tabs at run time.
Transform PDF fields into Docusign tabs and assign them to recipients.
Let’s take as an example a Statement of Work where the description of the work provided varies and the hourly rate varies depending on the work provided. A Docusign template could be created that includes all the tabs for a customer to initial and sign the document defined by auto-place text, or as we say in the eSignature API, anchorStrings. One of these tabs would be labeled HourlyRate
. At run time we want to use our saved template, but swap in a new document, define a new customer and set the value of hourly rate.
To do this, we add an array of compositeTemplates
to our envelope. In that array we define one composite template. We add a document to the composite template to replace the document saved on the server template. We also add a serverTemplates
array consisting of one server template. This is the template you have saved in your Docusign account. And finally, we add the inlineTemplates
array, consisting of one inline template to provide the runtime information about recipients and tabs. Notice that to write a value to the HourlyRate
tab, I only needed to match the tabLabel
on the template to identify the tab, set the value and set the tab to locked. In JSON the complete envelope definition would look like the code below. There are only three envelope properties: compositeTemplates
, emailSubject
, and status
.
{
"compositeTemplates": [
{
"compositeTemplateId": "1",
"document": {
"documentBase64": "PDF Bytes",
"documentId": "1",
"fileExtension": "pdf",
"name": "Statement of Work"
},
"inlineTemplates": [
{
"recipients": {
"signers": [
{
"email": "g...test@example.com",
"name": "Geoff Test",
"recipientId": "1",
"roleName": "Customer",
"routingOrder": "1",
"tabs": {
"textTabs": [
{
"tabLabel": "HourlyRate",
"value": "$180.00",
"locked": "true"
}
]
}
}
]
},
"sequence": "2"
}
],
"serverTemplates": [
{
"sequence": "1",
"templateId": "57fd4752-xxxx-xxxx-xxxx-ecbfc7a43bef"
}
]
}
],
"emailSubject": "CompositeTemplate Example",
"status": "sent"
}
To generate this JSON using the C# SDK, the code would look like this:
public static string CompositeTemplateExample()
{
// Instantiate ApiClient and configure authentication. Method not not shown.
string accountId = GetAPIandAuthenticate();
EnvelopesApi api = new EnvelopesApi(Configuration.Default);
// Create a list of composite templates
List<CompositeTemplate> CompoTemplateList = new List<CompositeTemplate>();
// Create one Composite Templates
CompositeTemplate compoTemplate = new CompositeTemplate();
// Create a document
var documents = new List<Document>();
byte[] fileBytes = null;
Document doc = new Document();
fileBytes = File.ReadAllBytes(@"C:\temp\SOW1.pdf");
doc.Name = "Statement of Work";
doc.DocumentBase64 = System.Convert.ToBase64String(fileBytes);
doc.DocumentId = "1";
doc.FileExtension = "pdf";
// Add to Composite template
compoTemplate.Document = doc;
// Create Envelope recipients, including them in the first template
List<Signer> signers = new List<Signer>();
// Create the tab for hourly rate
Tabs tabs = new Tabs();
Text textBox = new Text();
textBox.TabLabel = "HourlyRate";
textBox.Value = "$180.00";
textBox.Locked = "true";
tabs.TextTabs = new List<Text>();
tabs.TextTabs.Add(textBox);
// Create the signer and add the tabs to pick up the HourlyRate
Signer newRecipient = new Signer
{
Email = "g...test@example.com",
Name = "Geoff Test",
RecipientId = "1",
RoleName = "Customer",
RoutingOrder = "1",
Tabs = tabs,
};
signers.Add(newRecipient);
// Create first list for InlineTemplates
List<InlineTemplate> inlineTemplateList = new List<InlineTemplate>();
InlineTemplate inlineTemplate = new InlineTemplate();
inlineTemplate.Sequence = "2";
inlineTemplate.Recipients = new Recipients();
inlineTemplate.Recipients.Signers = signers;
// Add it to the inlineTemplatesList
inlineTemplateList.Add(inlineTemplate);
// Create the reference to the template housed on your Docusign account
ServerTemplate serverTemplate = new ServerTemplate()
{
Sequence = "1",
TemplateId = "ce839909-xxxx-xxxx-xxxx-a05dbd8c7217" // Statement of Work
};
List<ServerTemplate> serverTemplateList = new List<ServerTemplate>();
// Add it to the templates List
serverTemplateList.Add(serverTemplate);
// Create the composite template, add the server / inline template lists.
compoTemplate.CompositeTemplateId = "1";
compoTemplate.ServerTemplates = serverTemplateList;
compoTemplate.InlineTemplates = inlineTemplateList;
// Take the Composite Template list, add both
List<CompositeTemplate> compositList = new List<CompositeTemplate>();
compositList.Add(compoTemplate);
// Create the definition for the envelope
EnvelopeDefinition envDefinition = new EnvelopeDefinition();
// Add the Composite Template list
envDefinition.CompositeTemplates = compositList;
envDefinition.EmailSubject = "CompositeTemplate Example";
envDefinition.Status = "sent";
EnvelopesApi.CreateEnvelopeOptions options = null; //No query parameters
// Create the envelope
EnvelopeSummary Response = api.CreateEnvelope(accountId, envDefinition, options);
string envelopeId = Response.EnvelopeId;
Console.WriteLine(envelopeId);
Console.ReadLine();
return envelopeId;
}
The resulting envelope has been created with the new document of terms and conditions. All the Initial and SignHere tabs are placed on the anchor strings. The hourly rate has been written to the PDF and cannot be edited by the signer.
Additional resources
Beginning in the 1990s, Geoff's engineering career has followed the evolution of COM, Java and .NET on the machine and SOAP and REST in the cloud. Currently the Developer Support team's subject matter expert for the Apex Toolkit, Geoff has extensive experience as an engineer in support, test, and sales. You can find him on LinkedIn.
Related posts