I'm requesting a signature by email using an existing template.
After using JWT grant for successful authorization, I call the api function docusign.EnvelopesApi(dsApiClient).createEnvelope with a new envelope including my templateId.
The call results in the error: {"errorCode":"TEMPLATE_ID_INVALID","message":"Invalid template ID."}
My server is authorized successfully,
I only have a single docu-sign admin user (myself)
The templateId is correct (i've double and tripped checked)
I'm on a paying account
async function main(){
const args = makeEnvelope({
email: "signer email",
name: "Signer name",
templateId: "some template id",
});
// Make the envelope request body
let envelope = makeEnvelope(args)
let results = await new docusign.EnvelopesApi(dsApiClient).createEnvelope(
accountInfo.apiAccountId, {envelopeDefinition: envelope});
return results;
}
function makeEnvelope(args){
let env = new docusign.EnvelopeDefinition();
env.templateId = args.templateId;
let signer = docusign.TemplateRole.constructFromObject({
email: args.signerEmail,
name: args.signerName,
roleName: 'signer'});
env.templateRoles = [signer];
env.status = "sent";
return env;
}
main();
This error can mean:
TemplateID is just wrong.
TemplateID is from production or developer account, but you are using developer account or production (mismatch)
TemplateID is from a different account then the one you authenticating to.
I cannot tell which one it is, you will have to contact support for this. But instead of just double-checking your ID, you need to also double check the env (prod vs. dev) as well as the accounts, make sure it's from the same account.
Related
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();
I'm running the following code in my nodejs server
// Create the recipient view, the Signing Ceremony
let viewRequest: RecipientViewRequest = {
returnUrl: "http://localhost:3000/fund/123?state=123",
authenticationMethod: "none",
email: "my_email",
userName: "Ryan",
clientUserId: "my client user id",
pingFrequency: "600",
pingUrl: "http://localhost:3000"
};
// Call the CreateRecipientView API
// Exceptions will be caught by the calling function
const dsApiClient = new ApiClient();
dsApiClient.setBasePath("https://account-d.docusign.com");
const api = new EnvelopesApi(dsApiClient);
const results = await api.createRecipientView(
"1234",
"5678",
{ recipientViewRequest: viewRequest }
);
and it keeps giving me the output of exports {} no errors or anything. this is pretty painful to debug. has anyone else ran into a similar problem? and how did you fix it?
When you use embedded signing you must set the clientUserId.
But, the clientUserId has to be set when the envelope is created, or when the recipient is added to an a draft envelope and must match the value you later pass in a request for a recipient View.
You cannot make a request for recipient view for an envelope that was created via the web app, unless your code modified that envelope to set the clientUserId for the recipient you want.
I need to send mails from a background application(worker service/azure function) using MSGraph API with Application permission. This is how I have initialized the GraphServiceClient to send emails.
var credentials = new ClientSecretCredential(
"TenantID",
"ClientId",
"ClientSecret",
new TokenCredentialOptions { AuthorityHost = AzureAuthorityHosts.AzurePublicCloud });
GraphServiceClient graphServiceClient = new GraphServiceClient(credentials);
var subject = $"Subject from demo code";
var body = $"Body from demo code";
// Define a simple e-mail message.
var email = new Microsoft.Graph.Message
{
Subject = subject,
Body = new ItemBody
{
ContentType = BodyType.Html,
Content = body
},
ToRecipients = new List<Recipient>()
{
new Recipient { EmailAddress = new EmailAddress { Address = "EmailId" }}
}
};
// Send mail as the given user.
graphServiceClient
.Users["UserID"]
.SendMail(email, true)
.Request()
.PostAsync().Wait();
How long the graphServiceClient will have a valid token and how to regenerate a token when the token is expired.
What are the best practices for this usage
The default lifetime of an access token is variable. When issued, an access token's default lifetime is assigned a random value ranging between 60-90 minutes (75 minutes on average). Please refer this DOC for more information.
The refresh tokens can be used to acquire access tokens if they expire, Refresh tokens are long-lived, and can be used to retain access to resources for extended periods of time.
For getting the access tokens with client secret please refer this method of getting the access tokens.
Hope this will help.
As of May 2022, there is no option to generate a refresh token while using client_credentials options.
For client_credentials option
It's possible to generate a refresh token while using on behalf of user
For on behalf of a user
I get the following error
Code: OrganizationFromTenantGuidNotFound
Message: The tenant for tenant guid 'tenantId' does not exist.
I created a .Net Core console app to send emails using the following 2 functions
I used the following namespaces
using Microsoft.Graph;
using Microsoft.Graph.Auth; //In .Net Core this is in preview only
using Microsoft.Identity.Client;
using Microsoft.IdentityModel.Clients.ActiveDirectory;
Common Email Message to be sent in both the functions
var message = new Message
{
Subject = "Meet for lunch?",
Body = new ItemBody
{
ContentType = BodyType.Html,
Content = "The new cafeteria is open."
},
ToRecipients = new List<Recipient>()
{
new Recipient
{
EmailAddress = new EmailAddress
{
Address = "my email id"
}
}
},
CcRecipients = new List<Recipient>()
{
new Recipient
{
EmailAddress = new EmailAddress
{
Address = "2nd email id"
}
}
}
};
Scope required in the following functions
string[] scopes = new string[] { "https://graph.microsoft.com/.default" };
1st Method
var confidentialClient = ConfidentialClientApplicationBuilder
.Create(clientId)
.WithClientSecret(clientSecret)
.WithAuthority(new Uri($"https://login.microsoftonline.com/{tenantId}/v2.0"))
.Build();
// Retrieve an access token for Microsoft Graph (gets a fresh token if needed).
var authResult = await confidentialClient
.AcquireTokenForClient(scopes)
.ExecuteAsync().ConfigureAwait(false);
var token = authResult.AccessToken;
// Build the Microsoft Graph client. As the authentication provider, set an async lambda
// which uses the MSAL client to obtain an app-only access token to Microsoft Graph,
// and inserts this access token in the Authorization header of each API request.
GraphServiceClient graphServiceClient =
new GraphServiceClient(new DelegateAuthenticationProvider(async (requestMessage) =>
{
// Add the access token in the Authorization header of the API request.
requestMessage.Headers.Authorization =
new AuthenticationHeaderValue("Bearer", token);
})
);
try
{
await graphServiceClient.Users["my user guid"]
.SendMail(message, false)
.Request()
.PostAsync();
//I also tried with
await graphServiceClient.Me
.SendMail(message, false)
.Request()
.PostAsync();
}
catch (Exception ex)
{
}
2nd Method
IConfidentialClientApplication confidentialClientApplication = ConfidentialClientApplicationBuilder
.Create(clientId)
.WithTenantId(tenantId)
.WithClientSecret(clientSecret)
.Build();
var authResultDirect = await confidentialClientApplication.AcquireTokenForClient(scopes).ExecuteAsync().ConfigureAwait(false);
//Microsoft.Graph.Auth is required for the following to work
ClientCredentialProvider authProvider = new ClientCredentialProvider(confidentialClientApplication);
GraphServiceClient graphClient = new GraphServiceClient(authProvider);
try
{
await graphClient.Users["my user id"]
.SendMail(message, false)
.Request()
.PostAsync();
//I also tried the following
await graphClient.Me
.SendMail(message, false)
.Request()
.PostAsync();
}
catch (Exception ex)
{
}
I have given all the required permissions. Some of the permissions are extra and may not be required. I gave the permissions to check if those permissions are the reason why I am getting the error but nothing changed.
I have also checked the token I am getting on jwt.io. I am getting the following roles
"roles": [
"Mail.ReadWrite",
"User.ReadWrite.All",
"Mail.ReadBasic.All",
"User.Read.All",
"Mail.Read",
"Mail.Send",
"Mail.ReadBasic"
],
I don't see any issue with the code or with the permissions that I have given but I am still missing something which I am unable to figure out. The reason why I say this is because when I tried to get user information by calling the api - https://graph.microsoft.com/v1.0/users, I get the users information as below.
value = [
{
"businessPhones": [],
"displayName": "user display name",
"givenName": "user first name",
"jobTitle": null,
"mail": null,
"mobilePhone": null,
"officeLocation": null,
"preferredLanguage": "en",
"surname": "user last name",
"userPrincipalName": "user information",
"id": "user id"
}
]
Any help is appreciated
This is because your Azure AD tenant does not have an Exchange online license under the O365 subscription.
As a result, your tenant does not have the ability to send Email messages.
If you have an o365 subscription, you'll see it here.
1.
2.
3.
#Chauncy Zhou was absolutely right with the solution.
But there are a couple of things you need to do if you are an individual because you will not get Office 365 license in your azure account as an individual.
I created a Developer.Microsoft.com account and then I used that account to create a new Azure account where I was able to add the license for Office for the Active Directory and that user. Rest of the code is already there and it works fine.
Here is my issue:
We integrated docusign in our application, server side with nodejs using this tutorial https://github.com/docusign/docusign-node-client ("OAuth JSON Web Token (JWT) Grant" section)
We have done the "Go Live Process": our application is registered in our production account
We have replaced the test config to the production config.
When we try to create an envelope, we get the following error:
PARTNER_AUTHENTICATION_FAILED: The specified Integrator Key was not found or is disabled. Invalid account specified for user
What am I doing wrong ?
async function docusignInit() {
var options;
var env = [40077,50077].indexOf(config.main.port) != -1 ? 'test' :'prod';
if (env == "test") {
options = {
basePath: restApi.BasePath.DEMO,
oAuthBasePath: oAuth.BasePath.DEMO
}
} else {
options = {
oAuthBasePath: "account.docusign.com",
// We called https://account.docusign.com/oauth/userinfo to found the uri
basePath:"https://eu.docusign.net/restapi/"
}
}
// in production, We must do
// var apiClient = new docusign.ApiClient(options.basePath);
// Otherwise, we get "Error: getaddrinfo ENOTFOUND undefined undefined:443"
var apiClient = new docusign.ApiClient(options.basePath);
var privateKeyFile = fs.readFileSync(`./server/docusign/keys/${env}/private.PEM`);
var res = await apiClient.requestJWTUserToken(config.docusign.integratorKey, config.docusign.userName, [oAuth.Scope.IMPERSONATION, oAuth.Scope.SIGNATURE], privateKeyFile, 3600)
var token = res.body.access_token;
apiClient.addDefaultHeader('Authorization', 'Bearer ' + token);
docusign.Configuration.default.setDefaultApiClient(apiClient);
await sendDocusign({
userId: 1,
firstName: 'foor',
lastName: 'bar',
email:'foo#bar;'
})
}
async function sendDocusign(role) {
var envDef = new docusign.EnvelopeDefinition();
envDef.emailSubject = 'Please signe this';
envDef.templateId = config.docusign.templateId;
var role = new docusign.TemplateRole();
role.roleName = "roleName";
role.clientUserId = role.userId;
role.name = role.firstName + " " + role.lastName;
role.email = role.email;
envDef.allowReassign = false;
envDef.templateRoles = [role];
envDef.status = 'sent';
var envelopesApi = new docusign.EnvelopesApi();
return await envelopesApi.createEnvelope(config.docusign.userAccountId, {
'envelopeDefinition': envDef
})
}
As you are able to generate AccesToken properly in PROD with PROD RSA KeyPair, so please check the endpoint which you using to make API calls to create an envelope. In demo it is always demo.docusign.net but in PROD it will be a different value depending on where you PROD account exists in the DocuSign data center. For instance if your PROD account is in NA1, then hostname will be will be www.docusign.net; if it is NA2 then hostname will be na2.docusign.net etc.
So it is recommended to make a /userinfo API call with the Access token to know the baseURI to make calls related to envelope. To get the base URI, call the /oauth/userinfo endpoint, supplying your application’s access token as a header.
For the developer sandbox environment, the URI is
https://account-d.docusign.com/oauth/userinfo
For the production environment, the URI is
https://account.docusign.com/oauth/userinfo
Documentation related to /userinfo API call is available here. Once you know you BaseURI then append this baseURI with envelopes related endpoint like below:
{base_uri} + "/restapi/v2.1/accounts/" + {account_id}
considering your error seems that you're missing the integratorKey or you're writing it in the wrontg way. According to that LINK is possible that you miss the brackets inside the intregrator key?
The integrator key must be placed in front of the user ID that is in
the Username node of the UsernameToken. The integrator key must be
wrapped with brackets, “[ and ]”.
An example of the api in the above documentation:
<soap:Header>
<wsa:Action>http://www.docusign.net/API/3.0/GetRecipientEsignList</wsa:Action>
<wsa:MessageID>uuid:3f9d7626-c088-43b4-b579-2bd5e8026b17</wsa:MessageID>
<wsa:ReplyTo>
<wsa:Address>http://schemas.xmlsoap.org/ws/2004/03/addressing/role/anonymous</wsa:Address>
</wsa:ReplyTo>
<wsa:To>http://demo.docusign.net/api/3.0/api.asmx</wsa:To>
<wsse:Security soap:mustUnderstand="1">
<wsu:Timestamp wsu:Id="Timestamp-8838aa24-9759-4f85-8bf2-26539e14f750">
<wsu:Created>2006-04-14T14:29:23Z</wsu:Created>
<wsu:Expires>2006-04-14T14:34:23Z</wsu:Expires>
</wsu:Timestamp>
<wsse:UsernameToken xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="SecurityToken-7c7b695e-cef7-463b-b05a-9e133ea43c41">
<wsse:Username>[Integrator Key Here]2988541c-4ec7-4245-b520-f2d324062ca3</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">password</wsse:Password>
<wsse:Nonce>SjlScsL5q3cC1CDWrcMx3A==</wsse:Nonce>
<wsu:Created>2006-04-14T14:29:23Z</wsu:Created>
</wsse:UsernameToken>
</wsse:Security>
</soap:Header>