Skip to navigation

How to attach documents via binary transfer

View as Markdown

This topic demonstrates how to attach documents to an envelope via binary transfer.

Run this code example from our Quickstart or launcher projects: Bash, C#, Java, Node.js, PHP, PowerShell, Python, or Ruby.

Required data

Running the code in this how-to requires this data:

Data elementDescription
{API_ACCOUNT_ID}A GUID value that identifies your account. This value is automatically generated by Docusign for any account you create. Copy the value from the API Account ID field on the Apps and Keys page.
{BASE_PATH}A string value that forms the root of the URL required to make API calls. The base path value in the example code is set to target the developer environment at
https://<domain>/restapi
Where <domain> is demo.docusign.net for the developer environment and is the result of the GetUserInfo call in production.
{BOUNDARY_STRING}A string value that acts as a delimiter for multipart body data. This value should not be found in any documents or fields.
{CC_RECIPIENT_EMAIL}A string value for the email address of the carbon copy recipient.
{CC_RECIPIENT_NAME}A string value for the name of the carbon copy recipient.
{CLIENT_USER_ID}A string value that serves as an identifier of an individual signer throughout the signing process. The combination of this value, the signer’s name, and the signer’s email is used to uniquely identify them.
{DOCS_PATH}A string value for the file path to the folder containing the documents you want to include in the envelope.
Documents to be signedYou must provide at least one document to be signed. Documents used in this how-to:
  • DOCX file
  • PDF file
  • A third document in HTML is constructed dynamically by the sample code
{SIGNER_EMAIL}A string value for the email address where the signer will receive a notification of the signing request.
{SIGNER_NAME}A string value for the full name of the signer.

Step 1. Obtain your OAuth token

To make the API call shown in this how-to, you need a valid OAuth access token. Docusign supports access tokens for three different recommended OAuth grant types: Public Authorization Code Grant, Confidential Authorization Code Grant, and JSON Web Token (JWT) Grant. Choose the OAuth grant type appropriate for your scenario.

See Confidential Authorization Code Grant for guidance on your options to get an Confidential Authorization Code Grant OAuth token.

Three icons that represent the three methods a user can use to obtain an OAuth token: JSON Web Token (JWT), Public Authorization Code Grant (ACG), and Confidential Authorization Code grant

Step 2. Construct your API headers

After you have a valid OAuth access token, you are ready to construct the API headers that you will pass to the API call. Construct your headers like this, but make sure to substitute your valid OAuth access token for {ACCESS_TOKEN}.

boundary="multipartboundary_multipartboundary"
declare -a Headers=('--header' "Authorization: Bearer ${ACCESS_TOKEN}"
'--header' "Accept: application/json"
'--header' "Content-Type: multipart/form-data; boundary=${boundary}")

Step 3. Construct the request body

Create a custom envelope definition to apply multipart boundary string delimiters for your JSON request. This topic shows how to create a JSON envelope definition using a method, makeEnvelope, that:

  • Creates your multipart JSON request body object.

    • Begin a multipart body by first appending two hyphens, then the boundary separator. From there, append a CRLF (A carriage return/line feed, more commonly known as a line break or new line), then add the header "Content-Type: application/json"; make another CRLF, and then add the header "Content-Disposition: form data".
    • Now add two more CRLFs, one after another (which occurs to denote that the proceeding data is assumed to be of Content-Type text/plain). From there, insert the envelope JSON object.
  • Attaches multiple documents to the JSON envelope.

    • Add each file in bytes (specifically as an encoded byte array), with a correlated content disposition, into the request body. To do so, for each document, append your existing request body with the following sequence: Content-Type with the value being the MIME type, UTF-8 encoded, and then Content-Disposition as a file, also including attributes such as the filename and document ID, and finally the document in bytes.
  • Selects the appropriate MIME type and file attributes for your documents.

    Note:

    You must specify correct matching MIME-type attributes so you do not encounter errors when attempting to load the documents.

  • Specifies your CRLF boundary delimiter and applies it to your documents.

    • With all documents attached one after another, split by boundary delimiters, specify a closing boundary by appending a final set of CRLF, hyphens, boundary, hyphens, then ending CRLF.
  • Attaches multiple documents to the JSON envelope.

  • Sets signer and cc recipient data in the JSON envelope.

  • Creates a routing order for the documents in the JSON envelope. Documents are delivered to recipients in ascending order, as each previous document is signed and completed.

  • Creates and assigns signable fields to specific signers within the documents.

base_path="https://demo.docusign.net/restapi"
# temp files
request_data=$(mktemp /tmp/request-eg-010.XXXXXX)
response=$(mktemp /tmp/response-eg-010.XXXXXX)
doc1_path="demo_documents/doc_1.html"
doc2_path="demo_documents/World_Wide_Corp_Battle_Plan_Trafalgar.docx"
doc3_path="demo_documents/World_Wide_Corp_lorem.pdf"
echo ""
echo "Sending the envelope request to DocuSign..."
echo "The envelope has three documents. Processing time will be about 15 seconds."
echo "Results:"
echo ""
# Make the JSON part of the final request body
json='
{
"emailSubject": "Please sign this document set",
"documents": [
{
"name": "Order acknowledgement", "fileExtension": "html",
"documentId": "1"
},
{
"name": "Battle Plan", "fileExtension": "docx",
"documentId": "2"
},
{
"name": "Lorem Ipsum", "fileExtension": "pdf",
"documentId": "3"
}
],
"recipients": {
"signers": [
{
"email": "'"${SIGNER_EMAIL}"'",
"name": "'"${SIGNER_NAME}"'",
"recipientId": "1",
"routingOrder": "1",
"tabs": {
"signHereTabs": [
{
"anchorString": "**signature_1**",
"anchorYOffset": "10",
"anchorUnits": "pixels",
"anchorXOffset": "20"
},
{
"anchorString": "/sn1/",
"anchorYOffset": "10",
"anchorUnits": "pixels",
"anchorXOffset": "20"
}
]
}
}
],
"carbonCopies": [
{
"email": "'"${CC_EMAIL}"'",
"name": "'"${CC_NAME}"'",
"routingOrder": "2",
"recipientId": "2"
}
]
},
"status": "sent"
}'
# Assemble the multipart body
CRLF="\r\n"
# it is not easy to printf hyphens. See https://unix.stackexchange.com/q/22764/149244
hyphens_cmd='printf "--" --'
eval "$hyphens_cmd" > $request_data
printf "${boundary}" >> $request_data
printf "${CRLF}Content-Type: application/json" >> $request_data
printf "${CRLF}Content-Disposition: form-data" >> $request_data
printf "${CRLF}" >> $request_data
printf "${CRLF}${json}" >> $request_data
# Next add the documents. Each document has its own mime type,
# filename, and documentId. The filename and documentId must match
# the document's info in the JSON.
printf "${CRLF}" >> $request_data
eval "$hyphens_cmd" >> $request_data
printf "${boundary}" >> $request_data
printf "${CRLF}Content-Type: text/html" >> $request_data
printf "${CRLF}Content-Disposition: file; filename=\"Order acknowledgement\";documentid=1" >> $request_data
printf "${CRLF}" >> $request_data
printf "${CRLF}" >> $request_data
cat "$doc1_path" >> $request_data
printf "${CRLF}" >> $request_data
eval "$hyphens_cmd" >> $request_data
printf "${boundary}" >> $request_data
printf "${CRLF}Content-Type: application/vnd.openxmlformats-officedocument.wordprocessingml.document" >> $request_data
printf "${CRLF}Content-Disposition: file; filename=\"Battle Plan\";documentid=2" >> $request_data
printf "${CRLF}" >> $request_data
printf "${CRLF}" >> $request_data
cat "$doc2_path" >> $request_data
printf "${CRLF}" >> $request_data
eval "$hyphens_cmd" >> $request_data
printf "${boundary}" >> $request_data
printf "${CRLF}Content-Type: application/pdf" >> $request_data
printf "${CRLF}Content-Disposition: file; filename=\"Lorem Ipsum\";documentid=3" >> $request_data
printf "${CRLF}" >> $request_data
printf "${CRLF}" >> $request_data
cat "$doc3_path" >> $request_data
# Add closing boundary
printf "${CRLF}" >> $request_data
eval "$hyphens_cmd" >> $request_data
printf "${boundary}" >> $request_data
eval "$hyphens_cmd" >> $request_data
printf "${CRLF}" >> $request_data

Step 4. Call the eSignature REST API

With a completed request body taking some reference fields from the envelope JSON, you can send the envelope with the Envelopes:create method.

  • Send a POST request using the base path that injects your API account ID in the account_id portion of the URI.
  • Set the Authorization header to the OAuth2.0 bearer token, an Accept header to application/json, the Content-type to multipart/form-data, and the boundary to the specified delimiter variable in the prerequisite. Complete the request by passing in the completed request body.
  • Keep the code contained in a wrapper named worker, then run this worker method within a try/catch mechanism to handle any returned errors should any parameters be invalid or expired. By using a known template GUID and passing along appropriate template role parameters, you can return an envelope ID from the result.

View the source code for this how-to on GitHub: Bash, C#, Java, Node.js, PHP, PowerShell, Python, or Ruby.

Status=$(curl --request POST ${base_path}/v2.1/accounts/${account_id}/envelopes \
"${Headers[@]}" \
--data-binary @${request_data} \
--output ${response})

Expected response

If you run this code example from our Quickstart or launcher projects, you should see a JSON response similar to the code shown.

In addition, the signer receives an email containing a signing link that they can use to open and electronically sign a document using the Docusign mobile app or the Docusign website. After signing is complete, the recipient receives a carbon copy (CC) of the email that includes all of the completed and signed documents.

Sample response
{
"envelopeId": "eead435f-xxxx-xxxx-xxxx-25b7d8523d2b",
"uri": "/envelopes/eead435f-xxxx-xxxx-xxxx-25b7d8523d2b",
"statusDateTime": "2020-08-18T23:36:26.8830000Z",
"status": "sent"
}

Next steps