> 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 request a signature by multiple delivery methods

> This topic demonstrates how to request a signature using email as the primary delivery method, with either SMS or WhatsApp as an additional delivery method.

eSignature REST API 2.1 only

This topic demonstrates how to request a signature using email as the primary delivery method, with either [SMS or WhatsApp](/docs/esign-rest-api/esign101/concepts/sms-delivery) as an additional delivery method.

In this configuration:

* You must set email as the primary delivery method.
* You can configure only one secondary delivery method per recipient: SMS or WhatsApp. You cannot configure both SMS and WhatsApp for the same recipient.
* Secondary delivery methods are supported only for `signer` (Needs to Sign), `carbonCopy` (Receives a Copy), and `certifiedDelivery` (Needs to View) recipient types.

Recipients receive an email notification for the signing request, along with an SMS or WhatsApp notification. The signing link in any of these notifications can be used to open and electronically sign the document using the Docusign mobile app or the Docusign website.

> **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.                                                                                                    |
| \{CC_COUNTRY_CODE}           | The country code corresponding to the CC_PHONE_NUMBER.                                                                                                                                                                                                                                                                                                                                                                    |
| \{CC_PHONE_NUMBER}           | The phone number of the carbon copy recipient to whom the SMS or WhatsApp notification will be sent.                                                                                                                                                                                                                                                                                                                      |
| \{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.                                                                                                                                                                                                                                                                                                                                                                 |
| \{COUNTRY_CODE}              | The country code corresponding to the PHONE_NUMBER.                                                                                                                                                                                                                                                                                                                                                                       |
| 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 |
| \{PHONE_NUMBER}              | The phone number of the signer to whom the SMS or WhatsApp notification will be sent.                                                                                                                                                                                                                                                                                                                                     |
| \{SECONDARY_DELIVERY_METHOD} | The secondary delivery method specified for a given recipient. One of: SMS or WhatsApp. Secondary delivery methods are limited to `signer`, `carbonCopy`, and `certifiedDelivery` recipients.                                                                                                                                                                                                                             |
| \{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. Create the envelope definition

To request a signature, you need to create a new envelope definition. The accompanying code shows how to create an individual envelope by defining a method named `makeEnvelope` that creates the envelope definition. The `makeEnvelope` method:

* Creates and attaches multiple documents to the envelope.
* Sets signer and carbon copy recipient data.
* Creates a routing order for the recipients.
* Creates and assigns signable fields to specific signers within the documents.

To use multiple delivery methods, configure the signer object by setting `deliveryMethod` to `Email`, and add an entry to the signer’s `additionalNotifications` array. In this entry, set `secondaryDeliveryMethod` to `SMS` or `WhatsApp`, and provide the recipient’s phone number by setting values for `number` and `countryCode` in the `phoneNumber` object. You should make these changes for each supported recipient you want to notify via email and SMS or WhatsApp. The accompanying code also demonstrates how to configure a carbon copy recipient using the same fields in the `carbonCopy` object.

**`Bash`**

```bash title="Bash"
printf \
'{
    "emailSubject": "Please sign this document set",
    "documents": [
        {
            "documentBase64": "' > $request_data
            cat $doc1_base64 >> $request_data
            printf '",
            "name": "Order acknowledgement",
            "fileExtension": "html",
            "documentId": "1"
        },
        {
            "documentBase64": "' >> $request_data
            cat $doc2_base64 >> $request_data
            printf '",
            "name": "Battle Plan",
            "fileExtension": "docx",
            "documentId": "2"
        },
        {
            "documentBase64": "' >> $request_data
            cat $doc3_base64 >> $request_data
            printf '",
            "name": "Lorem Ipsum",
            "fileExtension": "pdf",
            "documentId": "3"
        }
    ],
    "recipients":
    {
        "carbonCopies":
        [
            {
                "name": "'"${CC_NAME}"'",
                "email": "'"${CC_EMAIL}"'",
                "recipientId": "2",
                "routingOrder": "2",
                "deliveryMethod": "Email",
                "additionalNotifications": [
                    {
                        "phoneNumber":
                        {
                            "countryCode": "'"${CC_PHONE_COUNTRY}"'",
                            "number":"'"${CC_PHONE_NUMBER}"'"
                        },
                        "secondaryDeliveryMethod": "'"${DELIVERY_METHOD}"'"
                    }
                ],
            }
        ],
        "signers":
        [
            {
                "name": "'"${SIGNER_NAME}"'",
                "email": "'"${SIGNER_EMAIL}"'",
                "recipientId": "1",
                "routingOrder": "1",
                "deliveryMethod": "Email",
                "additionalNotifications": [
                    {
                        "phoneNumber":
                        {
                            "countryCode": "'"${SIGNER_PHONE_COUNTRY}"'",
                            "number":"'"${SIGNER_PHONE_NUMBER}"'"
                        },
                        "secondaryDeliveryMethod": "'"${DELIVERY_METHOD}"'"
                    }
                ],
                "tabs":
                {
                    "signHereTabs":
                    [
                        {
                            "anchorString": "**signature_1**",
                            "anchorUnits": "pixels",
                            "anchorXOffset": "20",
                            "anchorYOffset": "10"
                        },
                        {
                            "anchorString": "/sn1/",
                            "anchorUnits": "pixels",
                            "anchorXOffset": "20",
                            "anchorYOffset": "10"
                        }
                    ]
                }
            }
        ]
    },
    "status": "sent"
}' >> $request_data
```

**`C#`**

```csharp title="C#"
public static EnvelopeDefinition MakeEnvelope(
    string signerName,
    string signerEmail,
    string signerCountryCode,
    string signerPhoneNumber,
    string ccName,
    string ccEmail,
    string ccCountryCode,
    string ccPhoneNumber,
    string docDocx,
    string docPdf,
    string envStatus,
    string deliveryMethod)
{
    string doc2DocxBytes = Convert.ToBase64String(System.IO.File.ReadAllBytes(docDocx));
    string doc3PdfBytes = Convert.ToBase64String(System.IO.File.ReadAllBytes(docPdf));
    string b64 = Convert.ToBase64String(Document1(signerPhoneNumber, signerName, ccPhoneNumber, ccName));

    Document document1 = new Document
    {
        DocumentBase64 = b64,
        Name = "Order acknowledgement",
        FileExtension = "html",
        DocumentId = "1",
    };

    Document document2 = new Document
    {
        DocumentBase64 = doc2DocxBytes,
        Name = "Battle Plan",
        FileExtension = "docx",
        DocumentId = "2",
    };

    Document document3 = new Document
    {
        DocumentBase64 = doc3PdfBytes,
        Name = "Lorem Ipsum",
        FileExtension = "pdf",
        DocumentId = "3",
    };

    Signer signer = new Signer
    {
        Name = signerName,
        RecipientId = "1",
        RoutingOrder = "1",
        Email = signerEmail,
        DeliveryMethod = "Email",
        AdditionalNotifications = new List<RecipientAdditionalNotification>
        {
            new RecipientAdditionalNotification
            {
                SecondaryDeliveryMethod = deliveryMethod,
                PhoneNumber = new RecipientPhoneNumber
                {
                    CountryCode = signerCountryCode,
                    Number = signerPhoneNumber,
                },
            },
        },
    };

    Tabs signerTabs = new Tabs
    {
        SignHereTabs = new List<SignHere>
        {
            new SignHere
            {
                AnchorString = "**signature_1**",
                AnchorUnits = "pixels",
                AnchorYOffset = "10",
                AnchorXOffset = "20",
            },
            new SignHere
            {
                AnchorString = "/sn1/",
                AnchorUnits = "pixels",
                AnchorYOffset = "10",
                AnchorXOffset = "20",
            },
        },
    };
    signer.Tabs = signerTabs;

    CarbonCopy cc = new CarbonCopy
    {
        Name = ccName,
        RecipientId = "2",
        RoutingOrder = "2",
        Email = ccEmail,
        DeliveryMethod = "Email",
        AdditionalNotifications = new List<RecipientAdditionalNotification>
        {
            new RecipientAdditionalNotification
            {
                SecondaryDeliveryMethod = deliveryMethod,
                PhoneNumber = new RecipientPhoneNumber
                {
                    CountryCode = ccCountryCode,
                    Number = ccPhoneNumber,
                },
            },
        },
    };

    Recipients recipients = new Recipients
    {
        Signers = new List<Signer> { signer },
        CarbonCopies = new List<CarbonCopy> { cc },
    };

    EnvelopeDefinition env = new EnvelopeDefinition
    {
        EmailSubject = "Please sign this document set",
        Documents = new List<Document> { document1, document2, document3 },
        Recipients = recipients,
        Status = envStatus,
    };

    return env;
}
```

**`Java`**

```java title="Java"
public static EnvelopeDefinition makeEnvelope(
    String signerName,
    String signerEmail,
    String countryCode,
    String signersPhoneNumber,
    String ccName,
    String ccEmail,
    String ccCountryCode,
    String carbonCopyPhoneNumber,
    String deliveryMethod,
    String status) throws IOException {

    Tabs signerTabs = EnvelopeHelpers.createSignerTabs(
        EnvelopeHelpers.createSignHere(
        "/sn1/",
            ANCHOR_OFFSET_Y,
            ANCHOR_OFFSET_X
        ));

    Signer signer = new Signer();
    signer.setName(signerName);
    signer.setEmail(signerEmail);
    signer.setRecipientId(SIGNER_ID);
    signer.setRoutingOrder("1");
    signer.setTabs(signerTabs);
    signer.setDeliveryMethod(EMAIL_DELIVERY);
    signer.setAdditionalNotifications(Arrays.asList(
        createAdditionalNotification(countryCode, signersPhoneNumber, deliveryMethod)
    ));

    CarbonCopy cc = new CarbonCopy();
    cc.setName(ccName);
    cc.setEmail(ccEmail);
    cc.setRecipientId(CC_ID);
    cc.setRoutingOrder("2");
    cc.setDeliveryMethod(EMAIL_DELIVERY);
    cc.setAdditionalNotifications(Arrays.asList(
        createAdditionalNotification(ccCountryCode, carbonCopyPhoneNumber, deliveryMethod)
    ));

    EnvelopeDefinition envelope = new EnvelopeDefinition();
    envelope.setEmailSubject("Please sign this document set");
    envelope.setDocuments(
        Arrays.asList(
            EnvelopeHelpers.createDocumentFromFile(
                DOCX_DOCUMENT_FILE_NAME,
                DOCX_DOCUMENT_NAME,
                "2"
            ),
            EnvelopeHelpers.createDocumentFromFile(
                PDF_DOCUMENT_FILE_NAME,
                PDF_DOCUMENT_NAME,
                "3"
            )
        )
    );
    envelope.setRecipients(EnvelopeHelpers.createRecipients(signer, cc));
    envelope.setStatus(status);

    return envelope;
}

private static RecipientAdditionalNotification createAdditionalNotification(
        String countryCode,
        String phoneNumber,
        String deliveryMethod) {

    RecipientPhoneNumber phone = new RecipientPhoneNumber();
    phone.setCountryCode(countryCode);
    phone.setNumber(phoneNumber);

    RecipientAdditionalNotification notification = new RecipientAdditionalNotification();
    notification.setSecondaryDeliveryMethod(deliveryMethod);
    notification.setPhoneNumber(phone);

    return notification;
}
```

**`Node.js`**

```javascript title="Node.js"
function makeEnvelope(args) {
  // Data for this method
  // args.signerName
  // args.phoneNumber
  // args.countryCode
  // args.ccName
  // args.ccPhoneNumber
  // args.ccCountryCode
  // args.status
  // doc2File
  // doc3File

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

  let doc2DocxBytes, doc3PdfBytes;
  // read files from a local directory
  // The reads could raise an exception if the file is not available!
  doc2DocxBytes = fs.readFileSync(args.doc2File);
  doc3PdfBytes = fs.readFileSync(args.doc3File);

  // create the envelope definition
  const env = new docusign.EnvelopeDefinition();
  env.emailSubject = 'Please sign this document set';

  // add the documents
  const doc1 = new docusign.Document();
  const doc1b64 = Buffer.from(document1(args)).toString('base64');
  const doc2b64 = Buffer.from(doc2DocxBytes).toString('base64');
  const doc3b64 = Buffer.from(doc3PdfBytes).toString('base64');
  doc1.documentBase64 = doc1b64;
  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

  // Alternate pattern: using constructors for docs 2 and 3...
  const doc2 = new docusign.Document.constructFromObject({
    documentBase64: doc2b64,
    name: 'Battle Plan', // can be different from actual file name
    fileExtension: 'docx',
    documentId: '2',
  });

  const doc3 = new docusign.Document.constructFromObject({
    documentBase64: doc3b64,
    name: 'Lorem Ipsum', // can be different from actual file name
    fileExtension: 'pdf',
    documentId: '3',
  });

  // The order in the docs array determines the order in the envelope
  env.documents = [doc1, doc2, doc3];

  // Create a RecipientPhoneNumber object for the signer's phone number
  const signerPhoneNumber = docusign.RecipientPhoneNumber.constructFromObject({
    countryCode: args.countryCode,
    number: args.phoneNumber,
  });

  const signerAdditionalNotification = docusign.RecipientAdditionalNotification.constructFromObject({
    secondaryDeliveryMethod: args.deliveryMethod,
    phoneNumber: signerPhoneNumber
  });

  // Create a signer recipient to sign the document, identified by name and phone number
  // We're setting the parameters via the object constructor
  const signer = docusign.Signer.constructFromObject({
    name: args.signerName,
    email: args.signerEmail,
    deliveryMethod: 'Email',
    additionalNotifications: [signerAdditionalNotification],
    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 RecipientPhoneNumber object for the signer's phone number
  const ccPhoneNumber = docusign.RecipientPhoneNumber.constructFromObject({
    countryCode: args.ccCountryCode,
    number: args.ccPhoneNumber,
  });

  const ccAdditionalNotification = docusign.RecipientAdditionalNotification.constructFromObject({
    secondaryDeliveryMethod: args.deliveryMethod,
    phoneNumber: ccPhoneNumber
  });

  // Create a cc recipient to receive a copy of the documents, identified by name and phone number
  // We're setting the parameters via setters
  const cc = new docusign.CarbonCopy.constructFromObject({
    name: args.ccName,
    email: args.ccEmail,
    routingOrder: '2',
    recipientId: '2',
    deliveryMethod: 'Email',
    additionalNotifications: [ccAdditionalNotification],
  });

  // 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.
  const signHere1 = docusign.SignHere.constructFromObject({
    anchorString: '**signature_1**',
    anchorYOffset: '10',
    anchorUnits: 'pixels',
    anchorXOffset: '20',
  });
  const signHere2 = docusign.SignHere.constructFromObject({
    anchorString: '/sn1/',
    anchorYOffset: '10',
    anchorUnits: 'pixels',
    anchorXOffset: '20',
  });
  // Tabs are set per recipient / signer
  const signerTabs = docusign.Tabs.constructFromObject({
    signHereTabs: [signHere1, signHere2],
  });
  signer.tabs = signerTabs;

  // Add the recipients to the envelope object
  const recipients = docusign.Recipients.constructFromObject({
    signers: [signer],
    carbonCopies: [cc],
  });
  env.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.status = args.status;

  return env;
}

/**
 * Creates document 1
 * @function
 * @private
 * @param {Object} args parameters for the envelope
 * @returns {string} A document in HTML format
 */

function document1(args) {
  // Data for this method
  // args.signerName
  // args.ccName

  return `
    <!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.signerName}</h4>
        <p style="margin-top:0em; margin-bottom:0em;">Phone number: ${args.phoneNumber}</p>
        <p style="margin-top:0em; margin-bottom:0em;">Copy to: ${args.ccName}, ${args.ccPhoneNumber}</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>
  `;
}
```

**`PHP`**

```php title="PHP"
private static function makeEnvelope(
    array $args,
    $clientService,
    $demoDocsPath,
    $docDocx,
    $docPDF
): EnvelopeDefinition {
    $envelopeDefinition = CreateAnEnvelopeFunctionService::makeEnvelope(
        $args,
        $clientService,
        $demoDocsPath,
        $docDocx,
        $docPDF
    );

    $signer = new Signer([
        'name' => $args['signer_name'],
        'email' => $args['signer_email'],
        'additional_notifications' => [
            self::buildAdditionalNotification(
                $args['signer_country_code'],
                $args['signer_phone_number'],
                $args['deliveryMethod']
            )
        ],
        'recipient_id' => "1",
        'routing_order' => "1",
        'delivery_method' => "Email"
    ]);

    $cc = new CarbonCopy([
        'name' => $args['cc_name'],
        'email' => $args['cc_email'],
        'additional_notifications' => [
            self::buildAdditionalNotification(
                $args['cc_country_code'],
                $args['cc_phone_number'],
                $args['deliveryMethod']
            )
        ],
        'recipient_id' => "2",
        'routing_order' => "2",
        'delivery_method' => "Email"
        ]);

    return self::addSignersToTheDelivery($signer, $cc, $envelopeDefinition, $args);
}

private static function addSignersToTheDelivery($signer, $cc, $envelopeDefinition, $args)
{
    $signHere = new SignHere([
        'anchor_string' => '**signature_1**',
        'anchor_units' => 'pixels',
        'anchor_y_offset' => '10',
        'anchor_x_offset' => '20'
    ]);

    $signHere2 = new SignHere([
        'anchor_string' => '/sn1/',
        'anchor_units' =>  'pixels',
        'anchor_y_offset' => '10',
        'anchor_x_offset' => '20'
    ]);

    $signer->setTabs(new Tabs([
        'sign_here_tabs' => [$signHere, $signHere2]
    ]));

    $recipients = new Recipients([
        'signers' => [$signer],
        'carbon_copies' => [$cc]
    ]);

    $envelopeDefinition->setRecipients($recipients);
    $envelopeDefinition->setStatus($args["status"]);

    return $envelopeDefinition;
}
```

**`PowerShell`**

```text title="PowerShell"
$requestData = New-TemporaryFile
$response = New-TemporaryFile

@{
    emailSubject = "Please sign this document set";
    documents    = @(
        @{
            documentBase64 = "$(Get-Content $doc1Base64)";
            name           = "Order acknowledgement";
            fileExtension  = "html";
            documentId     = "1";
        };
        @{
            documentBase64 = "$(Get-Content $doc2Base64)";
            name           = "Battle Plan";
            fileExtension  = "docx";
            documentId     = "2";
        };
        @{
            documentBase64 = "$(Get-Content $doc3Base64)";
            name           = "Lorem Ipsum";
            fileExtension  = "pdf";
            documentId     = "3";
        };
    );
    recipients   = @{
        carbonCopies = @(
            @{
                additionalNotifications = @(
                    @{
                        secondaryDeliveryMethod = $deliveryMethod;
                        phoneNumber = @{
                            countryCode = $ccCountry;
                            number      = $ccNumber;
                        };
                    };
                );
                name           = $variables.CC_NAME;
                email          = $variables.CC_EMAIL;
                recipientId    = "2";
                routingOrder   = "2";
                deliveryMethod = "Email";
            };
        );
        signers = @(
            @{
                additionalNotifications = @(
                    @{
                        secondaryDeliveryMethod = $deliveryMethod;
                        phoneNumber = @{
                            countryCode = $signerCountry;
                            number      = $signerNumber;
                        };
                    };
                );
                name             = $variables.SIGNER_NAME;
                email            = $variables.SIGNER_EMAIL;
                recipientId      = "1";
                routingOrder     = "1";
                deliveryMethod   = "Email";
                tabs             = @{
                    signHereTabs = @(
                        @{
                            anchorString  = "**signature_1**";
                            anchorUnits   = "pixels";
                            anchorXOffset = "20";
                            anchorYOffset = "10";
                        };
                        @{
                            anchorString  = "/sn1/";
                            anchorUnits   = "pixels";
                            anchorXOffset = "20";
                            anchorYOffset = "10";
                        };
                    );
                };
            };
        );
    };
    status       = "sent";
} | ConvertTo-Json -Depth 32 > $requestData
```

**`Python`**

```python title="Python"
@classmethod
def make_envelope(cls, args):
    """
    Creates envelope:
    document 1 (HTML) has signHere anchor tag: **signature_1**
    document 2 (DOCX) has signHere anchor tag: /sn1/
    document 3 (PDF)  has signHere anchor tag: /sn1/
    DocuSign will convert all of the documents to the PDF format.
    The recipient’s field tags are placed using anchor strings.
    The envelope has two recipients:
    recipient 1: signer
    recipient 2: cc
    The envelope will be sent first to the signer via SMS.
    After it is signed, a copy is sent to the cc recipient via SMS.
    """
    # Create the envelope definition
    env = EnvelopeDefinition(
        email_subject="Please sign this document set"
    )
    doc1_b64 = base64.b64encode(bytes(cls.create_document1(args), "utf-8")).decode("ascii")
    # Read files 2 and 3 from a local folder
    # The reads could raise an exception if the file is not available!
    with open(path.join(demo_docs_path, DS_CONFIG["doc_docx"]), "rb") as file:
        doc2_docx_bytes = file.read()
    doc2_b64 = base64.b64encode(doc2_docx_bytes).decode("ascii")
    with open(path.join(demo_docs_path, DS_CONFIG["doc_pdf"]), "rb") as file:
        doc3_pdf_bytes = file.read()
    doc3_b64 = base64.b64encode(doc3_pdf_bytes).decode("ascii")

    # Create the document models
    document1 = Document(  # Create the DocuSign document object
        document_base64=doc1_b64,
        name="Order acknowledgement",  # Can be different from actual file name
        file_extension="html",  # Many different document types are accepted
        document_id="1"  # A label used to reference the doc
    )
    document2 = Document(  # Create the DocuSign document object
        document_base64=doc2_b64,
        name="Battle Plan",  # Can be different from actual file name
        file_extension="docx",  # Many different document types are accepted
        document_id="2"  # A label used to reference the doc
    )
    document3 = Document(  # Create the DocuSign document object
        document_base64=doc3_b64,
        name="Lorem Ipsum",  # Can be different from actual file name
        file_extension="pdf",  # Many different document types are accepted
        document_id="3"  # A label used to reference the doc
    )
    # The order in the docs array determines the order in the envelope
    env.documents = [document1, document2, document3]

    signer_phone_number = RecipientPhoneNumber(
        country_code=args["signer_country_code"],
        number=args["signer_phone_number"]
    )
    signer_additional_notification = RecipientAdditionalNotification(
        secondary_delivery_method=args["delivery_method"],
        phone_number=signer_phone_number
    )

    # Create the signer recipient model
    signer1 = Signer(
        name=args["signer_name"],
        email=args["signer_email"],
        recipient_id="1",
        routing_order="1",
        delivery_method="Email",
        additional_notifications=[signer_additional_notification]
    )

    # Create a RecipientPhoneNumber and add it to the additional SMS notification
    cc_phone_number = RecipientPhoneNumber(
        country_code=args["cc_country_code"],
        number=args["cc_phone_number"]
    )

    cc_additional_notification = RecipientAdditionalNotification(
        secondary_delivery_method=args["delivery_method"],
        phone_number=cc_phone_number
    )

    # Create a cc recipient to receive a copy of the documents
    cc1 = CarbonCopy(
        name=args["cc_name"],
        email=args["cc_email"],
        recipient_id="2",
        routing_order="2",
        delivery_method="Email",
        additional_notifications=[cc_additional_notification]
    )

    # 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 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 = SignHere(
        anchor_string="**signature_1**",
        anchor_units="pixels",
        anchor_y_offset="10",
        anchor_x_offset="20"
    )

    sign_here2 = SignHere(
        anchor_string="/sn1/",
        anchor_units="pixels",
        anchor_y_offset="10",
        anchor_x_offset="20"
    )

    # Add the tabs model (including the SignHere tabs) to the signer
    # The Tabs object wants arrays of the different field/tab types
    signer1.tabs = Tabs(sign_here_tabs=[sign_here1, sign_here2])

    # Add the recipients to the envelope object
    recipients = Recipients(signers=[signer1], carbon_copies=[cc1])
    env.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.status = args["status"]

    return env

@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;">Phone Number: {args["signer_phone_number"]}</p>
        <p style="margin-top:0em; margin-bottom:0em;">Copy to: {args["cc_name"]}</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(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 via SMS
  # After it is signed, a copy is sent to the cc person via SMS

  # Create the envelope definition
  envelope_definition = DocuSign_eSign::EnvelopeDefinition.new

  envelope_definition.email_subject = 'Please sign this document set'

  # Add the documents
  doc1_b64 = Base64.encode64(create_document1(envelope_args))
  # Read files 2 and 3 from a local directory
  # The reads could raise an exception if the file is not available!
  doc_docx = Rails.application.config.doc_docx
  doc2_b64 = Base64.encode64(File.binread(File.join('data', doc_docx)))
  doc_pdf = Rails.application.config.doc_pdf
  doc3_b64 = Base64.encode64(File.binread(File.join('data', doc_pdf)))

  # Create the document models
  document1 = DocuSign_eSign::Document.new(
    # Create the Docusign document object
    documentBase64: doc1_b64,
    name: 'Order acknowledgement', # Can be different from actual file name
    fileExtension: 'html', # Many different document types are accepted
    documentId: '1' # A label used to reference the doc
  )
  document2 = DocuSign_eSign::Document.new(
    # Create the Docusign document object
    documentBase64: doc2_b64,
    name: 'Battle Plan', # Can be different from actual file name
    fileExtension: 'docx', # Many different document types are accepted
    documentId: '2' # A label used to reference the do
  )
  document3 = DocuSign_eSign::Document.new(
    # Create the Docusign document object
    documentBase64: doc3_b64,
    name: 'Lorem Ipsum', # Can be different from actual file name
    fileExtension: 'pdf', # Many different document types are accepted
    documentId: '3' # A label used to reference the doc
  )

  # The order in the docs array determines the order in the envelope
  envelope_definition.documents = [document1, document2, document3]

  signer_phone_number = DocuSign_eSign::RecipientPhoneNumber.new
  signer_phone_number.country_code = envelope_args[:country_code]
  signer_phone_number.number = envelope_args[:phone_number]

  signer_additional_notification = DocuSign_eSign::RecipientAdditionalNotification.new
  signer_additional_notification.phone_number = signer_phone_number
  signer_additional_notification.secondary_delivery_method = envelope_args[:delivery_method]

  # Create the signer recipient model
  signer1 = DocuSign_eSign::Signer.new
  signer1.name = envelope_args[:signer_name]
  signer1.email = envelope_args[:signer_email]
  signer1.recipient_id = '1'
  signer1.routing_order = '1'
  signer1.delivery_method = 'Email'
  signer1.additional_notifications = [signer_additional_notification]

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

  cc_phone_number = DocuSign_eSign::RecipientPhoneNumber.new
  cc_phone_number.country_code = envelope_args[:cc_country_code]
  cc_phone_number.number = envelope_args[:cc_phone_number]

  cc_additional_notification = DocuSign_eSign::RecipientAdditionalNotification.new
  cc_additional_notification.phone_number = cc_phone_number
  cc_additional_notification.secondary_delivery_method = envelope_args[:delivery_method]

  # Create a cc recipient to receive a copy of the documents
  cc1 = DocuSign_eSign::CarbonCopy.new
  cc1.name = envelope_args[:cc_name]
  cc1.email = envelope_args[:cc_email]
  cc1.routing_order = '2'
  cc1.recipient_id = '2'
  cc1.delivery_method = 'Email'
  cc1.additional_notifications = [cc_additional_notification]

  # 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'
  )
  # Add the tabs model (including the sign_here tabs) to the signer
  # The Tabs object takes arrays of the different field/tab types
  signer1_tabs = DocuSign_eSign::Tabs.new({
                                            signHereTabs: [sign_here1, sign_here2]
                                          })

  signer1.tabs = signer1_tabs

  # Add the recipients to the envelope object
  recipients = DocuSign_eSign::Recipients.new(
    signers: [signer1],
    carbonCopies: [cc1]
  )
  # Request that the envelope be sent by setting status to "sent".
  # To request that the envelope be created as a draft, set status to "created"
  envelope_definition.recipients = recipients
  envelope_definition.status = envelope_args[:status]
  envelope_definition
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;\">Phone number: #{args[:phone_number]}</p>
      <p style=\"margin-top:0em; margin-bottom:0em;\">Copy to: #{args[:cc_name]}, #{args[:cc_phone_number]}</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 3. Create and send the envelope

With the envelope definition and the attributes defined for the recipients, document, and custom fields, you can now use the [Envelopes:create](/docs/esign-rest-api/reference/envelopes/envelopes/create) API method to create an envelope and send it, adding your access token and base path to the request header.

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

**`Bash`**

```bash title="Bash"
curl --header "Authorization: Bearer ${ACCESS_TOKEN}" \
     --header "Content-Type: application/json" \
     --data-binary @${request_data} \
     --request POST ${base_path}/v2.1/accounts/${account_id}/envelopes \
     --output $response
```

**`C#`**

```csharp title="C#"
public static string SendRequestByMultipleChannels(
    string accessToken,
    string basePath,
    string accountId,
    EnvelopeDefinition envelopeDefinition)
{
    var docusignClient = new DocuSignClient(basePath);
    docusignClient.Configuration.DefaultHeader.Add("Authorization", "Bearer " + accessToken);
    EnvelopesApi envelopesApi = new EnvelopesApi(docusignClient);

    var results = envelopesApi.CreateEnvelopeWithHttpInfo(accountId, envelopeDefinition);
    results.Headers.TryGetValue("X-RateLimit-Remaining", out string remaining);
    results.Headers.TryGetValue("X-RateLimit-Reset", out string 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);
    }

    return results.Data.EnvelopeId;
}
```

**`Java`**

```java title="Java"
public static EnvelopeSummary smsDelivery(
        EnvelopesApi envelopesApi,
        String accountId,
        EnvelopeDefinition envelope) throws ApiException {
    var createEnvelopeResponse = envelopesApi.createEnvelopeWithHttpInfo(
        accountId,
        envelope,
        envelopesApi.new CreateEnvelopeOptions()
    );

    Map<String, List<String>> headers = createEnvelopeResponse.getHeaders();
    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);
    }

    return createEnvelopeResponse.getData();
}
```

**`Node.js`**

```javascript title="Node.js"
results = await envelopesApi.createEnvelope(args.accountId, {
  envelopeDefinition: envelope,
});
```

**`PHP`**

```php title="PHP"
public static function multipleDelivery(
    array $args,
    $clientService,
    $demoDocsPath,
    $docDocx,
    $docPDF
): array {
    $envelopeDefinition = self::makeEnvelope(
        $args["envelope_args"],
        $clientService,
        $demoDocsPath,
        $docDocx,
        $docPDF
    );

    $envelopeApi = $clientService->getEnvelopeApi();

    $envelopeResponse = $envelopeApi->createEnvelopeWithHttpInfo($args['account_id'], $envelopeDefinition);

    $remaining = $envelopeResponse[2]['X-RateLimit-Remaining'] ?? null;
    $reset =  $envelopeResponse[2]['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));
    }

    return ['envelope_id' => $envelopeResponse[0]->getEnvelopeId()];
}
```

**`PowerShell`**

```text title="PowerShell"
Invoke-RestMethod `
    -Uri "${apiUri}/v2.1/accounts/${accountId}/envelopes" `
    -Method 'POST' `
    -Headers @{
        'Authorization' = "Bearer $accessToken";
        'Content-Type'  = "application/json";
    } `
    -InFile (Resolve-Path $requestData).Path `
    -OutFile $response

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

$envelopeId = $(Get-Content $response | ConvertFrom-Json).envelopeId
```

**`Python`**

```python title="Python"
envelope_args = args["envelope_args"]
# Create the envelope request object
api_client = create_api_client(base_path=args["base_path"], access_token=args["access_token"])
envelope_definition = cls.make_envelope(envelope_args)
# Call Envelopes::create API method
# Exceptions will be caught by the calling function
envelopes_api = EnvelopesApi(api_client)
(results, status, headers) = envelopes_api.create_envelope_with_http_info(account_id=args["account_id"], envelope_definition=envelope_definition)

remaining = headers.get("X-RateLimit-Remaining")
reset = headers.get("X-RateLimit-Reset")

if remaining is not None and reset is not None:
    reset_date = dt.fromtimestamp(int(reset), tz=timezone.utc)
    print(f"API calls remaining: {remaining}")
    print(f"Next Reset: {reset_date}")

envelope_id = results.envelope_id

return {"envelope_id": envelope_id}
```

**`Ruby`**

```ruby title="Ruby"
results, _status, headers = envelope_api.create_envelope_with_http_info args[:account_id], envelope_definition

remaining = headers['X-RateLimit-Remaining']
reset = headers['X-RateLimit-Reset']

if remaining && reset
  reset_date = Time.at(reset.to_i).utc
  puts "API calls remaining: #{remaining}"
  puts "Next Reset: #{reset_date}"
end
envelope_id = results.envelope_id
```

## 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 and an SMS or WhatsApp message. They can use the signing link in any of these notifications to open and electronically sign a document using the Docusign mobile app or the Docusign website. After signing is complete, the recipients receive a carbon copy of the email that includes all of the completed and signed documents.

**`Sample response`**

```json title="Sample response"
{
  "envelopeId": "e319acf5-xxxx-xxxx-xxxx-8bd6eae9abb7",
  "uri": "/envelopes/e319acf5-xxxx-xxxx-xxxx-8bd6eae9abb7",
  "statusDateTime": "2023-04-06T19:38:30.6530000Z",
  "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 more about [SMS delivery or WhatsApp](/docs/esign-rest-api/esign101/concepts/sms-delivery).
* Find out [How to request a signature by SMS or WhatsApp delivery](/docs/esign-rest-api/how-to/request-signature-sms-whatsapp).
* Learn [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.