I'm trying to duplicate the logic from this sample https://github.com/docusign/sample-app-loanco-nodejs/blob/master/routes/loan-sailboat.js in C#
I want to be able to capture two signatures for the same document (two different recipients), but am having trouble getting the second signature tab to show.
Here's a snippet:
Signer signer1 = new Signer {
Email = signerEmail,
Name = signerName,
ClientUserId = signerClientId,
RecipientId = "1",
RoutingOrder = "1"
};
Signer signer2 = new Signer
{
Email = "asdklfasdf#asdf.com",
Name = "bobby boucher",
ClientUserId = "2000",
RecipientId = "2",
RoutingOrder = "2"
};
// Create signHere fields (also known as tabs) on the documents,
// We're using anchor (autoPlace) positioning
//
// The DocuSign platform seaches throughout your envelope's
// documents for matching anchor strings.
SignHere signHere1 = new SignHere
{
XPosition = "170",
YPosition = "418",
Optional = "false",
StampType = "signature",
DocumentId = "3",
PageNumber = "1",
RecipientId = "1",
Name = "SignHere One",
};
SignHere signHere2 = new SignHere
{
XPosition = "200",
YPosition = "418",
Optional = "false",
StampType = "signature",
DocumentId = "3",
PageNumber = "1",
RecipientId = "2",
Name = "SignHere Two"
};
// Tabs are set per recipient / signer
Tabs signer1Tabs = new Tabs
{
SignHereTabs = new List<SignHere> { signHere1 }
};
signer1.Tabs = signer1Tabs;
Tabs signer2Tabs = new Tabs
{
SignHereTabs = new List<SignHere> { signHere2 }
};
signer2.Tabs = signer2Tabs;
// Add the recipient to the envelope object
Recipients recipients = new Recipients
{
Signers = new List<Signer> { signer1, signer2 }
};
envelopeDefinition.Recipients = recipients;
EDIT: The solution is to create two view requests to capture two unique signatures on a document simultaneously.
You have two signers, both with ClientUserId set, which means you create two views for them to both sign using embedded signing?
And after the first one signed, the second would sign.
This is probably the reason. If you want it done at the same time - set the RoutingOrder to both be "1".
If you want an email sent - remove the ClientUserId.
And of course, you need to two separate requests for the embedded signing - one for each signer.
Related
Can we send a DocuSign with multiple signature? I need to send a DocuSign with multiple signature field. One recipient has to sign one particular signature field and then send the same DocuSign has to another recipient and he has to sign other signature field keeping the previous recipient signature and so on and I have to set receipt programmatically. Is it possible? and how can I implement that? Is it possible on embedded signing?
Yes, it's possible, You add two recipients, two signers. You set the first one to routiner_order 1 and the second one to routing_order 2 to force the particular order. Here is some C# code, not sure which lang you use:
// Create a signer recipient to sign the document, identified by name and email
// We set the clientUserId to enable embedded signing for the recipient
// We're setting the parameters via the object creation
Signer signer1 = new Signer
{
Email = signerEmail,
Name = signerName,
ClientUserId = signerClientId,
RoutingOrder = "1",
RecipientId = "1"
};
Signer signer2 = new Signer
{
Email = signerEmail,
Name = signerName,
ClientUserId = signerClientId,
RoutingOrder = "2",
RecipientId = "2"
};
// Create signHere fields (also known as tabs) on the documents,
// We're using anchor (autoPlace) positioning
//
// The DocuSign platform seaches throughout your envelope's
// documents for matching anchor strings.
SignHere signHere1 = new SignHere
{
AnchorString = "/sn1/",
AnchorUnits = "pixels",
AnchorXOffset = "10",
AnchorYOffset = "20"
};
// The DocuSign platform seaches throughout your envelope's
// documents for matching anchor strings.
SignHere signHere2 = new SignHere
{
AnchorString = "/sn2/",
AnchorUnits = "pixels",
AnchorXOffset = "10",
AnchorYOffset = "20"
};
// Tabs are set per recipient / signer
Tabs signer2Tabs = new Tabs
{
SignHereTabs = new List<SignHere> { signHere2 }
};
signer2.Tabs = signer2Tabs;
Tabs signer1Tabs = new Tabs
{
SignHereTabs = new List<SignHere> { signHere1 }
};
signer1.Tabs = signer1Tabs;
My application is fairly simple: a user can upload a document from their computer, see an image of the document to scale on the webpage, and finally "add a signature" to the document.
The point at which the user clicks to add a signature is recorded with x/y location and page number.
The "Send" button should gather those points and apply a "sign here tab" from DocuSign and, of course, send to the specified recipient.
I can't find the documentation that would give me the ability to add a signing tab solely on the x/y coordinate. As suggested here: Can I place signature Tab dynamically in docusign documents
Is this possible?
How might that signing object look?
Here is C# code, but you can do that in other ways. Most tabs object have xPosition and yPosition properties you can use to specify coordinates.
SignHere signHere1 = new SignHere
{
XPosition = "170",
YPosition = "418",
Optional = "false",
StampType = "signature",
DocumentId = "3",
PageNumber = "1",
RecipientId = "1",
Name = "SignHere",
};
SignHere signHere2 = new SignHere
{
XPosition = "220",
YPosition = "418",
Optional = "false",
StampType = "signature",
DocumentId = "3",
PageNumber = "1",
RecipientId = "2",
Name = "SignHere"
};
I have a user and a supervisor.
The user will submit some information, which will be used to generate a document, create an envelope and send it to the user to sign. I add 2 signing fields, one for the user and one for the supervisor.
What I would like to do is instead of sending it on to the supervisor after a user signs, I would like to get all the documents for each user and create a new envelope and send that one to the supervisor. This will then only have one email to the supervisor instead of no: users.
Is there a way this can be done? I have been unable to find a way to complete this.
Below is what I am doing at the current moment. For the first signer they are redirected.
const doc1 = new docusign.Document();
doc1.documentBase64 = Buffer.from(htmlPage(args.htmlArgs)).toString('base64');
doc1.name = args.documentName;
doc1.fileExtension = 'html';
doc1.documentId = '1';
env.documents = [doc1];
const signer1 = docusign.Signer.constructFromObject({
email: args.htmlArgs.submitterEmail,
name: args.htmlArgs.submitterName,
clientUserId: 1,
recipientId: 1,
routingOrder: 1 });
// Signer 2 is the supervisor. Gets sent the document after signer 1 signs
const signer2 = docusign.Signer.constructFromObject({
email: args.htmlArgs.supervisorEmail,
name: args.htmlArgs.supervisorName,
recipientId: 2,
routingOrder: 2 });
const signHere1 = docusign.SignHere.constructFromObject({
anchorString: '**signature_1**',
anchorYOffset: '10', anchorUnits: 'pixels',
anchorXOffset: '20'});
const signHere2 = docusign.SignHere.constructFromObject({
anchorString: '**signature_2**',
anchorYOffset: '10', anchorUnits: 'pixels',
anchorXOffset: '20'});
// Tabs are set per recipient / signer
signer1.tabs = docusign.Tabs.constructFromObject({
signHereTabs: [signHere1]});
signer2.tabs = docusign.Tabs.constructFromObject({
signHereTabs: [signHere2]});
env.recipients = docusign.Recipients.constructFromObject({
signers: [signer1, signer2],
});
env.status = args.status;
This can be done.
There are multiple things to consider here:
RoutingOrder - you can use that to have users sign in the order you choose and the suprevisor last.
Document Visibly feature enables you to prevent user 1 from seeing user 2 documents if that's what you want.
Merge fields. the ability to get data into a document.
Using a template to nicely capture the repeatable process for all the above.
Would suggest to first do all of this without the API using the web app to understand the capabilities. If you can do it via web app - you can use the API to do the same. So that's a good way to know what can or cannot be done.
I am using Docusign SDK for NodeJS and below is sample code that I followed from nodejs github example.
let taxYear = docusign.Text.constructFromObject({
customTabId:"taxYear",
tabLabel: "taxYear",
value:"2018"
})
let signer1Tabs = docusign.Tabs.constructFromObject({
textTabs: [taxYear]
})
// Create a signer recipient for the signer role of the server template
let signer1 = docusign.Signer.constructFromObject({
email: args.signerEmail,
name: args.signerName,
roleName: "signer",
recipientId: "1",
// Adding clientUserId transforms the template recipient
// into an embedded recipient:
clientUserId: "1",
tabs: signer1Tabs
});
// Create the cc recipient
let cc1 = docusign.CarbonCopy.constructFromObject({
email: args.ccEmail,
name: args.ccName,
roleName: "cc",
recipientId: "2"
});
// Recipients object:
let recipientsServerTemplate = docusign.Recipients.constructFromObject({
carbonCopies: [cc1], signers: [signer1], });
// create a composite template for the Server Template
let compTemplate1 = docusign.CompositeTemplate.constructFromObject({
compositeTemplateId: "1",
serverTemplates: [
docusign.ServerTemplate.constructFromObject({
sequence: "1",
templateId: args.templateId
})
],
// Add the roles via an inlineTemplate
inlineTemplates: [
docusign.InlineTemplate.constructFromObject({
sequence: "1",
recipients: recipientsServerTemplate
})
]
})
// create the envelope definition
let env = docusign.EnvelopeDefinition.constructFromObject({
status: "sent",
compositeTemplates: [compTemplate1]
})
return env;
I have custom text field with tab label as taxYear but I am not seeing it getting posted in the form when envelop is sent out.
Here is the out put I am receiving
Not sure what I am missing!!!!!!
The Taxfield that you're using does not appear to have an X/Y location or anchor string attached to it -- so our system would not know where to place it.
For these fields to be added, you need to supply the documentId (if using x/y coordinates), recipientId, tabLabel, and either the x/y position or an anchor string to place it.
If adding those doesn't seem to do it, please edit your comment with the parameters specifically for the taxYear tab and we can have another look at it.
Note: I'm using the 'classic' experience because the new interface doesn't have a way for a template to set up required fields for future signers.
The workflow:
have a template with a bunch of fields
using the api:
create an envelope/document from the template, and assign a new user to sign (this document is going to be an agreement for signing up for a service)
create new role
set roleName to fake signer on template (because I can't configure fields without at least one signer on the template)
add textTabs to try to perfill some of the fields.
retrieve the recipients
create a recipient view so that I get the URL to put in an iframe
This is kind of obnoxious, because I don't care about having a first signer that isn't the user signing up for the service. I would however, like to have the the document be copied to someone after signing, but docusign doesn't appear to support this (that I've found anyway).
Here is the node.js code for the creation of the envelope (where I think my API usage is going wrong):
function createEnvelopeDefinition(templateId, userData) {
var envDef = new docusign.EnvelopeDefinition();
envDef.setEmailSubject('Signup Agreement');
envDef.setTemplateId(templateId);
var tRole = new docusign.TemplateRole();
tRole.setRoleName('RoleOne');
tRole.setName(userData.fullName);
tRole.setEmail(userData.email);
tRole.setClientUserId('2');
tRole.setTabs(new docusign.Tabs());
tRole.getTabs().setTextTabs([]);
const fieldsToPreFill = [
'field1',
'field2',
'field3',
'field4'];
fieldsToPreFill.forEach(fieldName => {
let textTab = new docusign.Text();
let value = userData[fieldName];
if (value === null || value === undefined) { value = 'not null'; }
textTab.setTabLabel(fieldName);
textTab.setValue(value);
tRole.getTabs().getTextTabs().push(textTab);
});
tRole = removeNulls(tRole);
envDef.setTemplateRoles([tRole]);
// send the envelope by setting |status| to 'sent'.
// To save as a draft set to 'created'
// sent is required for getting view URLs
envDef.setStatus('sent');
return envDef;
}
In the template editor on docusign, the Data Field Tag Properties show the label of each of the corresponding fields as field1, field2, etc.
These fields are now filled out with the provided values when I throw the new envelope in an iframe.
just for reference here is the rest of the code that creates the api connection, and gets the view URL
import ENV from 'environment/backend';
const accountId = ENV.docusign.accountId;
var Promise = require('bluebird');
var docusign = require('docusign-esign');
export function newApiClient() {
let apiClient = new docusign.ApiClient();
apiClient.setBasePath(ENV.docusign.endpoint);
// create JSON formatted auth header
let creds = JSON.stringify({
Username: ENV.docusign.email,
Password: ENV.docusign.password,
IntegratorKey: ENV.docusign.integratorKey
});
apiClient.addDefaultHeader('X-DocuSign-Authentication', creds);
// assign api client to the Configuration object
// this probably doesn't need to be set every time...
docusign.Configuration.default.setDefaultApiClient(apiClient);
return apiClient;
}
const defaultApiClient = newApiClient();
const envelopesApi = new docusign.EnvelopesApi();
const createEnvelope = Promise.promisify(envelopesApi.createEnvelope, { context: envelopesApi });
const listRecipients = Promise.promisify(envelopesApi.listRecipients, { context: envelopesApi });
const createRecipientView = Promise.promisify(envelopesApi.createRecipientView, { context: envelopesApi });
export default defaultApiClient;
// promise resolves to the view URL, envelopeId for the user.
// returns a recipientView
export function setupDocumentForEmbeddedSigning(templateId, userData) {
let envDefinition = createEnvelopeDefinition(templateId, userData);
return createEnvelope(accountId, envDefinition, null)
.then(envelopeSummary => {
const envelopeId = envelopeSummary.envelopeId;
return createViewFromEnvelope(envelopeId);
});
}
export function createViewFromEnvelope(envelopeId) {
return getRecipients(envelopeId).then(recipients => {
// the last signer is the one we added in the
// createEnvelopeDefinition step
let signers = recipients.signers;
let lastSigner = signers[signers.length - 1];
return createView(envelopeId, lastSigner)
.then(recipientView => [recipientView.url, envelopeId]);
});
}
function getRecipients(envelopeId) {
return listRecipients(accountId, envelopeId);
}
function createView(envelopeId, signerData) {
var viewRequest = new docusign.RecipientViewRequest();
viewRequest.setReturnUrl(ENV.host);
viewRequest.setAuthenticationMethod('email');
// recipient information must match embedded recipient info
// from the createEnvelopeDefinition method
viewRequest.setEmail(signerData.email);
viewRequest.setUserName(signerData.name);
viewRequest.setRecipientId('2');
viewRequest.setClientUserId('2');
return createRecipientView(accountId, envelopeId, viewRequest);
}
// bug with the api wrapper
// https://github.com/docusign/docusign-node-client/issues/47
const removeNulls = function(obj) {
var isArray = obj instanceof Array;
for (var k in obj) {
if (obj[k] === null) isArray ? obj.splice(k, 1) : delete obj[k];
else if (typeof obj[k] == 'object') removeNulls(obj[k]);
if (isArray && obj.length == k) removeNulls(obj);
}
return obj;
};
So, I may not fully understand where you're stuck, but I'll take a crack at this anyway...
Let's say I create a Template using the DocuSign UI and define two Recipient roles:
Signer1 (which will be the person who is signing up for your service) -- Action = "Sign"
CarbonCopy1 (which will be the person who gets a copy of the completed/signed documents once Signer1 signs) -- Action = "Receive a Copy"
(Note: these roles can be named whatever you want to name them -- I named them "Signer1" and "CarbonCopy1" so it'd be clear who each role represents.)
Assuming the above scenario, your Template's Recipient Roles (in the DocuSign UI) will look like this:
Next, let's assume that you define some fields (tabs) in the Template's document(s) (i.e., using the DocuSign UI) that the Signer1 recipient will need to populate when they sign the document(s). For this example, let's assume that the label (name) of one of those Text tabs is field1. Notice that the field is assigned to the Signer1 recipient:
Now, if I want to create an Envelope via the API that uses this Template, and pre-fill fields for one or more of the recipients, the key to doing that is using the "Composite Templates" structure in the API request. (See the Composite Templates section of this page for details.) In the example described above, your compositeTemplates object in the API request would contain a single serverTemplate object (which specifies the templateId and sequence=1), and a single inlineTemplate object (which specifies sequence=2 and the recipient info, including values for any tabs (fields) that you want to pre-fill).
In the example described above, the JSON API request to create the Envelope would look like this (assuming we're just pre-filling a single field for Signer1 -- obviously you could pre-fill additional fields by simply including them in the tabs object of the request along with field1):
POST https://{{env}}.docusign.net/restapi//v2/accounts/{{accountId}}/envelopes
{
"emailSubject": "Test Pre-fill Tabs",
"emailBlurb": "This is a test.",
"compositeTemplates": [{
"serverTemplates": [{
"sequence": "1",
"templateId": "CD0E6D53-3447-4A9E-BBAF-0EB2C78E8310"
}],
"inlineTemplates":[{
"sequence": "2",
"recipients": {
"signers": [
{
"roleName": "Signer1",
"recipientId": "1",
"name": "John Doe",
"email": "johndoe#test.com",
"clientUserId": "1234",
"tabs": {
"textTabs": [
{
"tabLabel": "field1",
"value": "TEST-123"
}
]
}
},
{
"roleName": "CarbonCopy1",
"recipientId": "2",
"name": "Jane Doe",
"email": "janedoe#test.com"
}
]
}
}]
}],
"status": "sent"
}
Once I create the Envelope using the above request, I execute a "POST Recipient View" request to get the signing URL for the first recipient (https://{{env}}.docusign.net/restapi//v2/accounts/{{accountId}}/envelopes/{{envelopeId/views/recipient).
Then, when I subsequently use the URL that's returned in that response to launch the signing session for Signer1 (John Doe), I see that the field1 tab is indeed pre-filled with the value that I specified in the "Create Envelope" API request (TEST-123):
Furthermore, once John Doe (Signer1) finishes signing and submits the completed documents, Jane Doe (CarbonCopy1) will be sent a copy.
I'm not familiar with the DocuSign Node SDK, but imagine you can figure out the syntax to use composite templates as shown in the above example. Hope this helps!