I'm using the dev account and the demo.docusign.net site to test out the API. I want to create a template with a document that has custom data fields. I created a template and on the page where you drag fields on to the document, I created a custom field. I called it "Last Name". I saved the custom field and saved the template. Now I want to create a new document for signing through the API and populate that field. Using the Walkthroughs as a guide, I was able to create a new draft envelope from a template. I then wanted to populate the custom field with data. However, this is failing. I'm getting the following error:
{
"errorCode": "INVALID_REQUEST_BODY",
"message": "The request body is missing or improperly formatted."
}'
Below is my code based off the Walkthroughs. In addition to having a custom field attached at design time, I wanted to test dynamically adding a new custom field and modifying it as well. So, first I make a POST request to add a new field and set it using the Recipients/Tabs API. Then I make a GET request to get the Tabs for the recipient so I can capture the Tag ID. Then I make a PUT request to modify the field and that's where I get the error message. But the request body looks fine to me and it contains the only required field for TagId. I assume the only other needed field is one to set the value. The same request body works fine for the POST request. I just copied it and changed the fields. The POST works fine and I can validate the added field by opening it in the Console. The new field is there. It's just the PUT to modify that isn't working.
/////////////////////////////////////////////////////////////////////////////////////////////////
// STEP 1 - Add New Tab
/////////////////////////////////////////////////////////////////////////////////////////////////
$curl = curl_init($baseUrl . "/envelopes/" . $envelopeId . "/recipients/1/tabs" );
$data = array (
'textTabs' =>
array (
0 =>
array (
'documentId' => '1',
'pageNumber' => '1',
'tabLabel' => 'test tab',
'value' => 'test',
),
),
);
$data_string = json_encode($data);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $data_string);
curl_setopt($curl, CURLOPT_HTTPHEADER, array(
'Content-Type: application/json',
'Content-Length: ' . strlen($data_string),
"X-DocuSign-Authentication: $header" )
);
$json_response = curl_exec($curl);
$status = curl_getinfo($curl, CURLINFO_HTTP_CODE);
if ( $status != 201 ) {
echo "error calling webservice, status is:" . $status;
exit(-1);
}
$response = json_decode($json_response, true);
curl_close($curl);
//--- display results
/////////////////////////////////////////////////////////////////////////////////////////////////
// STEP 2 - Get recipient tab information
/////////////////////////////////////////////////////////////////////////////////////////////////
$curl = curl_init($baseUrl . "/envelopes/" . $envelopeId . "/recipients/1/tabs" );
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_HTTPHEADER, array(
"X-DocuSign-Authentication: $header" )
);
$json_response = curl_exec($curl);
$status = curl_getinfo($curl, CURLINFO_HTTP_CODE);
if ( $status != 200 ) {
echo "error calling webservice, status is:" . $status;
exit(-1);
}
$response = json_decode($json_response, true);
curl_close($curl);
$lastNameTabID = $response['textTabs'][0]['tabId'];
$testTabID = $response['textTabs'][1]['tabId'];
//--- display results
/////////////////////////////////////////////////////////////////////////////////////////////////
// STEP 3 - update tab value
/////////////////////////////////////////////////////////////////////////////////////////////////
$curl = curl_init($baseUrl . "/envelopes/" . $envelopeId . "/recipients/1/tabs" );
$data = array (
'textTabs' =>
array (
0 =>
array (
'tabId' => $testTabID,
'value' => 'Some Value',
),
),
);
$data_string = json_encode($data);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_PUT, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $data_string);
curl_setopt($curl, CURLOPT_HTTPHEADER, array(
'Content-Type: application/json',
'Content-Length: ' . strlen($data_string),
"X-DocuSign-Authentication: $header" )
);
$json_response = curl_exec($curl);
$status = curl_getinfo($curl, CURLINFO_HTTP_CODE);
if ( $status != 201 ) {
echo "error calling webservice, status is:" . $status;
exit(-1);
}
$response = json_decode($json_response, true);
curl_close($curl);
And here is the output of the Request Body
data_string= '{"textTabs":[{"tabId":"627883d0-542c-40c7-a58c-ce68d9e057e1","value":"Some Value"}]}'
I appreciate some guidance.
Thanks
Joe
I think this is easier than we think. You should be able to define the additional tag in the post to create the envelope. Below is part of my json to define a template role and text tabs. The first one is a field defined in the Template labeled "Company". The second one is a data field I'm adding on the fly and placing on the 3rd page with XY coordinates. You can also place this using anchor text.
"templateRoles": [
{
"tabs": {
"textTabs": [
{
"tabLabel": "Company",
"value": "Acme Inc"
},
{
"tabLabel": "business",
"value": "widgets",
"pageNumber": "3",
"documentId": "1",
"yPosition": "300",
"xPosition": "300",
"locked": false
}
]
},
"roleName": "Customer",
"name": "Customer Bob",
"email": "signerrob#outlook.com"
}
],
Alright, so I did a little digging and think I have what we need here. First, to get the Recipient ID as well as associated Tab ID's for the envelope, use the following GET: v2/accounts/:accountId/envelopes/:envelopeId/recipients. This will give you what you need to edit existing tags. Once you have the info here, you can use the PUT v2/accounts/:accountId/envelopes/:envelopeId/recipients/:recipientId/tabs to edit the tabs you're looking to edit. Here is a sample JSON request I sent using Postman to successfully update a text tabs value.
{
"textTabs": [
{
"tabId": "c75d32c4-8024-48c0-975a-acc232b20212",
"value": "ABC Corp",
}
]
}
To add tabs to that recipient, use the same URL as the edit, but use a POST.
Related
I am trying to achieve following things while interacting with AzureDevops using python:
To get the stories under Boards section
To get the branches under Repos section
I am able to establish connection to AzureDevops URL using requests API, but not sure how to read the data using it.
Is there any way by which I can do the same or if there is some other API using which I can do this?
Thanks in advance!!
Agree with Krzysztof Madej,
We could use write a WIQL query to list all User Story, you could refer this link for more details.
from vsts.vss_connection import VssConnection
from msrest.authentication import BasicAuthentication
import json
from vsts.work_item_tracking.v4_1.models.wiql import Wiql
def emit(msg, *args):
print(msg % args)
def print_work_item(work_item):
emit(
"{0} {1}: {2}".format(
work_item.fields["System.WorkItemType"],
work_item.id,
work_item.fields["System.Title"],
)
)
personal_access_token = 'YourPATToken'
organization_url = 'https://dev.azure.com/YourorgName'
# Create a connection to the org
credentials = BasicAuthentication('', personal_access_token)
connection = VssConnection(base_url=organization_url, creds=credentials)
wiql = Wiql(
query="""select [System.Id] From WorkItems """
)
wit_client = connection.get_client('vsts.work_item_tracking.v4_1.work_item_tracking_client.WorkItemTrackingClient')
wiql_results = wit_client.query_by_wiql(wiql).work_items
if wiql_results:
# WIQL query gives a WorkItemReference with ID only
# => we get the corresponding WorkItem from id
work_items = (
wit_client.get_work_item(int(res.id)) for res in wiql_results
)
for work_item in work_items:
print_work_item(work_item)
List all branches, we could use Refs - List and add variable filter to list all branches, If we do not add it, it will also list pull request.
Sample:
List all repo and get repo ID.
GET https://dev.azure.com/{Org name}/{Project name}/_apis/git/repositories?api-version=4.1
List repo branches via repo ID
GET https://dev.azure.com/{Org name}/{Project name}/_apis/git/repositories/{Repo ID}/refs?filter=heads&api-version=4.1
Result:
Update1
Power shell script
#List all branches name
$connectionToken="PAT"
$base64AuthInfo= [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($connectionToken)"))
$BranchDetailURL = "https://dev.azure.com/{Org name}/{Project name}/_apis/git/repositories/{Repo ID}/refs?filter=heads&?api-version=6.0"
$BranchInfo = Invoke-RestMethod -Uri $BranchDetailURL -Headers #{authorization = "Basic $base64AuthInfo"} -Method Get
Write-Host $BranchInfo.value.name
#List all User Story ID
$WorkItemWiqlQuery = "https://dev.azure.com/v-viliu/test_Agile/test/_apis/wit/wiql?api-version=5.1"
$query = "Select [System.Id], [System.Title], [System.State] From WorkItems Where [System.WorkItemType] = 'User Story'"
$body = #{query=$query} | ConvertTo-Json
$WorkItemDetailInfo = Invoke-RestMethod -Uri $WorkItemWiqlQuery -Method Post -ContentType "application/json" -Headers #{Authorization=("Basic $base64AuthInfo")} -Body $body
Write-Host $WorkItemDetailInfo.workItems.id
Result:
To get stories please check this answer but keep in mind to set proper filter [System.WorkItemType] = 'Task'".
To get branches you need to use Refs - List endpoint
GET https://dev.azure.com/{organization}/{project}/_apis/git/repositories/{repositoryId}/refs?api-version=6.0
Sample response
{
"value": [
{
"name": "refs/heads/feature/calcApp",
"objectId": "ffe9cba521f00d7f60e322845072238635edb451",
"creator": {
"displayName": "Normal Paulk",
"url": "https://vssps.dev.azure.com/fabrikam/_apis/Identities/ac5aaba6-a66a-4e1d-b508-b060ec624fa9",
"_links": {
"avatar": {
"href": "https://dev.azure.com/fabrikam/_apis/GraphProfile/MemberAvatars/aad.YmFjMGYyZDctNDA3ZC03OGRhLTlhMjUtNmJhZjUwMWFjY2U5"
}
},
"id": "ac5aaba6-a66a-4e1d-b508-b060ec624fa9",
"uniqueName": "dev#mailserver.com",
"imageUrl": "https://dev.azure.com/fabrikam/_api/_common/identityImage?id=ac5aaba6-a66a-4e1d-b508-b060ec624fa9",
"descriptor": "aad.YmFjMGYyZDctNDA3ZC03OGRhLTlhMjUtNmJhZjUwMWFjY2U5"
},
"url": "https://dev.azure.com/fabrikam/7484f783-66a3-4f27-b7cd-6b08b0b077ed/_apis/git/repositories/d3d1760b-311c-4175-a726-20dfc6a7f885/refs?filter=heads%2Ffeature%2FcalcApp"
},
{
"name": "refs/heads/feature/replacer",
"objectId": "917131a709996c5cfe188c3b57e9a6ad90e8b85c",
"creator": {
"displayName": "Normal Paulk",
"url": "https://vssps.dev.azure.com/fabrikam/_apis/Identities/ac5aaba6-a66a-4e1d-b508-b060ec624fa9",
"_links": {
"avatar": {
"href": "https://dev.azure.com/fabrikam/_apis/GraphProfile/MemberAvatars/aad.YmFjMGYyZDctNDA3ZC03OGRhLTlhMjUtNmJhZjUwMWFjY2U5"
}
},
"id": "ac5aaba6-a66a-4e1d-b508-b060ec624fa9",
"uniqueName": "dev#mailserver.com",
"imageUrl": "https://dev.azure.com/fabrikam/_api/_common/identityImage?id=ac5aaba6-a66a-4e1d-b508-b060ec624fa9",
"descriptor": "aad.YmFjMGYyZDctNDA3ZC03OGRhLTlhMjUtNmJhZjUwMWFjY2U5"
},
"url": "https://dev.azure.com/fabrikam/7484f783-66a3-4f27-b7cd-6b08b0b077ed/_apis/git/repositories/d3d1760b-311c-4175-a726-20dfc6a7f885/refs?filter=heads%2Ffeature%2Freplacer"
},
I have looked through the documentation available at -
https://learn.microsoft.com/en-us/rest/api/azure/devops/security/?view=azure-devops-rest-5.1
For a certain build definition, I want to be able to get all the security groups and users associated with it through code/powershell script and output it to a json file for example.
Any help will be appreciated! I have tried curling multiple api's but not getting what I need.
Thanks!
There has one api does not been documented. Try with below:
POST https://dev.azure.com/{org name}/_apis/Contribution/HierarchyQuery/project/{project name}?api-version=5.0-preview.1
Request body:
{
"contributionIds": [
"ms.vss-admin-web.security-view-members-data-provider"
],
"dataProviderContext": {
"properties": {
"permissionSetId": "33344d9c-fc72-4d6f-aba5-fa317101a7e9",
"permissionSetToken": "{token}",
"sourcePage": {
"url": "https://dev.azure.com/{org name}/{project name}/_build?definitionId={build definition id}&_a=summary",
"routeId": "ms.vss-build-web.pipeline-details-route",
"routeValues": {
"project": "{project name}",
"viewname": "details",
"controller": "ContributedPage",
"action": "Execute",
"serviceHost": "{org name}"
}
}
}
}
}
Some key points you should pay attention to:
permissionSetId: Here the 33344d9c-fc72-4d6f-aba5-fa317101a7e9 is
a fixed value which represent the namespaceid of build security.
permissionSetToken: This is the token which can used to get the
security info. You can run below command to get the token(s) you
should used.
az devops security permission list --id
33344d9c-fc72-4d6f-aba5-fa317101a7e9 --subject {your account}
--output table --organization https://dev.azure.com/{org name} --project {project name}
url: Here the url value used to tell the system which specific
build you want to check. Just replace the corresponding org
name/project name/definition id into the URL sample provided.
In addition, I wrote a shot powershell script for you:
$token = "{token}"
$url="https://dev.azure.com/{org name}/_apis/Contribution/HierarchyQuery/project/{project name}?api-version=5.0-preview.1"
$token = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($token)"))
$context=#"
{
"contributionIds": [
"ms.vss-admin-web.security-view-members-data-provider"
],
"dataProviderContext": {
"properties": {
"permissionSetId": "33344d9c-fc72-4d6f-aba5-fa317101a7e9",
"permissionSetToken": "{token}",
"sourcePage": {
"url": "https://dev.azure.com/{org name}/{project name}/_build?definitionId={build definition id}&_a=summary",
"routeId": "ms.vss-build-web.pipeline-details-route",
"routeValues": {
"project": "{project name}",
"viewname": "details",
"controller": "ContributedPage",
"action": "Execute",
"serviceHost": "{org name}"
}
}
}
}
}
"#
$response = Invoke-RestMethod -Uri $url -Headers #{Authorization = "Basic $token"} -Method Post -Body $context -ContentType "application/json"
Write-Host "results = $($response.dataProviders.'ms.vss-admin-web.security-view-members-data-provider'.identities.displayname| ConvertTo-Json -Depth 100)"
I have defined an entity named visible_objects in my Dialogflow agent.
In the Dialogflow console I have put one entry named placeholder2 with a synonym placeholder.
When a user starts interacting with the agent, I'm updating this entity via the projects.agent.sessions.entity patch request. Following is the content of the request I'm sending.
`{
"name": "projects\/{PROJECT_NAME}\/agent\/sessions\/{SESSION}\/entityTypes\/visible_objects",
"entityOverrideMode": "ENTITY_OVERRIDE_MODE_OVERRIDE",
"entities": [
{
"value": "door",
"synonyms": [
"door"
]
},
{
"value": "desk",
"synonyms": [
"desk"
]
},
{
"value": "test tubes",
"synonyms": [
"test tubes",
"test",
"tubes"
]
}
]
}`
And this is the code I'm using to generate it:
<?php
$json = file_get_contents('php://input');
$request = json_decode($json, true);
$df_action = $request['queryResult']['action'];
$df_contexts = $request['queryResult']['outputContexts'];
$df_parameters = $request['queryResult']['parameters'];
// taken from private_key in my GCP authentication .json file
$CLIENT_ACCESS_TOKEN = "-----BEGIN PRIVATE KEY-----xxxxxxxxxxxxxx---END PRIVATE KEY-----\n";
// loop through the visible objects and prepare the output for dialogflow
foreach($_SESSION['STORY']['VISIBLE_OBJECTS'] as $visible_object)
{
unset($synonyms); // clear any existing synonyms
$synonyms = array();
$synonyms[] = $visible_object['name'];
if (strpos($visible_object['name'], ' ', 1))
{ // multiple words so split it as synonyms
$sub_objects = explode(' ', $visible_object['name']);
foreach($sub_objects as $sub_object)
$synonyms[] = $sub_object;
}
// add the object to the user entity
$user_ent_objects[] = array('value'=>$visible_object['name'], 'synonyms'=>$synonyms);
}
// prepare user_entity
$user_entity = array('name'=>$request['session'] . '/entityTypes/visible_objects', 'entityOverrideMode'=>'ENTITY_OVERRIDE_MODE_OVERRIDE', 'entities'=>$user_ent_objects);
// log for debugging
file_put_contents($SITE_DIR . '/webhook/user-entity-visible-objects.txt', json_encode($user_entity,JSON_PRETTY_PRINT));
$ch = curl_init('https://dialogflow.googleapis.com/v2/' . $request['session'] . '/entityTypes/visible_objects');
curl_setopt($ch, CURLOPT_POST, true); // tell it we're posting
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json', 'Authorization: Bearer ' . $CLIENT_ACCESS_TOKEN)); // set the headers
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($user_entity)); // load our data
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$curl_response = curl_exec($ch); // execute it
?>
I have an intent which is "look on the object name", where object name is mapped to the visible_objects entity. Here's what I'm seeing for some example phrases:
look on the placeholder -> "placeholder" is detected as object name
look on the test -> no object name detected
look on the tubes -> no object name detected
look on the desk -> no object name detected
Based on these responses is appears the session entity is not being updated as the new values are not detected and similarly the old value placeholder2 is not overwritten.
My webhook is written in PHP, and I'm not using the Google SDK (it is only in alpha for PHP). I am capturing the response from the request curl_exec but nothing is being returned.
Using curl_getinfo I'm seeing the following:
`[url] => https://dialogflow.googleapis.com/v2/projects/escaperoom-447aa/agent/sessions/SESSION_ID_MASKED/entityTypes/visible_objects
[content_type] => text/html; charset=UTF-8
[http_code] => 400
[header_size] => 144
[request_size] => 2002
[filetime] => -1
[ssl_verify_result] => 0
[redirect_count] => 0
[total_time] => 0.072034
[namelookup_time] => 0.023728
[connect_time] => 0.031063
[pretransfer_time] => 0.065598
[size_upload] => 394
[size_download] => 0
[speed_download] => 0
[speed_upload] => 5472
[download_content_length] => 1555
[upload_content_length] => 394
[starttransfer_time] => 0.065659
[redirect_time] => 0
[redirect_url] =>
[primary_ip] => 216.58.192.234
[certinfo] => Array
(
)
[primary_port] => 443
[local_ip] => 66.198.240.46
[local_port] => 41442
`
Can anyone see what I'm doing wrong here?
The issue is that you're not setting $CLIENT_ACCESS_TOKEN to an access token. You're setting it to your private key which should be associated with a service account.
You will need to use that private key to generate an access token - it is not the access token itself. Since there is a service definition for the Dialogflow service, you can choose to just generate a signed JWT for the service.
I would like to execute inset table entity REST API in Table Storage Service but it doesn't work.
I referred this doc.
My request code is here,
<?php
// storage account name
$account = "mystgaccount";
$tablestoragename = "mytablename";
$accessKey = "myaccesskey";
$date = gmdate('D, d M Y H:i:s T',time());
$api_version = "2015-12-11";
$url = "https://$account.table.core.windows.net/$tablestoragename";
$method = "POST";
$body = '{"Address":"MountainView","Age":23,"AmountDue":200.23,"CustomerCode#odata.type":"Edm.Guid","CustomerCode":"c9da6455-213d-42c9-9a793e9149a57833","CustomerSince#odata.type":"Edm.DateTime","CustomerSince":"2008-0710T00:00:00","IsActive":true,"NumberOfOrders#odata.type":"Edm.Int64","NumberOfOrders":"255","PartitionKey":"mypartitionkey","RowKey":"myrowkey"}';
$stringToSign = [
// VERB
$method,
// Content-MD5
'',
// Content-Type
'',
// Date
$date,
];
$stringToSign = array_merge($stringToSign, ["/$account/$tablestoragename"]);
$stringToSign = implode("\n", $stringToSign);
$signature = base64_encode(hash_hmac('sha256', $stringToSign, base64_decode($accessKey), true));
$headers = [
"x-ms-date:{$date}",
"x-ms-version:$api_version",
"Authorization:SharedKey $account:{$signature}",
"Content-Type: application/json",
];
$ch = curl_init();
$options = array(
CURLOPT_URL => $url,
CURLOPT_HTTPHEADER => $headers,
CURLOPT_CUSTOMREQUEST => $method,
CURLOPT_SSL_VERIFYPEER => FALSE,
CURLOPT_RETURNTRANSFER => TRUE,
CURLOPT_POSTFIELDS => http_build_query($body),
);
curl_setopt_array($ch, $proxy_options);
curl_setopt_array($ch, $options);
$response = curl_exec($ch);
var_dump($response);
echo curl_error($ch);
curl_close($ch);
?>
Response
"<?xml version="1.0" encoding="utf-8"?><m:error xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"><m:code>AuthenticationFailed</m:code><m:message xml:lang="en-US">Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.
RequestId:b93fe560-0002-0028-129a-571361000000
Time:2017-11-07T07:34:13.3303714Z</m:message></m:error>"
I read related questions but it hasn't resolved yet :(
Do you have any ideas?
One possible reason for this error could be because of Content-Type header. You're specifying this header in your request but is not included in your $stringToSign. Please try again by changing your $stringToSign to something like:
$stringToSign = [
// VERB
$method,
// Content-MD5
'',
// Content-Type
'application/json',
// Date
$date,
];
With docusign is there a way to send custom data to the document.
The use-case we have is that we are having customers sign an embedded form. We populate all of their data from our Database.
So the main contract is the same but we need to send some values such as contract number, name, address, and price to the document we are having signed. What would be the best way to accomplish this?
I have seen customer tags mentioned for this purpose but it seems like we can only do this in classic view which makes it seem like this will not be a supported feature in the new version.
Update:
I am still at a stand still on this issue.
I have tried doing what was suggested and setting textCustomFields
However, no matter what I pass in the label I set up does not show up.
For example.
I have the Name field on my Document and I also have a Text Field with the Data Label of: contractid
Then I try passing the data in in my envelope as described in the documentation (I have yet to find an example of this anywhere)
string requestBody =
"<envelopeDefinition xmlns=\"http://www.docusign.com/restapi\">" +
"<status>sent</status>" +
"<emailSubject>DocuSign API - Embedded Signing example</emailSubject>" +
"<templateId>" + templateId + "</templateId>" +
"<templateRoles>" +
"<templateRole>" +
"<email>" + recipientEmail + "</email>" +
"<name>" + recipientName + "</name>" +
"<roleName>" + templateRole + "</roleName>" +
"<clientUserId>1</clientUserId>" + // user-configurable
"</templateRole>" +
"</templateRoles>" +
"<customFields>" +
"<textCustomFields>" +
"<fieldId>contractid</fieldId>" +
"<name>contractid</name>" +
"<required>true</required>" +
"<show>true</show>" +
"<value>123</value>" +
"</textCustomFields>" +
"</customFields>" +
"</envelopeDefinition>";
The name field shows up correctly in the contract, but that is a custom field predefined by Docusign
However, the contractid field just shows blank as no data has been passed into it.
I even tried adding the information into the call to my view for when I show the embeded contract and that does not do anything either.
I may be going about this the wrong way but so far I can find no good documentation on how to send custom data into the contract via the REST API.
Edit:
Here is a Screen Shot of my setup and I have attempted to add the Text Tabs into both the envelope and the document view request.
I have to say I have worked with Multiple Rest API's including working with Twilio, Phaxio, Twitter and this Rest API implementation seems to be the most confusing I have every ran across as far as what does what
We are working through our DocuSign implementation and are able to do what you are looking for with textTabs added to the signers object. I've attached my POC code in PowerShell that shows the tabs being formatted.
We generate contracts in Word 2013 and use anchors to place everything. The source document will have something like //SIGNATURE// in the text, but before release it is highlighted and changed to white font so the final contract renders nicely in DocuSign.
Results in this (except I chopped out the name and title)
Put your API Key and credentials into the logon function and set up the recipient info at the top. The script creates and sends an envelope with document called "contract.docx"
[string]$recipientEmail = "mr.mann#bluesbrothers.com"
[string]$recipientName = "Mr. Mann"
[string]$recipientFirstName = "Mann"
[string]$recipientTitle = "CEO, Mann, Inc."
function boundry {
[System.Guid]::NewGuid().ToString()
}
function encodeFile {
param ([string]$fileName)
[System.Convert]::ToBase64String([IO.File]::ReadAllBytes((Resolve-Path $fileName).ProviderPath))
}
function logonParams {
[string] $userName = 'YOUR USER NAME'
[string] $password = 'YOUR PASSWORD'
[string] $integratorKey = 'YOUR INTEGRATOR KEY'
#"
{
"Username" : "$userName",
"Password" : "$password",
"IntegratorKey" : "$integratorKey"
}
"#
}
function logon {
[string] $loginURL = 'https://demo.docusign.net/restapi/v2/login_information'
$headers =
#{
"X-DocuSign-Authentication"=$(logonParams);
"accept"="application/json";
"content-type"="application/json";
}
$r = Invoke-WebRequest -uri $loginURL -headers $headers -method GET
$responseInfo = $r.content | ConvertFrom-Json
$baseURL = $responseInfo.loginAccounts.baseURL
$baseURL
}
function createEnvelope {
param ([string]$contractFile,
[string]$baseURL
)
[string]$boundry = boundry
$headers =
#{
"X-DocuSign-Authentication"=$(logonParams);
"accept"="application/json";
"content-type"="multipart/form-data; boundary=$boundry";
}
[string]$formData = #"
--$boundry
Content-Type: application/json
{
"status":"sent",
"emailBlurb":"$recipientFirstName, Here is a test contract that I uploaded to DocuSign and routed through their webservice API.",
"emailSubject": "Test Contract $(date)",
"authoritativeCopy" : "true",
"documents": [
{
"name": "$contractFile",
"documentId":"1",
"order":"1"
}
],
"recipients": {
"signers" : [{
"email" : "$recipientEmail",
"name" : "$recipientName",
"title" : "$recipientTitle",
"recipientId":"1",
"tabs" : {
"signHereTabs" : [{
"anchorString" : "//SIGNATURE//"
}],
"fullNameTabs" : [{
"anchorString" : "//SIGNATURE_NAME//",
"font" : "Calibri",
"fontSize" : "Size11",
"anchorYOffset" : -10
}],
"titleTabs" : [{
"anchorString" : "//SIGNATURE_TITLE//",
"font" : "Calibri",
"fontSize" : "Size11",
"anchorYOffset" : -10
}],
"dateTabs" : [{
"anchorString" : "//SIGNATURE_DATE//",
"font" : "Calibri",
"fontSize" : "Size11",
"anchorYOffset" : -10
}],
"textTabs" : [
{
"anchorString" : "//INVOICE_NAME//",
"font" : "Calibri",
"fontSize" : "Size11",
"anchorYOffset" : -10,
"value" : "My Invoice Name",
},
{
"anchorString" : "//INVOICE_ADDRESS1//",
"font" : "Calibri",
"fontSize" : "Size11",
"anchorYOffset" : -10,
"value" : "My Invoice Address 1",
},
{
"anchorString" : "//INVOICE_ADDRESS2//",
"font" : "Calibri",
"fontSize" : "Size11",
"anchorYOffset" : -10,
"value" : "My Invoice Address 2",
},
{
"anchorString" : "//INVOICE_ADDRESS3//",
"font" : "Calibri",
"fontSize" : "Size11",
"anchorYOffset" : -10,
"value" : "My Invoice Address 3",
},
{
"anchorString" : "//INVOICE_EMAIL//",
"font" : "Calibri",
"fontSize" : "Size11",
"anchorYOffset" : -10,
"value" : "somebody#somewhere.com"
}
],
}
}]
}
}
--$boundry
Content-Type: application/vnd.openxmlformats-officedocument.wordprocessingml.document
Content-Transfer-Encoding: base64
Content-Disposition: file; filename="$mainFile";documentid=1
$(encodeFile $contractFile)
--$boundry--
"#
$envelopeURL = "$baseURL/envelopes"
Invoke-WebRequest -uri $envelopeURL -headers $headers -body $formData -method POST
}
$baseURL = logon
createEnvelope "contract.docx" $baseURL
For those using XML and trying to auto fill in the data
string requestBody =
"<envelopeDefinition xmlns=\"http://www.docusign.com/restapi\">" +
"<status>sent</status>" +
"<emailSubject>DocuSign API - Embedded Signing example</emailSubject>" +
"<templateId>" + templateId + "</templateId>" +
"<templateRoles>" +
"<templateRole>" +
"<email>" + recipientEmail + "</email>" +
"<name>" + recipientName + "</name>" +
"<roleName>" + templateRole + "</roleName>" +
"<clientUserId>1</clientUserId>" + // user-configurable
"<tabs>" +
"<textTabs>" +
"<text>" +
"<anchorString>follows:</anchorString>" +
"<value>Initial Data Goes</value>" +
"</text>" +
"</textTabs>" +
"</tabs>" +
"</templateRole>" +
"</templateRoles>" +
"</envelopeDefinition>";
Then anywhere in your document you have the words follows: you will have the text show up and you can modify it to display it where you want using other fields.
This would be done through the DocuSign API. You can build a template based on that contract and add the fields that needs data in them. Then when creating the envelope you can set the data that is populated within those fields.
More info can be found here.
EDIT:
Sample code can be found here
Custom Fields refer to Envelope Custom Fields which are an element that can be used to record information about the envelope, help search for envelopes and track information, not for tabs.
You'll want textTab:
<textTabs>
<text>
<anchorIgnoreIfNotPresent>sample string 35</anchorIgnoreIfNotPresent>
<anchorString>sample string 31</anchorString>
<anchorUnits>sample string 34</anchorUnits>
<anchorXOffset>sample string 32</anchorXOffset>
<anchorYOffset>sample string 33</anchorYOffset>
<conditionalParentLabel>sample string 39</conditionalParentLabel>
<conditionalParentValue>sample string 40</conditionalParentValue>
<documentId>sample string 26</documentId>
<pageNumber>sample string 28</pageNumber>
<recipientId>sample string 27</recipientId>
<tabId>sample string 36</tabId>
<templateLocked>sample string 37</templateLocked>
<templateRequired>sample string 38</templateRequired>
<xPosition>sample string 29</xPosition>
<yPosition>sample string 30</yPosition>
<bold>sample string 21</bold>
<font>sample string 20</font>
<fontColor>sample string 24</fontColor>
<fontSize>sample string 25</fontSize>
<italic>sample string 22</italic>
<tabLabel>sample string 19</tabLabel>
<underline>sample string 23</underline>
<concealValueOnDocument>sample string 16</concealValueOnDocument>
<disableAutoSize>sample string 17</disableAutoSize>
<locked>sample string 15</locked>
<maxLength>18</maxLength>
<name>sample string 10</name>
<originalValue>sample string 12</originalValue>
<required>sample string 14</required>
<value>sample string 11</value>
<width>13</width>
<requireAll>sample string 9</requireAll>
<requireInitialOnSharedChange>sample string 7</requireInitialOnSharedChange>
<senderRequired>sample string 8</senderRequired>
<shared>sample string 6</shared>
<validationMessage>sample string 5</validationMessage>
<validationPattern>sample string 4</validationPattern>
<formula>sample string 3</formula>
<height>1</height>
<isPaymentAmount>sample string 2</isPaymentAmount>
</text>
</textTabs>