Docusign embedded signing request from template with nodejs - docusignapi

I am using the nodejs docusign api and am having trouble figuring out how do embedded signing request from template. I kinda want it working the way the example does for non template usage.
The main issue i am having is with the way the nodejs docusign library handles recipientIds when you are using a template, cant set the recipientIds directly when you use the template and doesnt seem to take the recipients set automatically by docusign
Most of my code wasfollowing the quickstart guide
Yes I have read, but found the answers unhelpful.
Docusign embedded signing request from template and Docusign Embedded Signing using template

function makeEnvelope(args){
// create the envelope definition
let env = new docusign.EnvelopeDefinition();
env.templateId = args.templateId;
// Create template role elements to connect the signer and cc recipients
// to the template
// We're setting the parameters via the object creation
let signer1 = docusign.TemplateRole.constructFromObject({
email: args.signerEmail,
name: args.signerName,
clientUserId: '1',
roleName: 'signer'});
// Add the TemplateRole objects to the envelope object
env.templateRoles = [signer1];
env.status = "sent"; // We want the envelope to be sent
return env;
}
{
let dsApiClient = new docusign.ApiClient();
dsApiClient.setBasePath(args.basePath);
dsApiClient.addDefaultHeader('Authorization', 'Bearer ' + args.accessToken);
let envelopesApi = new docusign.EnvelopesApi(dsApiClient);
// Step 1. Make the envelope request body (function above)
let envelope = makeEnvelope(args.envelopeArgs)
// Step 2. call Envelopes::create API method
// Exceptions will be caught by the calling function
let results = await envelopesApi.createEnvelope(
args.accountId, {envelopeDefinition: envelope});
return results;
}
function makeRecipientViewRequest(args) {
let viewRequest = new docusign.RecipientViewRequest();
viewRequest.returnUrl = args.dsReturnUrl + "?state=123";
viewRequest.authenticationMethod = 'none';
viewRequest.email = args.signerEmail;
viewRequest.userName = args.signerName;
viewRequest.clientUserId = args.signerClientId;
viewRequest.pingFrequency = 600; // seconds
viewRequest.pingUrl = args.dsPingUrl; // optional setting
return viewRequest
}

Related

DocuSign: Successful envelope but status is not "sent"

I'm using node and I make an envelope with env.status = "sent", I then hit the envelopesApi.createEnvelope with said envelope. The response back says its successful but the status is "created" and no email is sent for signature to the specified signer. What am I missing? Here is the full response
{
"envelopeId": "205ed07d-8094-4031-a334-7159e1bd0f34",
"status": "created",
"statusDateTime": "2023-01-05T06:19:17.9670000Z",
"uri": "/envelopes/205ed07d-8094-4031-a334-7159e1bd0f34"
}
Also note, the simple template has a signer role on it, and a signature specified, in my code I tried both adding the signer with TemplateRole.constructFromObject, and env.templateRoles = [signer1] and also removing this code (as its specified online in the UI), both just result in status created, not sent.
Heres all the relevant code:
async sendEnvelopeFromTemplate(accessToken: string): Promise<any>{
// Data for this method
// args.basePath
// args.accessToken
// args.accountId
const basePath = docusign_account_base_uri + '/restapi'
let dsApiClient = new docusign.ApiClient();
dsApiClient.setBasePath(basePath);
dsApiClient.addDefaultHeader("Authorization", "Bearer " + accessToken);
let envelopesApi = new docusign.EnvelopesApi(dsApiClient);
// Step 1. Make the envelope request body
let envelope = this.makeEnvelope();
// Step 2. call Envelopes::create API method
// Exceptions will be caught by the calling function
try{
let results = await envelopesApi.createEnvelope(docusign_api_account_id, {
envelopeDefinition: envelope,
});
return results;
}
catch(e){
console.log("ERROR")
console.log(e)
}
};
async makeEnvelope() {
const args = {
signerEmail: 'REDACTED',
signerName: 'REDACTED',
templateId: 'REDACTED'
}
// create the envelope definition
let env = new docusign.EnvelopeDefinition();
env.templateId = args.templateId;
// Create template role elements to connect the signer and cc recipients
// to the template
// We're setting the parameters via the object creation
let signer1 = docusign.TemplateRole.constructFromObject({
email: args.signerEmail,
name: args.signerName,
roleName: "signer",
});
// Add the TemplateRole objects to the envelope object
env.templateRoles = [signer1];
env.status = "sent"; // We want the envelope to be sent
return env;
}
You need to set status to "sent" when you create the envelope.
Otherwise (your situation), your envelope is in status "created" which is equivalent to a draft envelope.
Do you have a complete template, i.e. does the template contain a document? An envelope cannot be sent if a) there isn's at least one document in the envelope, b) there must be at least one recipient.
There could be other side issues, such as not allowing "free-form signing" (no tabs specified for the signer) and the envelope has no tabs. But I'm going to assume your account is set up as default so that isn't an issue here. Also assuming you assigned a tab to the role in your template.
Was a simple async issue, I did not await the call to makeEnvelope, I was getting a success back, but the sent status was not being set, as soon as I awaited it the problem went away. Thanks for the other helpful info.
let envelope = this.makeEnvelope();
needed to be
let envelope = await this.makeEnvelope();

event notification of envelope in DocuSign restapi c#,webapi

I have added event notification at the time of envelope creation in EnvelopeCreate Method as
apiClient.Configuration.DefaultHeader.Add("Authorization", "Bearer " + AccessToken);
EnvelopesApi envelopesApi = new EnvelopesApi(apiClient);
EnvelopeSummary results = envelopesApi.CreateEnvelope(AccountId, env);
EventNotificationForEnvelope();
and EventNotificationForEnvelope method is as
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
EnvelopeDefinition envelopeDefinition = new EnvelopeDefinition();
var eventNotification = new EventNotification();
// Set up the endpoint URL to call (it must be using HTTPS and at least TLS1.1 or higher)
eventNotification.Url = "https:\\testapi.example.com/api/DocuSignEventNotification";
// DocuSign will retry on failure if this is set
eventNotification.RequireAcknowledgment = "true";
// This would send the documents together with the event to the endpoint
eventNotification.IncludeDocuments = "true";
// Allows you to see this in the DocuSign Admin Connect logs section
eventNotification.LoggingEnabled = "true";
var envelopeEvents = new List<EnvelopeEvent>();
// In this case we only add a single envelope event, when the envelope is completed. You can also add events for recipients
envelopeEvents.Add(new EnvelopeEvent { EnvelopeEventStatusCode = "completed",
IncludeDocuments = "true" });
eventNotification.EnvelopeEvents = envelopeEvents;
envelopeDefinition.EventNotification = eventNotification;
and in my api's controller as
public class DocuSignEventNotificationController : ApiController
{
[HttpPost]
[HttpGet]
public HttpResponseMessage DocuSignDocumentStatus(HttpResponseMessage responseMessage)
{
dynamic response = responseMessage.Content.ReadAsStringAsync();
//here I will read values from response and use in my application
return Request.CreateResponse(HttpStatusCode.OK, "Testing");
}
}
I am not getting any response on envelope create and when status is updating of that envelope
A couple of things.
First,
https:\testapi.example.com/api/DocuSignEventNotification
Is not where you have your server I presume. Make sure that you use https and that your server is configured correctly to accepts TLS (1.2 and above).
Using a cloud service or some other third-party instead of building your own is much easier. If you do use your own, you may need to ensure firewall etc. allow for requests coming from the internet.
Second,
There's a log that you can find in the Connect section settings area in the DocuSign web app that can show you all attempts to reach servers. That can help you figure out if the request was made correctly to DocuSign and if DocuSign attempted to call your server and if so - what error may have been returned.
Just click "Logs":

How can I receive returnurl events from embedded app?

I sent envelope at embed app without client_id. Then, I can check the envelope by email, and if I signed the envelope in the email, is there a way to get an event on the embed app?
public Map<String,Object> createRecipientView(Map<String,Object> recipientInfo) {
Map<String,Object> result = new HashMap<String,Object>();
// instantiate a new EnvelopesApi object
EnvelopesApi envelopesApi = new EnvelopesApi();
// set the url where you want the recipient to go once they are done signing
RecipientViewRequest view = new RecipientViewRequest();
//view.setReturnUrl("https://www.docusign.com");
view.setReturnUrl(serverUrl+"/"+recipientInfo.get("usr_cls")+"/docusign/returnRecipientView.do?ds_usr_id="+recipientInfo.get("ds_usr_id") + "&docusign_id=" + recipientInfo.get("docusign_id")+ "&usr_cls=" + recipientInfo.get("usr_cls") + "&uiId=" +recipientInfo.get("uiId"));
view.setAuthenticationMethod("email");
// recipient information must match embedded recipient info we provided in step #2
String email = (String)recipientInfo.get("email");
String userName = (String)recipientInfo.get("usr_nm");
String recipientId = (String)recipientInfo.get("recipient_id");
String clientId = (String)recipientInfo.get("client_id");
String envelopeId = (String)recipientInfo.get("envelope_id");
view.setEmail(email);
view.setUserName(userName);
view.setRecipientId(recipientId);
//view.seta
//view.setClientUserId(clientId);
// call the CreateRecipientView API
ViewUrl recipientView;
try {
recipientView = envelopesApi.createRecipientView(accountId, envelopeId, view);
log.info("Signing URL = " + recipientView.getUrl());
result.put("url", recipientView.getUrl());
result.put("result_status", "S");
} catch (ApiException e) {
log.error("error : " + e.toString());
result.put("result_status", "F");
result.put("result_message", e.toString());
}
return result;
}
Yes, you can use webhook to get notifications about the envelope to your app.
You can read this blog post about it.
You can also look at this code example.
Here is some C# code taken from here:
EnvelopeDefinition envelopeDefinition = new EnvelopeDefinition();
var eventNotification = new EventNotification();
\\ Set up the endpoint URL to call (it must be using HTTPS and at least TLS1.1 or higher)
eventNotification.Url = "https:\\myapp.somedomain.com";
\\ DocuSign will retry on failure if this is set
eventNotification.RequireAcknowledgment = "true";
\\ This would send the documents together with the event to the endpoint
eventNotification.IncludeDocuments = "true";
\\ Allows you to see this in the DocuSign Admin Connect logs section
eventNotification.LoggingEnabled = "true";
var envelopeEvents = new List<EnvelopeEvent>();
\\ In this case we only add a single envelope event, when the envelope is completed. You can also add events for recipients
envelopeEvents.Add(new EnvelopeEvent { EnvelopeEventStatusCode = "completed", IncludeDocuments = "true" });
eventNotification.EnvelopeEvents = envelopeEvents;
envelopeDefinition.EventNotification = eventNotification;

Email notification to user is not sent when ClientUserId is provided

I'm trying to create envelope from template i uploaded to my account.
Using following code to do that:
public static void main(String[] args) throws ApiException {
// Enter your DocuSign credentials
String UserName = "my-user-name";
String Password = "my-password";
String IntegratorKey = "my-integrator-key";
// for production environment update to "www.docusign.net/restapi"
String BaseUrl = "https://demo.docusign.net/restapi";
// initialize the api client for the desired environment
ApiClient apiClient = new ApiClient();
apiClient.setBasePath(BaseUrl);
// create JSON formatted auth header
String creds = "{\"Username\":\"" + UserName + "\",\"Password\":\"" + Password + "\",\"IntegratorKey\":\"" + IntegratorKey + "\"}";
apiClient.addDefaultHeader("X-DocuSign-Authentication", creds);
// assign api client to the Configuration object
Configuration.setDefaultApiClient(apiClient);
//////////////////////////////// LOGIN START
// login call available off the AuthenticationApi
AuthenticationApi authApi = new AuthenticationApi();
// login has some optional parameters we can set
AuthenticationApi.LoginOptions loginOps = authApi.new LoginOptions();
loginOps.setApiPassword("true");
loginOps.setIncludeAccountIdGuid("true");
LoginInformation loginInfo = authApi.login(loginOps);
// note that a given user may be a member of multiple accounts
List<LoginAccount> loginAccounts = loginInfo.getLoginAccounts();
System.out.println("LoginInformation: " + loginAccounts);
// use the |accountId| we retrieved through the Login API to create the Envelope
String accountId = loginAccounts.get(0).getAccountId();
/////////////////////////////////////// LOGIN END
////////////////////////////////////// CREATE ENVELOPE START
// create a new envelope object that we will manage the signature request through
EnvelopeDefinition envDef = new EnvelopeDefinition();
envDef.setEmailSubject("Hey! Sign the following document");
// assign template information including ID and role(s)
envDef.setTemplateId("ebbe20e3-1c2e-4696-a0c4-41269bf54aeb");
// create a template role with a valid templateId and roleName and assign signer info
TemplateRole tRole = new TemplateRole();
tRole.setRoleName("Client");
String name = "Jake";
String email = "someEmail#goes.here";
tRole.setName(name);
tRole.setEmail(email);
tRole.setClientUserId("someClientUuid");
// create a list of template roles and add our newly created role
List<TemplateRole> templateRolesList = new ArrayList<>();
templateRolesList.add(tRole);
Tabs tabs = new Tabs();
Text clientIdField = new Text();
clientIdField.setTabLabel("CustomerId");
clientIdField.setValue("I changed text from API! It works!");
List<Text> textList = new ArrayList<>();
textList.add(clientIdField);
tabs.setTextTabs(textList);
tRole.setTabs(tabs);
// assign template role(s) to the envelope
envDef.setTemplateRoles(templateRolesList);
// send the envelope by setting |status| to "sent". To save as a draft set to "created"
envDef.setStatus("sent");
// use the |accountId| we retrieved through the Login API to create the Envelope
// instantiate a new EnvelopesApi object
EnvelopesApi envelopesApi = new EnvelopesApi();
// call the createEnvelope() API
EnvelopeSummary envelopeSummary = envelopesApi.createEnvelope(accountId, envDef);
System.out.println("EnvelopeSummary: " + envelopeSummary);
///////////////////////////////////// CREATE ENVELOPE END
String envelopeId = envelopeSummary.getEnvelopeId();
//////////////////////////////////////// CREATE RECIPIENT VIEW
// use the |accountId| we retrieved through the Login API
// instantiate a new EnvelopesApi object
// set the url where you want the recipient to go once they are done signing
RecipientViewRequest returnUrl = new RecipientViewRequest();
returnUrl.setReturnUrl("https://www.docusign.com/devcenter");
returnUrl.setAuthenticationMethod("email");
// recipient information must match embedded recipient info we provided in step #2
returnUrl.setEmail(email);
returnUrl.setUserName(name);
returnUrl.setClientUserId("someClientUuid");
// call the CreateRecipientView API then navigate to the URL to start the signing session
ViewUrl recipientView = envelopesApi.createRecipientView(accountId, envelopeId, returnUrl);
System.out.println("ViewUrl: " + recipientView);
//////////////////////////////////////// CREATE RECIPIENT VIEW
}
And i noticed strange thing - when i provide clientUserId field to my TemplateRole, while creating envelope from template - email notification to sign document is not sent to user. But when i remove this field - email is sent successfully.
The problem is that i need that clientUserId in my TemplateRole to be able to properly generate ViewUrl to use in my application.
So is it a bug or a feature, that notification is not sent with provided clientUserId in TemplateRole? Did not found any documentation about that on official site.
When clientUserId is specified the recipient is considered as an embedded recipient. By default only remote recipients receive email notifications.
If you want embedded recipients to receive email notifications then set the embeddedRecipientStartURL property.
tRole.setEmbeddedRecipientStartURL("SIGN_AT_DOCUSIGN")
See this answer for more information
Official Documentation

Prefill docusign template fields

Using the Docusign node.js sample I'm able to send a template, however I'm having trouble pre-setting the field values.
I've looked around on stack overflow and found 3 different versions of the setTemplateRoles JSON format. I've tried them all and none worked.
When I run this code, the email comes to foo#email.com and my template comes through fine, but the fields are not pre-filled.
Q1. When they say tab what are they talking about? What is a tab?
Q2. Does tabLabel mean Data Label, or are they different things?
Screenshot:
when editing the template in the GUI.
Q3. How can I add a "custom field" to my docusign template? I've tried to do it by clicking Custom Fields, and adding one. But it seems to be more of a field template than a specific custom field.
When I run the API call listCustomFields, it comes back empty.
var docusign = require('docusign-esign');
// Note: Following values are class members for readability and easy testing
// TODO: Enter your DocuSign credentials
var UserName = 'foo#email.com';
var Password = 'SECRET1';
// TODO: Enter your Integrator Key (aka API key), created through your developer sandbox preferences
var IntegratorKey = 'SECRET2';
// for production environment update to 'www.docusign.net/restapi'
var BaseUrl = 'https://demo.docusign.net/restapi';
var RequestSignatureFromTemplate = function () {
// TODO: Enter signer information and template info from a template in your account
var signerName = 'Bob';
var signerEmail = 'foo#email.com';
var subject = "testing 123";
var templateId = 'XXX';
var templateRoleName = 'Seller';
// initialize the api client
var apiClient = new docusign.ApiClient();
apiClient.setBasePath(BaseUrl);
// create JSON formatted auth header
var creds = '{"Username":"' + UserName + '","Password":"' + Password + '","IntegratorKey":"' + IntegratorKey + '"}';
apiClient.addDefaultHeader('X-DocuSign-Authentication', creds);
// assign api client to the Configuration object
docusign.Configuration.default.setDefaultApiClient(apiClient);
// ===============================================================================
// Step 1: Login() API
// ===============================================================================
// login call available off the AuthenticationApi
var authApi = new docusign.AuthenticationApi();
// login has some optional parameters we can set
var loginOps = new authApi.LoginOptions();
loginOps.setApiPassword('true');
loginOps.setIncludeAccountIdGuid('true');
authApi.login(loginOps, function (error, loginInfo, response) {
if (error) {
console.log('Error: ' + error);
return;
}
if (loginInfo) {
// list of user account(s)
// note that a given user may be a member of multiple accounts
var loginAccounts = loginInfo.getLoginAccounts();
console.log('LoginInformation: ' + JSON.stringify(loginAccounts));
// ===============================================================================
// Step 2: Create Envelope API (AKA Signature Request) from a Template
// ===============================================================================
// create a new envelope object that we will manage the signature request through
var envDef = new docusign.EnvelopeDefinition();
envDef.setEmailSubject(subject);
envDef.setTemplateId(templateId);
envDef.setTemplateRoles([
{email:'foo#email.com',
name:'bob',
roleName:'Seller',
// tabStatuses:[
// {tabStatus:[{
// tabLabel:'sellerName',
// tabValue:'test123'
// }]}
// ]
tabs:
{textTabs:[{
tabLabel:'sellerName',
tabName:'sellerName',
tabValue:'test123'
}]},
// tabStatuses:
// {textTabs:[{
// tabLabel:'sellerName',
// tabName:'sellerName',
// tabValue:'test123'
// }]}
}
]);
// console.log("eid", envDef.getEnvelopeId()); //undefined
//I commented out the following example code. I looked through the docusign-esign source and it didn't seem to have a way to add tabStatuses (whatever that means) so I used the above code instead. Which works as far as sending the email, but doesn't work for pre-filling the fields.
// create a template role with a valid templateId and roleName and assign signer info
// var tRole = new docusign.TemplateRole();
// tRole.setRoleName(templateRoleName);
// tRole.setName(signerName);
// tRole.setEmail(signerEmail);
//
// // create a list of template roles and add our newly created role
// var templateRolesList = [];
// templateRolesList.push(tRole);
//
// // assign template role(s) to the envelope
// envDef.setTemplateRoles(templateRolesList);
// send the envelope by setting |status| to "sent". To save as a draft set to "created"
envDef.setStatus('sent');
// use the |accountId| we retrieved through the Login API to create the Envelope
var loginAccount = new docusign.LoginAccount();
loginAccount = loginAccounts[0];
var accountId = loginAccount.accountId;
//it gets a little messy with junk experimental code. But what's not commented out is the same as the example, except I've added an additional callback in the deepest function.
// instantiate a new EnvelopesApi object
var envelopesApi = new docusign.EnvelopesApi();
// envelopesApi.getDocuments(loginAccount.accountId)
// call the createEnvelope() API
envelopesApi.createEnvelope(accountId, envDef, null, function (error, envelopeSummary, response) {
if (error) {
console.log('Error: ' + error);
return;
}
if (envelopeSummary) {
console.log('EnvelopeSummary: ' + JSON.stringify(envelopeSummary));
var envelopeId = envelopeSummary.envelopeId;
console.log("envelopeId", envelopeId);
// envelopesApi.listDocuments(accountId, envelopeId, function (error, data, response) {
// if (error) {console.log("error", error);return;}
// console.log("data", data);
// console.log("response", response);
// });
//envelopesApi.getDocument downloads the PDF binary 2.5MiB.
var documentId = '1';
var chunks=[];
envelopesApi.listCustomFields(accountId, envelopeId, function (error, data, response) {
if (error) {console.log("error", error);return;}
console.log("typeof data", typeof data);
// console.log("data.length", data.length);
// // console.log("response", response);
// response.on('data',chunk => chunks.push(chunk));
// response.on('end',()=>{
// var allChunks = chunks.join('');
// console.log("allChunks", allChunks);
// });
console.log("data", data);
// console.log("data.toJson()", data.toJson());
console.log("data.getTextCustomFields()", data.getTextCustomFields());
});
}
});
}
});
}; // end RequestSignatureFromTemplate()
When they say tab what are they talking about? What is a tab?
Tabs - aka fields or tags- can be added to documents and templates and are used several ways.
First they are used to indicate to a recipient where a signature or initials are required.
Second, they can be used to show data or information to recipients, such as dates, names, addresses, and other data.
Third, tabs can be used as editable information fields so you can retrieve data or information from your recipients
More information here
Does tabLabel mean Data Label, or are they different things?
Yes they are the same.
If you give tabs of the same type the same tabLabel when a recipient updates one tab it will update all the others with the same data in real-time.
More information here (see "Shared Tab Labels" section)
How can I add a "custom field" to my docusign template? I've tried to do it by clicking Custom Fields, and adding one. But it seems to be more of a field template than a specific custom field. When I run the API call listCustomFields, it comes back empty.
A "custom field" could mean several things.
See this answer for more information.
If you are looking for the Tabs on a document then you should explore the listEnvelopeTabs api
My template comes through fine, but the fields are not pre-filled.
If you are looking for pre-filled Fields (aka Tabs), you should set the "value" property in your request. More info here
Here is the raw Json request.
"tabs": {
"textTabs": [
{
"value": "$100",
"xPosition": "300",
"yPosition": "200",
"documentId": "1",
"pageNumber": "1"
}]
}

Resources