> 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 send multiple envelopes

> Learn how to use the capabilities of the Apex Toolkit to send multiple customized envelopes in a single transaction from within Salesforce.

This topic demonstrates how to send multiple envelopes in a single transaction using the Apex Toolkit. Multi-send is distinct from [bulk sending](/docs/salesforce/how-to/bulk-send) in that each envelope in this scenario can be unique without the recipient limits imposed by bulk sending. If you are sending the same document for signature to a list of recipients, bulk sending is the most efficient option. Carefully consider whether bulk sending is more appropriate for your use case.

Keep in mind the following limits when triggering an envelope multi-send:

* You are limited to 99 envelopes in a single transaction. This corresponds to [Salesforce callout limits](https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_callouts.htm) per transaction, with one callout reserved for requesting a Docusign access token.
* You may send up to 1000 envelopes in an hour via the Apex Toolkit. See [API resource limits](/platform/resource-limits) for more details.
* You cannot create draft envelopes using this method. Any envelope that is not fully ready to be sent will prevent all other envelopes in the same transaction from being sent.

## Prerequisites

1. Install the [Docusign eSignature for Salesforce](/docs/salesforce/how-to/apex-toolkit-install)  managed package.
2. Create a subdomain for your Salesforce organization by enabling "My Domain."
3. Select the **Docusign Setup** tab and complete the login step.
4. Configure the Contact object within your Salesforce organization with the custom fields necessary to run the code below. In the **Object Manager** menu, find **Contact**, then navigate to **Fields & Relationships** where you can select **New** to add a custom field. Add a new field of type **Picklist** with the label **OfferStage**. The picklist needs to have values **Prepared** and **Out for Signature**.
5. Check that the contacts to whom you want to send envelopes already have documents linked to their record in Salesforce. Note that files uploaded through Salesforce Classic are not currently detected to use for multi-send. Please upload documents using the new Salesforce Lightning experience to use them.
6. Update the **OfferStage** field for contacts that will receive envelopes to **Prepared**.

## Required data

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

| Data element           | Description                                          |
| ---------------------- | ---------------------------------------------------- |
| Documents to be signed | You must provide at least one document to be signed. |

## Step 1. Define your public classes and methods

Create one public class and one public method that will contain the code for this how-to. You can skip this step if you are adding this code to an existing class.

**`Apex`**

```java title="Apex"
public with sharing class SendMultipleEnvelopesController {
    public static void SendMultipleEnvelopes() {
    }
}
```

## Step 2. Prepare the envelopes

The Apex Toolkit allows you to build up to 99 envelopes. You can merge data from Salesforce into your envelopes, and each envelope may be unique. In the example below, we will send offer letters to Contacts with an **OfferStage** field that is set to **Prepared.** Notice that the **OfferStage** field becomes `OfferStage__c` in the code. All custom fields are given the `__c` suffix in the code to differentiate them from default objects and fields. For example purposes, we assume some custom fields exist on the Contact object and that each Contact in this stage has an offer letter linked to their record.

**Note:** Unlike with `dfsle.EnvelopeService.sendEnvelope`, you will not have an opportunity to tag the envelope as `draft` before sending. You should consider using [AutoPlace](https://support.docusign.com/s/document-item?language=en_US\&rsc_301\&bundleId=gbo1643332197980\&topicId=ytr1578456405118.html&_LANG=enus) fields in your documents or Docusign [templates](/docs/esign-rest-api/esign101/concepts/templates) when sending with this method.

**`Apex`**

```java title="Apex"
// Get up to 99 contacts in the "Prepared" offer stage
List<Contact> contacts = [SELECT Id, Name FROM Contact WHERE OfferStage__c = 'Prepared' LIMIT 99];

// Build a list of offer envelopes to send
List<dfsle.Envelope> envelopes = new List<dfsle.Envelope>();
for (Contact c : contacts) {
    // Get an empty envelope with org defaults
    envelopes.add(dfsle.EnvelopeService.getEmptyEnvelope(new dfsle.Entity(c.Id))
        // Customize the email subject and message
        .withEmail('Offer Letter for ' + c.Name, c.Name + ', please review and sign the enclosed offer letter.')
        // Add linked offer letter to envelope
        .withDocuments(dfsle.DocumentService.getLinkedDocuments(
            ContentVersion.getSObjectType(),
            new Set<Id> { c.Id },
            true))
        // Add the contact as a recipient
        .withRecipients(dfsle.RecipientService.getRecipients(
            Contact.getSObjectType(),
            new Set<Id> { c.Id })));
}
```

## Step 3. Send the envelopes

Now that you have built a list of offer letters to send, you can send all of them in a single batch using the [dfsle.EnvelopeService.sendEnvelope](/docs/salesforce/apex-toolkit-reference/envelopeservice.html) method. Invoking this method triggers a number of calls to the eSignature API equal to the size of the input envelope list, plus one call to request an access token. Unlike `dfsle.EnvelopeService.sendEnvelope`**,** this method will not create any associated envelope or status records in Salesforce.

This method may be partially successful. If the eSignature API returns any errors, the `dfsle.Envelope.error` property will contain the error details.

If you exceed your Docusign API hourly limit, the `dfsle.Envelope.error.code` will be `1014`. You must wait until the hourly count is reset to continue sending envelopes. Bear in mind that most other Docusign API calls count against your hourly limit. Refer to [API resource limits](/platform/resource-limits) for more details on API limits.

**`Apex`**

```java title="Apex"
// Send the envelopes and determine which envelopes were sent successfully
// Filter out unsuccessfully sent envelopes
List<Contact> contactsToUpdate = new List<Contact>();
List<dfsle.Envelope> sentEnvelopes = new List<dfsle.Envelope>();
for (dfsle.Envelope envelope : dfsle.EnvelopeService.sendEnvelopes(envelopes)) {
    if (envelope.error == null) {
        // Envelope sent successfully
        sentEnvelopes.add(envelope);
        contactsToUpdate.add(new Contact(
        Id = envelope.source.id,
        OfferStage__c = 'Out for Signature'));
    } else {
        // Handle send error
        System.debug('Envelope error: ' + envelope.error);
    }
}

// Update the Contact offer stage to "Out for Signature"
update contactsToUpdate;
```

## Step 4. Save the sent envelopes to Salesforce

Once the envelopes are sent, you may want to create the associated envelope and status records in Salesforce. Use the [dfsle.EnvelopeService.saveSentEnvelopes](/docs/salesforce/apex-toolkit-reference/envelopeservice.html) method to create these records.

**Note:** This step is required if you want to track the envelope status within Salesforce.

Only successfully sent envelopes may be updated with `dfsle.EnvelopeService.saveSentEnvelopes`. If any invalid envelopes are passed into this method, a `dfsle.DocuSignException` is thrown and no Data Manipulation Language update is performed.

**`Apex`**

```java title="Apex"
List<dfsle.Envelope> savedEnvelopes = dfsle.EnvelopeService.saveSentEnvelopes(sentEnvelopes);
```

## Step 5. Get the envelope status

Docusign administrators can track the status of Docusign envelopes after sending them to recipients by using the Apex Toolkit `getStatus` method. This method returns the current status of the envelope (Created, Deleted, Sent, Delivered, Signed, Completed, or Declined), the time and date of the most recent action on the envelope, and other information as a list of `Envelope.Status` objects. This method is passed a set of Salesforce source records that are associated with envelopes and an integer specifying the maximum number of records that will be returned.

Getting envelope status is useful for ensuring that the envelope operations you've already performed, such as sending, confirming delivery or signing, and completion, have been executed successfully, and to detect new status changes for an envelope. You must be the sender of the envelopes to call this method, as shown in the accompanying code.

**`Apex`**

```java title="Apex"
// Build a list of Contact IDs to query
Set<Id> contactIds = new Set<Id>();
for (dfsle.Envelope envelope : savedEnvelopes) {
    contactIds.add(envelope.source.id);
}

// Retrieve the most recent envelope statuses from the Salesforce source objects
// The status results are sorted oldest to newest
List<dfsle.Envelope.Status> statuses = dfsle.StatusService.getStatus(
    contactIds, // Envelope source object IDs
    99); // Maximum number of records to return

// Display or take action on the returned statuses
```

## Step 6. Execute your methods

To execute your code, go to the [Developer Console](https://help.salesforce.com/s/articleView?language=en_US\&id=sf.code_dev_console.htm\&type=5) in Salesforce, open the **Debug** menu, then select **Open Execute Anonymous Window**. Type the accompanying code in the window and select **Execute**.

If you skipped step 1 and added your code to existing classes or methods, you'll need to replace the class and method names with your own.

> **Note**
>
> View the source code for this how-to on GitHub: [Apex](https://github.com/docusign/code-examples-apex/blob/master/force-app/main/default/classes/SendMultipleEnvelopesController.cls).

**`Apex`**

```java title="Apex"
SendMultipleEnvelopesClass.sendMultipleMethod();
```

## Next steps

* See all available Apex Toolkit [How-to guides](/docs/salesforce/how-to).
* See [How to perform unit testing](/docs/salesforce/how-to/unit-testing) to ensure that you have adequate code coverage.