Bad Request on Embedded Console Sign View - docusignapi

I have gone past 2 stages in the Embedded Signing API which I use in my WCF web service using C#.
The login credentials & the request envelope API calls work & the envelopeID is generated.
The 3rd step is the "get URL for the Embedded Console Sign View"
string reqBody = "<recipientViewRequest xmlns=\"http://www.docusign.com/restapi\">" +
"<authenticationMethod>" + "email" + "</authenticationMethod>" +
"<email>" + "jay.krishnamoorthy#gmail.com" + "</email>" + // NOTE: Use different email address if username provided in non-email format!
"<returnUrl>" + "http://www.docusign.com" + "</returnUrl>" + // username can be in email format or an actual ID string
"<clientUserId>" + "1001" + "</clientUserId>" +
"<userName>" + "Jay Krishnamoorthy" + "</userName>" +
"</recipientViewRequest>";
// append uri + "/views/recipient" to baseUrl and use in the request
request = (HttpWebRequest)WebRequest.Create(baseURL + uri + "/views/recipient");
request.Headers.Add("X-DocuSign-Authentication", authenticateStr);
request.ContentType = "application/xml";
request.Accept = "application/xml";
request.ContentLength = reqBody.Length;
request.Method = "POST";
// write the body of the request
byte[] body2 = System.Text.Encoding.UTF8.GetBytes(reqBody);
Stream dataStream2 = request.GetRequestStream();
dataStream2.Write(body2, 0, reqBody.Length);
dataStream2.Close();
// read the response
webResponse = (HttpWebResponse)request.GetResponse();-----> comes back with Bad request
Can some one help with the missing info in my request body which causes the BAD request response.

I'm having trouble making sense of the reqBody value in your question, so instead of commenting on that, I'll just provide a simple example of what a proper POST Recipient View request looks like (in XML format):
POST https://{{env}}.docusign.net/restapi/{{version}}/accounts/{{acctId}}/envelopes/{{envelopeId}}/views/recipient
<recipientViewRequest xmlns="http://www.docusign.com/restapi">
<authenticationMethod>Email</authenticationMethod>
<email>RECIPIENT_EMAIL_ADDRESS</email>
<returnUrl>http://www.google.com</returnUrl>
<clientUserId>CLIENT_USER_ID_VALUE_SPECIFIED_IN_THE_REQUEST</clientUserId>
<userName>RECIPIENT_NAME</userName>
</recipientViewRequest>
I'd suggest that you compare the request URI and request body I've included here with what you're sending, and adjust yours as needed to match.
Additionally, I'd recommend that you use a tool like "Fiddler" or something similar to examine the XML Request and Response as they're being sent over the wire -- i.e., identify problems by examining the raw XML using Fiddler, then update your code to fix the problems (i.e., to generate/send a properly formatted request). Being able to produce a trace of the raw XML Request / Response is a requirement of the DocuSign API Certification process, so you might as well figure that out sooner rather than later, as it's a valuable troubleshooting asset during development as well (when you get a "Bad Request" response like you're getting).

Your request body has all the proper elements and looks to be correct on first glance, however I see what you are doing wrong now. In your request body when you set the authentication method I see that you are setting it to:
"<authenticationMethod>" + "email" + "</authenticationMethod>"
This is incorrect. The value here actually needs to be the string email or Email, you don't enter the recipient's actual email address. The point of the authenticationMethod property is to tell the system what level of authentication you are expecting. If set to email then you are telling the system simply that the email address is the only form of authentication you want for that recipient. So what you want instead is:
"<authenticationMethod>email</authenticationMethod>"

Related

How to send a query to Azure Table REST API with Postman

I'm trying to make a GET request to Azure Table REST API with Postman.
I can make a working request with a C# program I found, but when I try to copy the same information into the Postman request it return the followign error:
Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.
With the C# program I generate my UTC time and my Authorization code.
The program will give me the following output:
x-ms-date: Fri, 01 Nov 2019 10:13:26 GMT
Authorization: SharedKeyLite username:e4IREMOVEDSOMELETTERST4Ag=
Request URI: https://username.table.core.windows.net/MainTable(PartitionKey='akey',RowKey='130')
The generated output works in the C# program, because when I use:
result = await Client.GetAsync(requestUri);
The result will give me the information of (akey, 130).
When I pass them into postman it will still give me an error.
I do update the date in postman whenever I make a new authorized string.
My postman setup is as follows:
I eventually want to make this request with the ESP32, so it might be a bit unrelated, but the ESP is giving me the same error. Any tips on setting the headers correct either for Postman or the ESP are appreciated.
to make this work first create two variables in your environment :
{{utcDate}}
{{authToken}}
Then create a new Get request and setup your headers like this :
x-ms-version 2015-12-11
x-ms-date {{utcDate}}
Authorization SharedKey resourceName:{{authToken}}
DataServiceVersion 3.0;NetFx
MaxDataServiceVersion 3.0;NetFx
Accept application/json;odata=nometadata
Finally, define a Pre-request Script :
var now = new Date().toUTCString();
pm.environment.set("utcDate", now);
var hcar = "/resourceName/TableName";
var verb = request.method;
var cntMd5 = "";
var cntType = "";
var mKey="<Your service key goes here>";
var text = verb + "\n" + (cntMd5 || "") + "\n" + (cntType || "") + "\n" + now + "\n" + hcar;
var key = CryptoJS.enc.Base64.parse(mKey);
var signature = CryptoJS.HmacSHA256(text, key);
var base64Bits = CryptoJS.enc.Base64.stringify(signature);
pm.environment.set("authToken", base64Bits);
The reason for the variables is, authToken because you need a place holder to store the calculated token, utcDate because the same date in your header must be used to calculate your token.
I found that the problem was within Postman itself.
There has been an ongoing issue with the automatic URL encoding.
When I went directly to the MainTable the code of Mauricio worked.

Azure Text to Speech started returning "400 Bad Request" all the sudden

I was using Azure Text-to-Speech API succesfully for months with this format:
<speak version='1.0' xmlns='w3.org/2001/10/synthesis' xml:lang='en-US'><voice name='Microsoft Server Speech Text to Speech Voice (fi-FI, HeidiRUS)'>My text</voice></speak>
But suddenly this request started returning:
HTTP/1.1 400 Bad request
We were using the same request successfully for months (with different phrase of course) but just some weeks ago the same request started returning this error. I don't get any additional information so I don't know where to look. Azure documentation says:
A required parameter is missing, empty, or null. Or, the value passed
to either a required or optional parameter is invalid. A common issue
is a header that is too long.
I also tried making the request more specific by adding gender and language and replacing single quotes with double quotes, but no use:
<speak version="1.0" xmlns="w3.org/2001/10/synthesis" xml:lang="fi-FI" xml:gender="Female"><voice name="Microsoft Server Speech Text to Speech Voice (fi-FI, HeidiRUS)">Text.</voice></speak>
Did something change in the API? Or what is missing in my request?
I got a 200 OK with the right content when I send the following payload:
<speak version='1.0' xmlns='http://www.w3.org/2001/10/synthesis' xml:lang='en-US'><voice name='Microsoft Server Speech Text to Speech Voice (fi-FI, HeidiRUS)'>This is my test</voice></speak>
Here is my C# code to send this:
// Generate request
string body = $#"<speak version='1.0' xmlns='http://www.w3.org/2001/10/synthesis' xml:lang='{voiceLang}'><voice name='{voiceName}'>{text}</voice></speak>";
using (var client = new HttpClient())
{
using (var request = new HttpRequestMessage())
{
// Set the HTTP method
request.Method = HttpMethod.Post;
// Construct the URI
request.RequestUri = new Uri(ttsHostUri);
// Set the content type header
request.Content = new StringContent(body, Encoding.UTF8, "application/ssml+xml");
// Set additional header, such as Authorization and User-Agent
request.Headers.Add("Authorization", "Bearer " + accessToken);
request.Headers.Add("Connection", "Keep-Alive");
// Update your resource name
request.Headers.Add("User-Agent", "YOUR_RESOURCE_NAME");
request.Headers.Add("X-Microsoft-OutputFormat", "riff-24khz-16bit-mono-pcm");
// Create a request
using (var response = await client.SendAsync(request).ConfigureAwait(false))
{
response.EnsureSuccessStatusCode();
// Asynchronously read the response
using (var dataStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false))
{
// ... Process your audio here
}
}
}
}
The only difference that I can see on our payloads is the xmlns value where I have a full url (with http://) whereas yours doesn't get it.
The error may be elsewhere: are you sure you are authenticating yourself when querying the endpoint?
We also suddenly got the 400 error and in our case we had missed to encapsulate the text for the XML request with
<![CDATA[ your text here ]]>
after we did that in our code we got no more reported 400 errors by the users.

Docusign Signing Groups

I created an account in the Docusign Sandbox to evaluate the product. My main goal is to create a signing group but before that I would like to get the list of signing groups with RestSharp.
[EDIT]
docusign.configureApiClient("https://demo.docusign.net/restapi");
var login = docusign.LoginDocusign(USERNAME, PASSWORD);
var client = new RestClient(login.BaseUrl);
var request = new RestRequest("signing_groups", Method.GET);
string authHeader = "{\"Username\":\"" + USERNAME + "\", \"Password\":\"" + PASSWORD + "\", \"IntegratorKey\":\"" + INTEGRATOR_KEY + "\"}";
request.AddHeader("X-DocuSign-Authentication", authHeader);
IRestResponse response = client.Execute(request);
var content = response.Content;
Debug.WriteLine(content);
However the content returns
error code : "ACCOUNT_LACKS_PERMISSIONS"
message: "This Account lacks sufficient permissions."
I thought demo accounts have almost the same permissions as a premium account. Is there a setting somewhere to enable this?
I am certain that the authentication is correct when I request for list of groups, the content returns all of my groups.
var request = new RestRequest("groups", Method.GET);
I'm not familiar with RestSharp, but my suspicion is that there's a problem with the request.
To diagnose: first start with making a call to DocuSign and use the Request Log facility to see what is being sent.
If the incoming request can't be matched to your account, or fails some initial filters, then the request will not reach your account. In that case, use requestb.in (free) to see what you're sending.
Also, I don't see where you are requesting the accountId and base URL from DocuSign. (Using https://demo.docusign.net/restapi/v2/login_information)
That's the first step for an API integration since you can't predict which platform the user's account is running on.

how to void an envelope using C# / XML?

Can anyone tell me how to fix this code, I just get an 400 error:
public string VoidEnvelope(string envelopeID)
{
string url = baseURL + "/envelopes/" + envelopeID;
string requestBody =
"<envelopeDefinition xmlns=\"http://www.docusign.com/restapi\">" +
"<status>voided</status>" +
"<voidedReason>user aborted</voidedReason>" +
"</envelopeDefinition>";
HttpWebRequest request = initializeRequest(url, "PUT", requestBody, email, password);
string response = getResponseBody(request);
return response;
}
When creating an envelope by doing a POST to the /envelopes URI the outer most XML element is defined as
<envelopeDefinition ...
However when modifying an existing envelope using a PUT, the outer most XML element is defined simply as
<envelope ...
So try something like this:
"<envelope>" +
"<status>voided</status>" +
"<voidedReason>user aborted</voidedReason>" +
"</envelope>";
A great resource that many people (including myself) forget about is the Rest API help page. That is probably your best way of learning the XML request bodies and all the potential nodes (it's also great for JSON!)
https://www.docusign.net/restapi/help

Using APIServiceSoapClient for DocuSign

Im tring to user the DocuSign api/sdk to send a document for someone to sign. The examples say something like:
//.NET
APIServiceSoapClient apiService = new APIServiceSoapClient();
apiService.ClientCredentials.UserName.UserName = "Your DocuSign UserName here";
apiService.ClientCredentials.UserName.Password = "Your DocuSign Password here";
Which I of course have tried but its not working.
I get the following error:
Security requirements are not satisfied because the security header is not present in the incoming message.
Ive tried
var username = "myemail";
var pass = "mypass";
var iteratorKey = "iteratorkey";
APIServiceSoapClient apiService = new APIServiceSoapClient();
apiService.ClientCredentials.UserName.UserName = username;
//also tried ...UserName = "[" + iteratorKey + "]" + username;
apiService.ClientCredentials.UserName.Password = pass;
Is this not where all security requirements are met? maybe? Using APIService not DSAPIService if that makes a difference.
I ended up having to use a different way to pass in the credentials. Which I found somewhere else. Im still not sure how to correctly use the other method I tried though so if anyone knows how to use the other method it would be great just because the code is neater and easier to follow.
string auth = #"<DocuSignCredentials>
<Username>email</Username>
<Password>pass</Password>
<IntegratorKey>key</IntegratorKey>
</DocuSignCredentials>";
DSAPIServiceSoapClient apiService = new DSAPIServiceSoapClient();
using (var scope = new System.ServiceModel.OperationContextScope(apiService.InnerChannel))
{
var httpRequestProperty = new System.ServiceModel.Channels.HttpRequestMessageProperty();
httpRequestProperty.Headers.Add("X-DocuSign-Authentication", auth);
System.ServiceModel.OperationContext.Current.OutgoingMessageProperties[System.ServiceModel.Channels.HttpRequestMessageProperty.Name] = httpRequestProperty;
EnvelopeStatus envStatus = apiService.CreateAndSendEnvelope(envelope);
return envStatus.EnvelopeID;
}
There are two ways to pass member credentials through DocuSign's SOAP API (as opposed to the newer REST API):
SOAP Header via WS-Security UsernameToken
HTTP Header via a custom field “X-DocuSign-Authentication”
The Account Management API only supports the HTTP Header authentication method, while all others can support either method.
Additionally, the DocuSign SOAP API has two API end points: API.asmx and DSAPI.asmx. The API.asmx end point requires the WS-Security UsernameToken in the SOAP header authentication. The DSAPI.asmx and AccountManagement.asmx end points require the HTTP Header authentication method.

Resources