> You are reading the Docusign Developer Documentation. For clean Markdown of any page, append .md to the page URL.
>
> Documentation indexes by section:
> - APIs and SDKs: https://docusign.docs.buildwithfern.com/docs/llms.txt
> - Platform 101: https://docusign.docs.buildwithfern.com/platform/llms.txt
> - Extension Apps: https://docusign.docs.buildwithfern.com/extension-apps/llms.txt
> - Docusign CLI: https://docusign.docs.buildwithfern.com/docusign-cli/llms.txt
>
> Authentication (OAuth, JWT Grant, M2M): https://docusign.docs.buildwithfern.com/platform/auth
> Webhooks and Connect: https://docusign.docs.buildwithfern.com/platform/webhooks
>
> OpenAPI specifications: https://docusign.docs.buildwithfern.com/openapi.json
> MCP server: https://docusign.docs.buildwithfern.com/_mcp/server

# How to attach documents via binary transfer

> Demonstrates how to send documents using binary transfer rather than Base64 conversion.

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

> **Note**
>
> Run this code example from our [Quickstart](/docs/esign-rest-api/quickstart) or launcher projects: [Bash](https://github.com/docusign/code-examples-bash), [C#](https://github.com/docusign/code-examples-csharp), [Java](https://github.com/docusign/code-examples-java), [Node.js](https://github.com/docusign/code-examples-node), [PHP](https://github.com/docusign/code-examples-php), [PowerShell](https://github.com/docusign/code-examples-powershell), [Python](https://github.com/docusign/code-examples-python), or [Ruby](https://github.com/docusign/code-examples-ruby).

## Required data

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

| Data element           | Description                                                                                                                                                                                                                                                                                                                                                                                                               |
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| \{API_ACCOUNT_ID}      | A [GUID](http://guid.one/) 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](https://admindemo.docusign.com/authenticate?goTo=appsAndKeys) 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](/docs/esign-rest-api/esign101/concepts/envelopes).                                                                                                                                                                                                                                                          |
| Documents to be signed | You must provide at least one document to be signed. Documents used in this how-to:- [DOCX file](https://github.com/docusign/code-examples-java/blob/master/src/main/resources/World_Wide_Corp_Battle_Plan_Trafalgar.docx)
- [PDF file](https://github.com/docusign/code-examples-java/blob/master/src/main/resources/World_Wide_Corp_lorem.pdf)
- 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.

> **Note**
>
> See [Confidential Authorization Code Grant](/platform/auth/authcode#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](/_fern-files/_img/64f473773042ee439449a096bf7673292b1585b86a4ccc55f82ba0dda41f61a1.webp)

## 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}.

**`Bash`**

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

**`C#`**

```csharp title="C#"
string uri = basePath
        + "/v2.1/accounts/" + accountId + "/envelopes";
HttpWebRequest request = WebRequest.CreateHttp(uri);

request.Method = "POST";
request.Accept = "application/json";
request.ContentType = "multipart/form-data; boundary=" + Encoding.ASCII.GetString(boundary);
request.Headers.Add("Authorization", "Bearer " + accessToken);
```

**`Java`**

```java title="Java"
ApiClient apiClient = new ApiClient(basePath);
apiClient.addDefaultHeader(HttpHeaders.AUTHORIZATION, BEARER_AUTHENTICATION + userAccessToken);
```

**`Node.js`**

```javascript title="Node.js"
let options = {
        uri: `${args.basePath}/v2.1/accounts/${args.accountId}/envelopes`,
        method: 'POST',
        headers: {
            Accept: 'application/json',
            'Content-Type': `multipart/form-data; boundary=${boundary}`,
            Authorization: `Bearer ${args.accessToken}`
          },
        body: reqBody
    };
```

**`PHP`**

```php title="PHP"
$config = new Configuration();
$config->setHost($args['base_path']);
$config->addDefaultHeader('Authorization', 'Bearer ' . $args['ds_access_token']);
$this->apiClient = new ApiClient($config);
```

**`PowerShell`**

```text title="PowerShell"
$headers = @{
	'Authorization' = "Bearer $accessToken";
	'Content-Type'  = "multipart/form-data; boundary=${boundary}";
}
```

**`Python`**

```python title="Python"
headers = {
    "Authorization": "bearer " + args['access_token'],
    "Accept": "application/json",
    "Content-Type": f"multipart/form-data; boundary={boundary.decode('utf-8')}"
}
```

**`Ruby`**

```ruby title="Ruby"
header = {
  "Accept": 'application/json',
  "Authorization": "Bearer #{args[:access_token]}"
}
```

## 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.

**`Bash`**

```bash title="Bash"
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
```

**`C#`**

```csharp title="C#"
dynamic envelope = MakeEnvelope(signerEmail, signerName, ccEmail, ccName);

// Gather documents and their headeres
// Read files from a local directory
// The reads could raise an exception if the file is not available!
dynamic doc1 = envelope["documents"][0];
dynamic doc2 = envelope["documents"][1];
dynamic doc3 = envelope["documents"][2];

dynamic documents = new[]
{
    new
    {
        mime = "text/html",
        filename = (string)doc1["name"],
        documentId = (string)doc1["documentId"],
        bytes = Encoding.ASCII.GetBytes(Document1(signerEmail, signerName, ccEmail, ccName)),
    },
    new
    {
        mime = "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
        filename = (string)doc2["name"],
        documentId = (string)doc2["documentId"],
        bytes = System.IO.File.ReadAllBytes(docDocx),
    },
    new
    {
        mime = "application/pdf",
        filename = (string)doc3["name"],
        documentId = (string)doc3["documentId"],
        bytes = System.IO.File.ReadAllBytes(docPdf),
    },
};

// Create the multipart body
byte[] crlf = Encoding.ASCII.GetBytes("\r\n");
byte[] boundary = Encoding.ASCII.GetBytes("multipartboundary_multipartboundary");
byte[] hyphens = Encoding.ASCII.GetBytes("--");
```

**`Java`**

```java title="Java"
private static JSONObject makeEnvelopeJSON(
        String signerName,
        String signerEmail,
        String ccName,
        String ccEmail,
        List<DocumentInfo> documents) {
    // The DocuSign platform searches throughout your envelope's documents for
    // matching anchor strings. So the signHere2 tab will be used in both document
    // 2 and 3 since they use the same anchor string for their "signer 1" tabs.
    Tabs signerTabs = EnvelopeHelpers.createSignerTabs(
            EnvelopeHelpers.createSignHere("**signature_1**", ANCHOR_OFFSET_Y, ANCHOR_OFFSET_X),
            EnvelopeHelpers.createSignHere("/sn1/", ANCHOR_OFFSET_Y, ANCHOR_OFFSET_X));

    // create a signer recipient to sign the document, identified by name and email
    // RoutingOrder (lower means earlier) determines the order of deliveries
    // to the recipients. Parallel routing order is supported by using the
    // same integer as the order for two or more recipients.
    Signer signer = new Signer();
    signer.setEmail(signerEmail);
    signer.setName(signerName);
    signer.setRecipientId("1");
    signer.setRoutingOrder("1");
    signer.setTabs(signerTabs);

    // create a cc recipient to receive a copy of the documents, identified by name
    // and email
    CarbonCopy cc = new CarbonCopy();
    cc.setEmail(ccEmail);
    cc.setName(ccName);
    cc.setRecipientId("2");
    cc.setRoutingOrder("2");

    // The order in the documents array determines the order in the envelope
    JSONArray jsonDocuments = new JSONArray();
    for (DocumentInfo docInfo : documents) {
        JSONObject jsonDoc = new JSONObject();
        jsonDoc.put("name", docInfo.getName());
        jsonDoc.put("fileExtension", docInfo.getDocType().getDefaultFileExtention());
        jsonDoc.put("documentId", docInfo.getId());
        jsonDocuments.put(jsonDoc);
    }

    // Create the envelope definition. Request that the envelope be sent by
    // setting |status| to "sent". To request that the envelope be created
    // as a draft, set to "created"
    JSONObject envelopeJSON = new JSONObject();
    envelopeJSON.put("emailSubject", "Please sign this document set");
    envelopeJSON.put("documents", jsonDocuments);
    envelopeJSON.put("recipients", new JSONObject(EnvelopeHelpers.createRecipients(signer, cc)));
    envelopeJSON.put("status", EnvelopeHelpers.ENVELOPE_STATUS_SENT);

    return envelopeJSON;
}
```

**`Node.js`**

```javascript title="Node.js"
let envJSON = {};
envJSON.emailSubject = 'Please sign this document set';
// add the documents
let doc1 = {};
   let doc2 = {};
   let doc3 = {}
  ;
doc1.name = 'Order acknowledgement'; // can be different from actual file name
doc1.fileExtension = 'html'; // Source data format. Signed docs are always pdf.
doc1.documentId = '1'; // a label used to reference the doc
doc2.name = 'Battle Plan'; // can be different from actual file name
doc2.fileExtension = 'docx';
doc2.documentId = '2';
doc3.name = 'Lorem Ipsum'; // can be different from actual file name
doc3.fileExtension = 'pdf';
doc3.documentId = '3';
// The order in the docs array determines the order in the envelope
envJSON.documents = [doc1, doc2, doc3];
// create a signer recipient to sign the document, identified by name and email
// We're setting the parameters via the object creation
let signer1 = {
    email: args.signerEmail,
    name: args.signerName,
    recipientId: '1',
    routingOrder: '1'};
// routingOrder (lower means earlier) determines the order of deliveries
// to the recipients. Parallel routing order is supported by using the
// same integer as the order for two or more recipients.
// create a cc recipient to receive a copy of the documents, identified by name and email
// We're setting the parameters via setters
let cc1 = {};
cc1.email = args.ccEmail;
cc1.name = args.ccName;
cc1.routingOrder = '2';
cc1.recipientId = '2';
// Create signHere fields (also known as tabs) on the documents,
// We're using anchor (autoPlace) positioning
//
// The DocuSign platform searches throughout your envelope's
// documents for matching anchor strings. So the
// signHere2 tab will be used in both document 2 and 3 since they
// use the same anchor string for their "signer 1" tabs.
let signHere1 = {
    anchorString: '**signature_1**',
    anchorYOffset: '10', anchorUnits: 'pixels',
    anchorXOffset: '20'};
 let signHere2 = {
    anchorString: '/sn1/',
    anchorYOffset: '10', anchorUnits: 'pixels',
    anchorXOffset: '20'}
;
// Tabs are set per recipient / signer
let signer1Tabs = {signHereTabs: [signHere1, signHere2]};
signer1.tabs = signer1Tabs;
// Add the recipients to the envelope object
let recipients = {signers: [signer1], carbonCopies: [cc1]};
envJSON.recipients = recipients;
// Request that the envelope be sent by setting |status| to "sent".
// To request that the envelope be created as a draft, set to "created"
envJSON.status = 'sent';
```

**`PHP`**

```php title="PHP"
public static function sendBinaryDocs($args, $demoDocsPath, $clientService): array
{
    $envelope_args = $args["envelope_args"];
    # 1. Create the envelope JSON request object
    $envelope_JSON = SendBinaryDocsService::makeEnvelopeJson($envelope_args);

    # 2. Gather documents and their headers
    # Read files 2 and 3 from a local directory
    # The reads could raise an exception if the file is not available!
    # Note: the files are not binary encoded!
    $doc2_docx_bytes = file_get_contents($demoDocsPath . $GLOBALS['DS_CONFIG']['doc_docx']);
    $doc3_pdf_bytes = file_get_contents($demoDocsPath . $GLOBALS['DS_CONFIG']['doc_pdf']);

    $documents = [
        ['mime' => "text/html", 'filename' => $envelope_JSON['documents'][0]['name'],
         'document_id' => $envelope_JSON['documents'][0]['documentId'],
         'bytes' => $clientService->createDocumentForEnvelope($envelope_args)],
        ['mime' => "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
         'filename' => $envelope_JSON['documents'][1]['name'],
         'document_id' => $envelope_JSON['documents'][1]['documentId'],
         'bytes' => $doc2_docx_bytes],
        ['mime' => "application/pdf", 'filename' => $envelope_JSON['documents'][2]['name'],
         'document_id' => $envelope_JSON['documents'][2]['documentId'],
         'bytes' => $doc3_pdf_bytes]
    ];

    # Step 3. Create the multipart body
    $CRLF = "\r\n";
    $boundary = "multipartboundary_multipartboundary";
    $hyphens = "--";

    $req_body = ""
        . $hyphens . $boundary
        . $CRLF . "Content-Type: application/json"
        . $CRLF . "Content-Disposition: form-data"
        . $CRLF
        . $CRLF . json_encode($envelope_JSON, JSON_PRETTY_PRINT);

    # Loop to add the documents.
    # See section Multipart Form Requests on page
    # https://developers.docusign.com/esign-rest-api/guides/requests-and-responses
    foreach ($documents as $d) {
        $content_disposition = "Content-Disposition: file; filename=\"{$d['filename']}\";" .
            "documentid={$d['document_id']}";
        $req_body .= $CRLF . $hyphens . $boundary
            . $CRLF . "Content-Type: {$d['mime']}"
            . $CRLF . $content_disposition
            . $CRLF
            . $CRLF . $d['bytes'];
    }
    # Add closing $boundary
    $req_body .= $CRLF . $hyphens . $boundary . $hyphens . $CRLF;
public static function makeEnvelopeJson(array $args): array
{
    # create the envelope definition
    $env_json = [];
    $env_json['emailSubject'] = 'Please sign this document set';

    # add the documents
    $doc1 = [
        'name' => 'Order acknowledgement', # can be different from actual file name
        'fileExtension' => 'html', # Source data format. Signed docs are always pdf.
        'documentId' => '1' ]; # a label used to reference the doc
    $doc2 = [
        'name' => 'Battle Plan', 'fileExtension' => 'docx', 'documentId' => '2'];
    $doc3 = [
        'name' => 'Lorem Ipsum', 'fileExtension' => 'pdf', 'documentId' => '3'];
    # The order in the docs array determines the order in the envelope
    $env_json['documents'] = [$doc1, $doc2, $doc3];

    # create a signer recipient to sign the document, identified by name and email
    $signer1 = [
        'email' => $args['signer_email'], 'name' => $args['signer_name'],
        'recipientId' => '1', 'routingOrder' => '1'];
        # routingOrder (lower means earlier) determines the order of deliveries
        # to the recipients. Parallel routing order is supported by using the
        # same integer as the order for two or more recipients.

    # create a cc recipient to receive a copy of the documents, identified by name and email
    $cc1 = [
        'email' => $args['cc_email'], 'name' => $args['cc_name'],
        'routingOrder' => '2', 'recipientId' => '2'];

    # Create signHere fields (also known as tabs) on the documents,
    # We're using anchor (autoPlace) positioning
    #
    # The DocuSign platform searches throughout your envelope's
    # documents for matching anchor strings. So the
    # signHere2 tab will be used in both document 2 and 3 since they
    # use the same anchor string for their "signer 1" tabs.
    $sign_here1 = [
        'anchorString' => '**signature_1**', 'anchorYOffset' => '10', 'anchorUnits' => 'pixels',
        'anchorXOffset' => '20'];
    $sign_here2 = [
        'anchorString' => '/sn1/', 'anchorYOffset' => '10', 'anchorUnits' => 'pixels',
        'anchorXOffset' => '20'];

    # Tabs are set per recipient / signer
    $signer1_tabs = ['signHereTabs' => [$sign_here1, $sign_here2]];
    $signer1["tabs"] = $signer1_tabs;

    # Add the recipients to the envelope object
    $recipients = ['signers' => [$signer1], 'carbonCopies' => [$cc1]];
    $env_json['recipients'] = $recipients;

    # Request that the envelope be sent by setting |status| to "sent".
    # To request that the envelope be created as a draft, set to "created"
    $env_json['status'] = 'sent';

    return $env_json;
}
```

**`PowerShell`**

```text title="PowerShell"
function Add-OemContent {
	param(
		$destination,
		$content
	)
	Add-Content -Path $destination -Value $content -Encoding oem -NoNewline
}
# Construct the request body
#  document 1 (html) has tag **signature_1**
#  document 2 (docx) has tag /sn1/
#  document 3 (pdf) has tag /sn1/
#
#  The envelope has two recipients.
#  recipient 1 - signer
#  recipient 2 - cc
#  The envelope will be sent first to the signer.
#  After it is signed, a copy is sent to the cc person.

$apiUri = "https://demo.docusign.net/restapi"

# temp files
$requestData = New-TemporaryFile
$response = New-TemporaryFile

$doc1 = Get-Item ".\demo_documents\doc_1.html"
$doc2 = Get-Item ".\demo_documents\World_Wide_Corp_Battle_Plan_Trafalgar.docx"
$doc3 = Get-Item ".\demo_documents\World_Wide_Corp_lorem.pdf"

Write-Output "Sending the envelope request to Docusign..."
Write-Output "The envelope has three documents. Processing time will be about 15 seconds."
Write-Output "Results:"

$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"
} | ConvertTo-Json -Depth 32 -Compress;

$CRLF = "`r`n"
$boundary = "multipartboundary_multipartboundary"
Add-OemContent $requestData "--$boundary"
Add-OemContent $requestData "${CRLF}"
Add-OemContent $requestData "Content-Type: application/json"
Add-OemContent $requestData "${CRLF}"
Add-OemContent $requestData "Content-Disposition: form-data"
Add-OemContent $requestData "${CRLF}"
Add-OemContent $requestData "${CRLF}"
Add-OemContent $requestData $json
Add-OemContent $requestData "${CRLF}"

# 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.
Add-OemContent $requestData "--$boundary"
Add-OemContent $requestData "${CRLF}"
Add-OemContent $requestData "Content-Type: text/html"
Add-OemContent $requestData "${CRLF}"
Add-OemContent $requestData "Content-Disposition: file; filename=`"Order acknowledgement`";documentid=1"
Add-OemContent $requestData "${CRLF}"
Add-OemContent $requestData "${CRLF}"
Add-OemContent $requestData (Get-Content $doc1 -Encoding oem)
Add-OemContent $requestData "${CRLF}"

Add-OemContent $requestData "--$boundary"
Add-OemContent $requestData "${CRLF}"
Add-OemContent $requestData "Content-Type: application/vnd.openxmlformats-officedocument.wordprocessingml.document"
Add-OemContent $requestData "${CRLF}"
Add-OemContent $requestData "Content-Disposition: file; filename=`"Battle Plan`";documentid=2"
Add-OemContent $requestData "${CRLF}"
Add-OemContent $requestData "${CRLF}"
Add-OemContent $requestData (Get-Content $doc2 -Encoding oem -Raw)
Add-OemContent $requestData "${CRLF}"

Add-OemContent $requestData "--$boundary"
Add-OemContent $requestData "${CRLF}"
Add-OemContent $requestData "Content-Type: application/pdf"
Add-OemContent $requestData "${CRLF}"
Add-OemContent $requestData "Content-Disposition: file; filename=`"Lorem Ipsum`";documentid=3"
Add-OemContent $requestData "${CRLF}"
Add-OemContent $requestData "${CRLF}"
Add-OemContent $requestData (Get-Content $doc3 -Encoding oem -Raw)
Add-OemContent $requestData "${CRLF}"

# Add closing boundary
Add-OemContent $requestData "--$boundary--"
Add-OemContent $requestData "${CRLF}"
```

**`Python`**

```python title="Python"
envelope_json = cls.make_envelope_json(args["envelope_args"])

# Gather documents and their headers
# Read files 2 and 3 from a local directory
# The reads could raise an exception if the file is not available!
# Note: the fles are not binary encoded!
with open(path.join(demo_docs_path, DS_CONFIG["doc_docx"]), "rb") as file:
    doc2_docx_bytes = file.read()
with open(path.join(demo_docs_path, DS_CONFIG["doc_pdf"]), "rb") as file:
    doc3_pdf_bytes = file.read()

documents = [
    {"mime": "text/html", "filename": envelope_json["documents"][0]["name"],
     "document_id": envelope_json["documents"][0]["documentId"],
     "bytes": cls.create_document1(args["envelope_args"]).encode("utf-8")},
    {"mime": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
     "filename": envelope_json["documents"][1]["name"],
     "document_id": envelope_json["documents"][1]["documentId"],
     "bytes": doc2_docx_bytes},
    {"mime": "application/pdf", "filename": envelope_json["documents"][2]["name"],
     "document_id": envelope_json["documents"][2]["documentId"],
     "bytes": doc3_pdf_bytes}
]

# Create the multipart body
CRLF = b"\r\n"
boundary = b"multipartboundary_multipartboundary"
hyphens = b"--"

req_body = b"".join([
    hyphens, boundary,
    CRLF, b"Content-Type: application/json",
    CRLF, b"Content-Disposition: form-data",
    CRLF,
    CRLF, json.dumps(envelope_json, indent=4).encode("utf-8")])

# Loop to add the documents.
# See section Multipart Form Requests on page
# https://developers.docusign.com/esign-rest-api/guides/requests-and-responses
for d in documents:
    content_disposition = (f"Content-Disposition: file; filename={d['filename']};" +
                           f"documentid={d['document_id']}").encode("utf-8")
    req_body = b"".join([req_body,
                         CRLF, hyphens, boundary,
                         CRLF, f"Content-Type: {d['mime']}".encode("utf-8"),
                         CRLF, content_disposition,
                         CRLF,
                         CRLF, d["bytes"]])

# Add closing boundary
req_body = b"".join([req_body, CRLF, hyphens, boundary, hyphens, CRLF])
    @classmethod
    def make_envelope_json(cls, args):
"""
Create envelope JSON
<br />Document 1: An HTML document.
<br />Document 2: A Word .docx document.
<br />Document 3: A PDF document.
<br />DocuSign will convert all of the documents to the PDF format.
<br />The recipients" field tags are placed using <b>anchor</b> strings.
@param {Object} args parameters for the envelope:
  <tt>signerEmail</tt>, <tt>signerName</tt>, <tt>cc_email</tt>, <tt>cc_name</tt>
@returns {Envelope} An envelope definition
"""

# document 1 (html) has tag **signature_1**
# document 2 (docx) has tag /sn1/
# document 3 (pdf) has tag /sn1/
#
# The envelope has two recipients.
# recipient 1 - signer
# recipient 2 - cc
# The envelope will be sent first to the signer.
# After it is signed, a copy is sent to the cc person.

# create the envelope definition
env_json = {
    "emailSubject": "Please sign this document set"
}
# add the documents
doc1 = {
    "name": "Order acknowledgement",  # can be different from actual file name
    "fileExtension": "html",  # Source data format. Signed docs are always pdf.
    "documentId": "1"}  # a label used to reference the doc
doc2 = {
    "name": "Battle Plan", "fileExtension": "docx", "documentId": "2"}
doc3 = {
    "name": "Lorem Ipsum", "fileExtension": "pdf", "documentId": "3"}
# The order in the docs array determines the order in the envelope
env_json["documents"] = [doc1, doc2, doc3]

# create a signer recipient to sign the document, identified by name and email
signer1 = {
    "email": args["signer_email"], "name": args["signer_name"],
    "recipientId": "1", "routingOrder": "1"}
# routingOrder (lower means earlier) determines the order of deliveries
# to the recipients. Parallel routing order is supported by using the
# same integer as the order for two or more recipients.

# create a cc recipient to receive a copy of the documents, identified by name and email
cc1 = {
    "email": args["cc_email"], "name": args["cc_name"],
    "routingOrder": "2", "recipientId": "2"}

# Create signHere fields (also known as tabs) on the documents,
# We"re using anchor (autoPlace) positioning
#
# The DocuSign platform searches throughout your envelope"s
# documents for matching anchor strings. So the
# signHere2 tab will be used in both document 2 and 3 since they
# use the same anchor string for their "signer 1" tabs.
sign_here1 = {
    "anchorString": "**signature_1**", "anchorYOffset": "10", "anchorUnits": "pixels",
    "anchorXOffset": "20"}
sign_here2 = {
    "anchorString": "/sn1/", "anchorYOffset": "10", "anchorUnits": "pixels",
    "anchorXOffset": "20"}

# Tabs are set per recipient / signer
signer1_tabs = {"signHereTabs": [sign_here1, sign_here2]}
signer1["tabs"] = signer1_tabs

# Add the recipients to the envelope object
recipients = {"signers": [signer1], "carbonCopies": [cc1]}
env_json["recipients"] = recipients

# Request that the envelope be sent by setting |status| to "sent".
# To request that the envelope be created as a draft, set to "created"
env_json["status"] = "sent"

return env_json

    @classmethod
    def create_document1(cls, args):
""" Creates document 1 -- an html document"""

return f"""
<!DOCTYPE html>
<html>
    <head>
      <meta charset="UTF-8">
    </head>
    <body style="font-family:sans-serif;margin-left:2em;">
    <h1 style="font-family: "Trebuchet MS", Helvetica, sans-serif;
        color: darkblue;margin-bottom: 0;">World Wide Corp</h1>
    <h2 style="font-family: "Trebuchet MS", Helvetica, sans-serif;
      margin-top: 0px;margin-bottom: 3.5em;font-size: 1em;
      color: darkblue;">Order Processing Division</h2>
    <h4>Ordered by {args["signer_name"]}</h4>
    <p style="margin-top:0em; margin-bottom:0em;">Email: {args["signer_email"]}</p>
    <p style="margin-top:0em; margin-bottom:0em;">Copy to: {args["cc_name"]}, {args["cc_email"]}</p>
    <p style="margin-top:3em;">
        Candy bonbon pastry jujubes lollipop wafer biscuit biscuit. Topping brownie sesame snaps sweet roll pie.
        Croissant danish biscuit soufflé caramels jujubes jelly. Dragée danish caramels lemon drops dragée.
        Gummi bears cupcake biscuit tiramisu sugar plum pastry. Dragée gummies applicake pudding liquorice.
        Donut jujubes oat cake jelly-o.
        Dessert bear claw chocolate cake gummies lollipop sugar plum ice cream gummies cheesecake.
    </p>
    <!-- Note the anchor tag for the signature field is in white. -->
    <h3 style="margin-top:3em;">Agreed: <span style="color:white;">**signature_1**/</span></h3>
    </body>
</html>
      """
```

**`Ruby`**

```ruby title="Ruby"
def make_envelope_json(envelope_args)
  # document 1 (HTML) has tag **signature_1**
  # document 2 (DOCX) has tag /sn1/
  # document 3 (PDF) has tag /sn1/
  #
  # The envelope has two recipients.
  # recipient 1 - signer
  # recipient 2 - cc
  # The envelope will be sent first to the signer
  # After it is signed, a copy is sent to the cc person

  # Create the envelope definition
  env_json = {} # DocuSign_eSign::EnvelopeDefinition.new

  puts env_json[:emailSubject] = 'Please sign this document set'

  # Add the documents
  doc1 = {}
  doc2 = {}
  doc3 = {}

  puts doc1[:name] = 'Order acknowledgement' # Can be different from actual file name
  puts doc1[:fileExtension] = 'html' # Source data format. Signed docs are always PDF
  puts doc1[:documentId] = '1' # A label used to reference the doc
  puts doc2[:name] = 'Battle Plan' # Can be different from actual file name
  puts doc2[:fileExtension] = 'docx'
  puts doc2[:documentId] = '2'
  puts doc3[:name] = 'Lorem Ipsum' # Can be different from actual file name
  puts doc3[:fileExtension] = 'pdf'
  puts doc3[:documentId] = '3'

  puts env_json[:documents] = [doc1, doc2, doc3]
  # Create a signer recipient to sign the document, identified by name and email
  # We're setting the parameters via the object creation
  signer1 = DocuSign_eSign::Signer.new
  signer1.email = envelope_args[:signer_email]
  signer1.name = envelope_args[:signer_name]
  signer1.recipient_id = '1'
  signer1.routing_order = '1'
  # routingOrder (lower means earlier) determines the order of deliveries
  # to the recipients. Parallel routing order is supported by using the
  # same integer as the order for two or more recipients

  # Create a cc recipient to receive a copy of the documents, identified by name and email
  # We're setting the parameters via setters
  cc1 = DocuSign_eSign::CarbonCopy.new(
    email: envelope_args[:cc_email],
    name: envelope_args[:cc_name],
    routingOrder: '2',
    recipientId: '2'
  )
  # Create signHere fields (also known as tabs) on the documents,
  # We're using anchor (autoPlace) positioning
  #
  # The Docusign platform searches throughout your envelope's documents for matching
  # anchor strings. So the sign_here_2 tab will be used in both document 2 and 3
  # since they use the same anchor string for their "signer 1" tabs.
  sign_here1 = DocuSign_eSign::SignHere.new({
                                              anchorString: '**signature_1**',
                                              anchorYOffset: '10',
                                              anchorUnits: 'pixels',
                                              anchorXOffset: '20'
                                            })

  sign_here2 = DocuSign_eSign::SignHere.new({
                                              anchorString: '/sn1/',
                                              anchorYOffset: '10',
                                              anchorUnits: 'pixels',
                                              anchorXOffset: '20'
                                            })
  # Tabs are set per recipient/signer
  signer1_tabs = DocuSign_eSign::Tabs.new({
                                            signHereTabs: [sign_here1, sign_here2]
                                          })

  signer1.tabs = signer1_tabs

  recipients = DocuSign_eSign::Recipients.new(
    signers: [signer1],
    carbonCopies: [cc1]
  )

  puts env_json[:recipients] = recipients
  puts env_json[:status] = 'sent'
  env_json
end

def create_document1(args)
  "
  <!DOCTYPE html>
  <html>
      <head>
        <meta charset=\"UTF-8\">
      </head>
      <body style=\"font-family:sans-serif;margin-left:2em;\">
      <h1 style=\"font-family: 'Trebuchet MS', Helvetica, sans-serif;
color: darkblue;margin-bottom: 0;\">World Wide Corp</h1>
      <h2 style=\"font-family: 'Trebuchet MS', Helvetica, sans-serif;
margin-top: 0px;margin-bottom: 3.5em;font-size: 1em;
color: darkblue;\">Order Processing Division</h2>
      <h4>Ordered by #{args[:signer_name]}</h4>
      <p style=\"margin-top:0em; margin-bottom:0em;\">Email: #{args[:signer_email]}</p>
      <p style=\"margin-top:0em; margin-bottom:0em;\">Copy to: #{args[:cc_name]}, #{args[:cc_email]}</p>
      <p style=\"margin-top:3em;\">
Candy bonbon pastry jujubes lollipop wafer biscuit biscuit. Topping brownie sesame snaps sweet roll pie. Croissant danish biscuit soufflé caramels jujubes jelly. Dragée danish caramels lemon drops dragée. Gummi bears cupcake biscuit tiramisu sugar plum pastry. Dragée gummies applicake pudding liquorice. Donut jujubes oat cake jelly-o. Dessert bear claw chocolate cake gummies lollipop sugar plum ice cream gummies cheesecake.
      </p>
      <!-- Note the anchor tag for the signature field is in white. -->
      <h3 style=\"margin-top:3em;\">Agreed: <span style=\"color:white;\">**signature_1**/</span></h3>
      </body>
  </html>"
end
```

## 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](/docs/esign-rest-api/reference/envelopes/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.

> **Note**
>
> View the source code for this how-to on GitHub: [Bash](https://github.com/docusign/code-examples-bash/blob/master/examples/eSignature/eg010SendBinaryDocs.sh), [C#](https://github.com/docusign/code-examples-csharp/blob/master/launcher-csharp/eSignature/Examples/CreateEnvelopeWithMultipleDocumentTypes.cs), [Java](https://github.com/docusign/code-examples-java/blob/master/src/main/java/com/docusign/controller/eSignature/examples/EG010ControllerSendBinaryDocs.java), [Node.js](https://github.com/docusign/code-examples-node/blob/master/lib/eSignature/examples/sendBinaryDocs.js), [PHP](https://github.com/docusign/code-examples-php/blob/master/src/Services/Examples/eSignature/SendBinaryDocsService.php), [PowerShell](https://github.com/docusign/code-examples-powershell/blob/master/examples/eSignature/eg010SendBinaryDocs.ps1), [Python](https://github.com/docusign/code-examples-python/blob/master/app/eSignature/examples/eg010_send_binary_docs.py), or [Ruby](https://github.com/docusign/code-examples-ruby/blob/main/app/services/e_sign/eg010_send_binary_docs_service.rb).

**`Bash`**

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

**`C#`**

```csharp title="C#"
WebResponse response = null;
WebException webEx = null;
try
{
    response = request.GetResponse();
}
catch (WebException ex)
{
    response = ex.Response;
    webEx = ex;
}

var res = string.Empty;

using (var stream = response.GetResponseStream())
{
    using (var reader = new StreamReader(stream))
    {
        res = reader.ReadToEnd();
    }
}

string remaining = ((HttpWebResponse)response).Headers.Get("X-RateLimit-Remaining");
string reset = ((HttpWebResponse)response).Headers.Get("X-RateLimit-Reset");

if (reset != null && remaining != null)
{
    DateTime resetDate = DateTimeOffset.FromUnixTimeSeconds(long.Parse(reset)).UtcDateTime;
    Console.WriteLine("API calls remaining: " + remaining);
    Console.WriteLine("Next Reset: " + resetDate);
}

HttpStatusCode code = ((HttpWebResponse)response).StatusCode;
dynamic obj = JsonConvert.DeserializeObject(res);
bool statusOk = code >= HttpStatusCode.OK && code < HttpStatusCode.MultipleChoices;
string envelopeId = null;
string errorCode = null;
string errorMessage = null;

if (statusOk)
{
    envelopeId = obj.envelopeId;
}
else
{
    errorCode = obj.errorCode;
    errorMessage = obj.message;
}

return (statusOk, envelopeId, errorCode, errorMessage, webEx);
        }

        private static string Document1(string signerEmail, string signerName, string ccEmail, string ccName)
        {
// Data for this method
// signerEmail
// signerName
// ccEmail
// ccName
return " <!DOCTYPE html>\n" +
        "    <html>\n" +
        "        <head>\n" +
        "          <meta charset=\"UTF-8\">\n" +
        "        </head>\n" +
        "        <body style=\"font-family:sans-serif;margin-left:2em;\">\n" +
        "        <h1 style=\"font-family: 'Trebuchet MS', Helvetica, sans-serif;\n" +
        "            color: darkblue;margin-bottom: 0;\">World Wide Corp</h1>\n" +
        "        <h2 style=\"font-family: 'Trebuchet MS', Helvetica, sans-serif;\n" +
        "          margin-top: 0px;margin-bottom: 3.5em;font-size: 1em;\n" +
        "          color: darkblue;\">Order Processing Division</h2>\n" +
        "        <h4>Ordered by " + signerName + "</h4>\n" +
        "        <p style=\"margin-top:0em; margin-bottom:0em;\">Email: " + signerEmail + "</p>\n" +
        "        <p style=\"margin-top:0em; margin-bottom:0em;\">Copy to: " + ccName + ", " + ccEmail + "</p>\n" +
        "        <p style=\"margin-top:3em;\">\n" +
        "  Candy bonbon pastry jujubes lollipop wafer biscuit biscuit. Topping brownie sesame snaps sweet roll pie. Croissant danish biscuit soufflé caramels jujubes jelly. Dragée danish caramels lemon drops dragée. Gummi bears cupcake biscuit tiramisu sugar plum pastry. Dragée gummies applicake pudding liquorice. Donut jujubes oat cake jelly-o. Dessert bear claw chocolate cake gummies lollipop sugar plum ice cream gummies cheesecake.\n" +
        "        </p>\n" +
        "        <!-- Note the anchor tag for the signature field is in white. -->\n" +
        "        <h3 style=\"margin-top:3em;\">Agreed: <span style=\"color:white;\">**signature_1**/</span></h3>\n" +
        "        </body>\n" +
        "    </html>";
        }

        private static Dictionary<string, dynamic> MakeEnvelope(string signerEmail, string signerName, string ccEmail, string ccName)
        {
// Data for this method
// signerEmail
// signerName
// ccEmail
// ccName

// document 1 (html) has tag **signature_1**
// document 2 (docx) has tag /sn1/
// document 3 (pdf) has tag /sn1/
//
// The envelope has two recipients.
// recipient 1 - signer
// recipient 2 - cc
// The envelope will be sent first to the signer.
// After it is signed, a copy is sent to the cc person.
// create the envelope definition
// add the documents
Dictionary<string, dynamic> doc1 = new Dictionary<string, dynamic>()
{
    { "name", "Order acknowledgement" }, // can be different from actual file name
    { "fileExtension", "html" }, // Source data format. Signed docs are always pdf.
    { "documentId", "1" }, // a label used to reference the doc
};
Dictionary<string, dynamic> doc2 = new Dictionary<string, dynamic>()
{
    { "name", "Battle Plan" }, // can be different from actual file name
    { "fileExtension", "docx" },
    { "documentId", "2" },
};
Dictionary<string, dynamic> doc3 = new Dictionary<string, dynamic>()
{
    { "name", "Lorem Ipsum" }, // can be different from actual file name
    { "fileExtension", "pdf" },
    { "documentId", "3" },
};

// create a signer recipient to sign the document, identified by name and email
// We're setting the parameters via the object creation
Dictionary<string, dynamic> signer1 = new Dictionary<string, dynamic>()
{
    { "email", signerEmail },
    { "name", signerName },
    { "recipientId", "1" },
    { "routingOrder", "1" },
};

// routingOrder (lower means earlier) determines the order of deliveries
// to the recipients. Parallel routing order is supported by using the
// same integer as the order for two or more recipients.

// create a cc recipient to receive a copy of the documents, identified by name and email
// We're setting the parameters via setters
Dictionary<string, dynamic> cc1 = new Dictionary<string, dynamic>()
{
    { "email", ccEmail },
    { "name", ccName },
    { "routingOrder", "2" },
    { "recipientId", "2" },
};

// Create signHere fields (also known as tabs) on the documents,
// We're using anchor (autoPlace) positioning
//
// The DocuSign platform searches throughout your envelope's
// documents for matching anchor strings. So the
// signHere2 tab will be used in both document 2 and 3 since they
// use the same anchor string for their "signer 1" tabs.
Dictionary<string, dynamic> signHere1 = new Dictionary<string, dynamic>()
{
    { "anchorString", "**signature_1**" },
    { "anchorYOffset", "10" },
    { "anchorUnits", "pixels" },
    { "anchorXOffset", "20" },
};
Dictionary<string, dynamic> signHere2 = new Dictionary<string, dynamic>()
{
    { "anchorString", "/sn1/" },
    { "anchorYOffset", "10" },
    { "anchorUnits", "pixels" },
    { "anchorXOffset", "20" },
};

// Tabs are set per recipient / signer
Dictionary<string, dynamic> signer1Tabs = new Dictionary<string, dynamic>()
{
    { "signHereTabs", new dynamic[] { signHere1, signHere2 } },
};
signer1.Add("tabs", signer1Tabs);

// Recipients holds the different recipient objects as sets of arrays
Dictionary<string, dynamic> recipients = new Dictionary<string, dynamic>()
{
    { "signers", new dynamic[] { signer1 } },
    { "carbonCopies", new dynamic[] { cc1 } },
};

// create the envelope definition
Dictionary<string, dynamic> envelopeDefinition = new Dictionary<string, dynamic>()
{
    { "emailSubject", "Please sign this document set" },
    { "documents", new dynamic[] { doc1, doc2, doc3 } },
    { "recipients", recipients },
    { "status", "sent" },
};

return envelopeDefinition;
```

**`Java`**

```java title="Java"
DataOutputStream buffer = new DataOutputStream(connection.getOutputStream());
SendBinaryDocsService.writeBoundaryHeader(buffer, MediaType.APPLICATION_JSON, "form-data");
buffer.writeBytes(envelopeJSON.toString(DoneExample.JSON_INDENT_FACTOR));

for (DocumentInfo docInfo : documents) {
    String content = String.format("file; filename=\"%s\";documentid=%s", docInfo.getName(), docInfo.getId());
    buffer.writeBytes(LINE_DELIMITER);
    SendBinaryDocsService.writeBoundaryHeader(buffer, docInfo.getDocType().getMime(), content);
    buffer.write(docInfo.getData());
}

SendBinaryDocsService.writeClosingBoundary(buffer);

Map<String, List<String>> headers = connection.getHeaderFields();
java.util.List<String> remaining = headers.get("X-RateLimit-Remaining");
java.util.List<String> reset = headers.get("X-RateLimit-Reset");

if (remaining != null & reset != null) {
    Instant resetInstant = Instant.ofEpochSecond(Long.parseLong(reset.get(0)));
    System.out.println("API calls remaining: " + remaining);
    System.out.println("Next Reset: " + resetInstant);
}
int responseCode = connection.getResponseCode();
if (responseCode < HttpURLConnection.HTTP_OK || responseCode >= HttpURLConnection.HTTP_MULT_CHOICE) {
    String error = StreamUtils.copyToString(connection.getErrorStream(), StandardCharsets.UTF_8);
    throw new ExampleException(error, null);
}

return StreamUtils.copyToString(connection.getInputStream(), StandardCharsets.UTF_8);
    }
```

**`Node.js`**

```javascript title="Node.js"
let CRLF = '\r\n'
  ; let boundary = 'multipartboundary_multipartboundary'
  ; let hyphens = '--'
  ; let reqBody
  ;
reqBody = Buffer.from([
    hyphens, boundary,
    CRLF, 'Content-Type: application/json',
    CRLF, 'Content-Disposition: form-data',
    CRLF,
    CRLF, JSON.stringify(envelopeJSON, null, '    ')].join('')
);
// Loop to add the documents.
// See section Multipart Form Requests on page https://developers.docusign.com/esign-rest-api/guides/requests-and-responses
documents.forEach(d => {
    reqBody = Buffer.concat([reqBody, Buffer.from([
        CRLF, hyphens, boundary,
        CRLF, `Content-Type: ${d.mime}`,
        CRLF, `Content-Disposition: file; filename="${d.filename}";documentid=${d.documentId}`,
        CRLF,
        CRLF].join('')), Buffer.from(d.bytes)]
    );
});
// Add closing boundary
reqBody = Buffer.concat([reqBody,
    Buffer.from([CRLF, hyphens, boundary, hyphens, CRLF].join(''))]);
const response = await nf(options.uri, options);
```

**`PHP`**

```php title="PHP"
$client = new Client();
$uri = "{$args['base_path']}/v2.1/accounts/{$args['account_id']}/envelopes";
$responseInterface = $client->request('POST', $uri, [
    'headers' => [
        'Authorization' => "bearer {$args['ds_access_token']}",
        'Accept' => 'application/json',
        'Content-Type' => "multipart/form-data; boundary=" . $boundary
    ],
    'body' => $req_body
]);

$remaining = $responseInterface->getHeaders()['X-RateLimit-Remaining'] ?? null;
$reset =  $responseInterface->getHeaders()['X-RateLimit-Reset'] ?? null;

if ($remaining !== null && $reset !== null) {
    $resetInstant = (new DateTime())->setTimestamp((int)$reset);
    error_log("API calls remaining: $remaining");
    error_log("Next Reset: " . $resetInstant->format(\DateTime::ATOM));
}

$responseInterfaceToJson = json_decode((string)$responseInterface->getBody());

return ['envelope_id' => $responseInterfaceToJson->envelopeId];
```

**`PowerShell`**

```text title="PowerShell"
	Invoke-RestMethod `
		-Uri "${apiUri}/v2.1/accounts/${accountId}/envelopes" `
		-Method 'POST' `
		-Headers $headers `
		-InFile (Resolve-Path $requestData).Path `
		-OutFile $response

	Write-Output "Response: $(Get-Content -Raw $response)"
```

**`Python`**

```python title="Python"
results = requests.post(
    url=f"{args['base_path']}/v2.1/accounts/{args['account_id']}/envelopes",
    headers=headers,
    data=req_body
)
return {"status_code": results.status_code, "results": results.json()}
```

**`Ruby`**

```ruby title="Ruby"
uri = URI.parse("#{args[:base_path]}/restapi/v2.1/accounts/#{args[:account_id]}/envelopes")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = (uri.scheme == 'https')
req = Net::HTTP::Post.new(uri, header)
req.content_type = "multipart/form-data; boundary=#{boundary}"
# req.accept = "application/json"
req.body = buffer.join

response = http.request(req)
obj = JSON.parse(response.body)

raise Net::HTTPError.new(response.code, response.body) unless (response.code.to_i >= 200) && (response.code.to_i < 300)
```

## 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`**

```json title="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

* Run this code example from our [Quickstart](/docs/esign-rest-api/quickstart) or launcher projects:    [Bash](https://github.com/docusign/code-examples-bash), [C#](https://github.com/docusign/code-examples-csharp), [Java](https://github.com/docusign/code-examples-java), [Node.js](https://github.com/docusign/code-examples-node), [PHP](https://github.com/docusign/code-examples-php), [PowerShell](https://github.com/docusign/code-examples-powershell), [Python](https://github.com/docusign/code-examples-python), or [Ruby](https://github.com/docusign/code-examples-ruby).
* Learn about [documents](/docs/esign-rest-api/esign101/concepts/documents).
* See [How to request a signature by email](/docs/esign-rest-api/how-to/request-signature-email-remote).
* See how to [Go-Live](/docs/esign-rest-api/go-live) with a completed app and find the base path for API calls in the production environment.