530 lines
12 KiB
Markdown
530 lines
12 KiB
Markdown
# API Reference
|
|
|
|
**Project**: Salesforce Composite Envelope Builder
|
|
**Version**: 1.0
|
|
**Date**: February 23, 2026
|
|
|
|
---
|
|
|
|
## 1. Docusign REST API Integration
|
|
|
|
### 1.1 Base Endpoint
|
|
|
|
**Production**:
|
|
```
|
|
https://na3.docusign.net/restapi/v2.1
|
|
```
|
|
|
|
**Sandbox**:
|
|
```
|
|
https://demo.docusign.net/restapi/v2.1
|
|
```
|
|
|
|
**Note**: Replace `na3` with your account's data center (na2, na3, eu1, etc.)
|
|
|
|
---
|
|
|
|
## 2. Create Composite Envelope
|
|
|
|
### 2.1 HTTP Request
|
|
|
|
**Method**: POST
|
|
**Endpoint**: `/accounts/{accountId}/envelopes`
|
|
**Content-Type**: `application/json`
|
|
**Authorization**: `Bearer {access_token}`
|
|
|
|
### 2.2 Request Headers
|
|
|
|
```http
|
|
POST /restapi/v2.1/accounts/12345678-abcd-1234-abcd-1234567890ab/envelopes HTTP/1.1
|
|
Host: na3.docusign.net
|
|
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6IjY4MTg...
|
|
Content-Type: application/json
|
|
Accept: application/json
|
|
```
|
|
|
|
### 2.3 Request Body (Composite Templates)
|
|
|
|
#### Minimum Example (2 templates)
|
|
|
|
```json
|
|
{
|
|
"status": "sent",
|
|
"emailSubject": "Please review and sign these forms",
|
|
"compositeTemplates": [
|
|
{
|
|
"compositeTemplateId": "1",
|
|
"serverTemplates": [
|
|
{
|
|
"sequence": "1",
|
|
"templateId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"compositeTemplateId": "2",
|
|
"serverTemplates": [
|
|
{
|
|
"sequence": "2",
|
|
"templateId": "b2c3d4e5-f6g7-8901-bcde-fg2345678901"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
#### Advanced Example (with merge fields)
|
|
|
|
```json
|
|
{
|
|
"status": "sent",
|
|
"emailSubject": "Please review and sign these forms",
|
|
"compositeTemplates": [
|
|
{
|
|
"compositeTemplateId": "1",
|
|
"serverTemplates": [
|
|
{
|
|
"sequence": "1",
|
|
"templateId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
|
|
}
|
|
],
|
|
"inlineTemplates": [
|
|
{
|
|
"sequence": "1",
|
|
"customFields": {
|
|
"textCustomFields": [
|
|
{
|
|
"name": "SalesforceRecordId",
|
|
"value": "0018V00000ABC123"
|
|
},
|
|
{
|
|
"name": "CaseNumber",
|
|
"value": "00001234"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
### 2.4 Response
|
|
|
|
#### Success (201 Created)
|
|
|
|
```json
|
|
{
|
|
"envelopeId": "f9876543-21ab-cdef-0123-456789abcdef",
|
|
"uri": "/envelopes/f9876543-21ab-cdef-0123-456789abcdef",
|
|
"statusDateTime": "2026-02-23T12:34:56.789Z",
|
|
"status": "sent"
|
|
}
|
|
```
|
|
|
|
#### Error (400 Bad Request)
|
|
|
|
```json
|
|
{
|
|
"errorCode": "INVALID_REQUEST_PARAMETER",
|
|
"message": "The request contained at least one invalid parameter. The template with ID 'invalid-id' does not exist."
|
|
}
|
|
```
|
|
|
|
#### Error (401 Unauthorized)
|
|
|
|
```json
|
|
{
|
|
"errorCode": "USER_AUTHENTICATION_FAILED",
|
|
"message": "One or both of Username and Password are invalid."
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 3. Composite Template Structure
|
|
|
|
### 3.1 Key Concepts
|
|
|
|
**compositeTemplates** (array):
|
|
- Each element represents a server template to include in the envelope
|
|
- Order in array determines document order in envelope
|
|
|
|
**compositeTemplateId** (string):
|
|
- Unique identifier for this composite template within the request
|
|
- Can be any string (recommend using sequence numbers: "1", "2", "3")
|
|
|
|
**serverTemplates** (array):
|
|
- References pre-existing templates in your Docusign account
|
|
- Must include `templateId` (GUID from Docusign)
|
|
|
|
**sequence** (string):
|
|
- Determines document order within the envelope
|
|
- "1" = first document, "2" = second, etc.
|
|
- **Important**: Use strings, not integers
|
|
|
|
**inlineTemplates** (array, optional):
|
|
- Allows runtime override of template values
|
|
- Used for custom fields, recipient data, tabs
|
|
|
|
### 3.2 Recipient Merging
|
|
|
|
**Automatic Merge**:
|
|
When multiple templates have recipients with the same `roleName`, Docusign automatically merges them into a single recipient.
|
|
|
|
**Example**:
|
|
- Template A has recipient role: "Signer"
|
|
- Template B has recipient role: "Signer"
|
|
- Result: One recipient signs all documents
|
|
|
|
**Requirements for merge**:
|
|
- Exact match on `roleName`
|
|
- Same recipient `routingOrder` (signing order)
|
|
- Merge happens automatically, no additional configuration needed
|
|
|
|
---
|
|
|
|
## 4. Authentication
|
|
|
|
### 4.1 JWT (JSON Web Token)
|
|
|
|
**Preferred method for server-to-server integration**
|
|
|
|
#### Step 1: Generate JWT
|
|
|
|
```apex
|
|
// Apex pseudocode
|
|
String jwt = generateJWT(
|
|
integrationKey, // From Docusign Apps & Keys
|
|
userId, // Docusign user GUID
|
|
rsaPrivateKey, // RSA private key (PEM format)
|
|
'https://account-d.docusign.com/oauth/auth', // Sandbox
|
|
3600 // Token expiry (1 hour)
|
|
);
|
|
```
|
|
|
|
#### Step 2: Exchange JWT for Access Token
|
|
|
|
**Request**:
|
|
```http
|
|
POST /oauth/token HTTP/1.1
|
|
Host: account-d.docusign.com
|
|
Content-Type: application/x-www-form-urlencoded
|
|
|
|
grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion={jwt}
|
|
```
|
|
|
|
**Response**:
|
|
```json
|
|
{
|
|
"access_token": "eyJ0eXAiOiJNVCIsImFsZyI...",
|
|
"token_type": "Bearer",
|
|
"expires_in": 3600
|
|
}
|
|
```
|
|
|
|
#### Step 3: Use Access Token
|
|
|
|
```http
|
|
Authorization: Bearer eyJ0eXAiOiJNVCIsImFsZyI...
|
|
```
|
|
|
|
### 4.2 OAuth2 Authorization Code
|
|
|
|
**User-based authentication** (not recommended for this use case)
|
|
|
|
See [Docusign OAuth2 documentation](https://developers.docusign.com/platform/auth/authcode/) for details.
|
|
|
|
---
|
|
|
|
## 5. Error Codes
|
|
|
|
### 5.1 Common Error Codes
|
|
|
|
| Error Code | HTTP | Meaning | Resolution |
|
|
|------------|------|---------|------------|
|
|
| `INVALID_REQUEST_PARAMETER` | 400 | Invalid parameter in request | Check JSON structure, template IDs |
|
|
| `USER_AUTHENTICATION_FAILED` | 401 | Invalid or expired access token | Refresh access token |
|
|
| `USER_LACKS_PERMISSIONS` | 403 | User doesn't have permission | Check Docusign user permissions |
|
|
| `RESOURCE_NOT_FOUND` | 404 | Template ID not found | Verify template exists in account |
|
|
| `DUPLICATE_RESOURCE` | 409 | Duplicate request | Check for duplicate envelope |
|
|
| `ONESIGNAL_GENERIC_ERROR` | 500 | Docusign server error | Retry after delay |
|
|
|
|
### 5.2 Rate Limits
|
|
|
|
**Hourly limit**: Varies by plan (1,000 - 10,000+ API calls/hour)
|
|
|
|
**Response header when nearing limit**:
|
|
```http
|
|
X-RateLimit-Limit: 1000
|
|
X-RateLimit-Remaining: 50
|
|
X-RateLimit-Reset: 1614358800
|
|
```
|
|
|
|
**Error when limit exceeded**:
|
|
```json
|
|
{
|
|
"errorCode": "HOURLY_APIINVOCATION_LIMIT_EXCEEDED",
|
|
"message": "The maximum number of hourly API invocations has been exceeded."
|
|
}
|
|
```
|
|
|
|
**Mitigation**:
|
|
- Implement exponential backoff
|
|
- Cache access tokens (don't generate new token for each request)
|
|
- Batch operations when possible
|
|
|
|
---
|
|
|
|
## 6. Custom Fields
|
|
|
|
### 6.1 Text Custom Fields
|
|
|
|
**Use case**: Store Salesforce record ID in envelope
|
|
|
|
```json
|
|
{
|
|
"compositeTemplates": [
|
|
{
|
|
"inlineTemplates": [
|
|
{
|
|
"customFields": {
|
|
"textCustomFields": [
|
|
{
|
|
"name": "SalesforceRecordId",
|
|
"value": "0018V00000ABC123",
|
|
"show": "false",
|
|
"required": "false"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
### 6.2 List Custom Fields
|
|
|
|
```json
|
|
{
|
|
"customFields": {
|
|
"listCustomFields": [
|
|
{
|
|
"name": "FormLanguage",
|
|
"value": "English",
|
|
"listItems": ["English", "Spanish"]
|
|
}
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 7. Webhook Configuration
|
|
|
|
### 7.1 Connect Webhook (for document retrieval)
|
|
|
|
**Not required for Phase 1**, but useful for future automation.
|
|
|
|
**Endpoint**: Configure in Docusign Admin → Connect → Add Configuration
|
|
|
|
**Webhook payload** (when envelope completes):
|
|
```json
|
|
{
|
|
"event": "envelope-completed",
|
|
"apiVersion": "v2.1",
|
|
"uri": "/restapi/v2.1/accounts/123/envelopes/abc",
|
|
"envelopeId": "f9876543-21ab-cdef-0123-456789abcdef",
|
|
"envelopeSummary": {
|
|
"status": "completed",
|
|
"emailSubject": "Please review and sign",
|
|
"completedDateTime": "2026-02-23T14:30:00Z"
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 8. Template Management APIs
|
|
|
|
### 8.1 List Templates
|
|
|
|
**Use case**: Retrieve template list for Flow dropdown
|
|
|
|
**Request**:
|
|
```http
|
|
GET /restapi/v2.1/accounts/{accountId}/templates?count=100&order=name&order_by=asc
|
|
```
|
|
|
|
**Response**:
|
|
```json
|
|
{
|
|
"resultSetSize": "14",
|
|
"totalSetSize": "14",
|
|
"envelopeTemplates": [
|
|
{
|
|
"templateId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
|
|
"name": "Form A - English",
|
|
"shared": "true",
|
|
"description": "English version of Form A"
|
|
},
|
|
{
|
|
"templateId": "b2c3d4e5-f6g7-8901-bcde-fg2345678901",
|
|
"name": "Form B - English",
|
|
"shared": "true",
|
|
"description": "English version of Form B"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
### 8.2 Get Template Details
|
|
|
|
**Use case**: Retrieve template metadata (recipients, tabs)
|
|
|
|
**Request**:
|
|
```http
|
|
GET /restapi/v2.1/accounts/{accountId}/templates/{templateId}
|
|
```
|
|
|
|
**Response**:
|
|
```json
|
|
{
|
|
"templateId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
|
|
"name": "Form A - English",
|
|
"recipients": {
|
|
"signers": [
|
|
{
|
|
"roleName": "Signer 1",
|
|
"recipientId": "1",
|
|
"routingOrder": "1"
|
|
},
|
|
{
|
|
"roleName": "Signer 2",
|
|
"recipientId": "2",
|
|
"routingOrder": "2"
|
|
}
|
|
]
|
|
},
|
|
"documents": [
|
|
{
|
|
"documentId": "1",
|
|
"name": "Form_A.pdf",
|
|
"pages": "2"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 9. Apex HTTP Callout Example
|
|
|
|
### 9.1 Complete Callout
|
|
|
|
```apex
|
|
public static String createCompositeEnvelope(String envelopeJSON, String accessToken, String accountId) {
|
|
HttpRequest req = new HttpRequest();
|
|
req.setEndpoint('callout:DocusignAPI/accounts/' + accountId + '/envelopes');
|
|
req.setMethod('POST');
|
|
req.setHeader('Authorization', 'Bearer ' + accessToken);
|
|
req.setHeader('Content-Type', 'application/json');
|
|
req.setHeader('Accept', 'application/json');
|
|
req.setBody(envelopeJSON);
|
|
req.setTimeout(120000); // 120 seconds
|
|
|
|
Http http = new Http();
|
|
HttpResponse res = http.send(req);
|
|
|
|
if (res.getStatusCode() == 201) {
|
|
Map<String, Object> responseMap = (Map<String, Object>) JSON.deserializeUntyped(res.getBody());
|
|
return (String) responseMap.get('envelopeId');
|
|
} else {
|
|
throw new CalloutException('Docusign API error [' + res.getStatusCode() + ']: ' + res.getBody());
|
|
}
|
|
}
|
|
```
|
|
|
|
### 9.2 Named Credential Configuration
|
|
|
|
**Setup → Named Credentials → New Named Credential**
|
|
|
|
**Settings**:
|
|
- **Label**: Docusign API
|
|
- **Name**: DocusignAPI
|
|
- **URL**: `https://na3.docusign.net/restapi/v2.1`
|
|
- **Identity Type**: Named Principal
|
|
- **Authentication Protocol**: OAuth 2.0
|
|
- **Scope**: `signature impersonation`
|
|
- **Token Endpoint**: `https://account-d.docusign.com/oauth/token` (sandbox)
|
|
- **JWT Token Exchange**: Enabled
|
|
|
|
**Usage in Apex**:
|
|
```apex
|
|
req.setEndpoint('callout:DocusignAPI/accounts/' + accountId + '/envelopes');
|
|
```
|
|
|
|
---
|
|
|
|
## 10. Testing with Postman
|
|
|
|
### 10.1 Import Docusign Collection
|
|
|
|
Docusign provides an official Postman collection:
|
|
https://github.com/docusign/postman-collections
|
|
|
|
### 10.2 Create Composite Envelope Test
|
|
|
|
**Request**:
|
|
```
|
|
POST {{baseUrl}}/accounts/{{accountId}}/envelopes
|
|
Headers:
|
|
Authorization: Bearer {{accessToken}}
|
|
Content-Type: application/json
|
|
Body:
|
|
{
|
|
"status": "sent",
|
|
"emailSubject": "Test Composite Envelope",
|
|
"compositeTemplates": [
|
|
{
|
|
"compositeTemplateId": "1",
|
|
"serverTemplates": [
|
|
{
|
|
"sequence": "1",
|
|
"templateId": "{{templateId1}}"
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"compositeTemplateId": "2",
|
|
"serverTemplates": [
|
|
{
|
|
"sequence": "2",
|
|
"templateId": "{{templateId2}}"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 11. Reference Links
|
|
|
|
- [Docusign REST API Reference](https://developers.docusign.com/docs/esign-rest-api/reference/)
|
|
- [Composite Templates Guide](https://developers.docusign.com/docs/esign-rest-api/how-to/request-signature-composite-template/)
|
|
- [JWT Authentication](https://developers.docusign.com/platform/auth/jwt/)
|
|
- [Salesforce Named Credentials](https://help.salesforce.com/s/articleView?id=sf.named_credentials_about.htm)
|
|
- [Salesforce HTTP Callouts](https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_classes_restful_http_httprequest.htm)
|
|
|
|
---
|
|
|
|
**Document Version**: 1.0
|
|
**Last Updated**: February 23, 2026
|