12 KiB
API Reference
Project: Salesforce Composite Envelope Builder
Version: 1.1
Date: February 23, 2026 (updated March 11, 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
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)
{
"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)
{
"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)
{
"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)
{
"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)
{
"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 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:
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:
{
"access_token": "eyJ0eXAiOiJNVCIsImFsZyI...",
"token_type": "Bearer",
"expires_in": 3600
}
Step 3: Use Access Token
Authorization: Bearer eyJ0eXAiOiJNVCIsImFsZyI...
4.2 OAuth2 Authorization Code
User-based authentication (not recommended for this use case)
See Docusign OAuth2 documentation 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:
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 50
X-RateLimit-Reset: 1614358800
Error when limit exceeded:
{
"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
{
"compositeTemplates": [
{
"inlineTemplates": [
{
"customFields": {
"textCustomFields": [
{
"name": "SalesforceRecordId",
"value": "0018V00000ABC123",
"show": "false",
"required": "false"
}
]
}
}
]
}
]
}
6.2 List Custom Fields
{
"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):
{
"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:
GET /restapi/v2.1/accounts/{accountId}/templates?count=100&order=name&order_by=asc
Response:
{
"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:
GET /restapi/v2.1/accounts/{accountId}/templates/{templateId}
Response:
{
"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
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:
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
- Composite Templates Guide
- JWT Authentication
- Salesforce Named Credentials
- Salesforce HTTP Callouts
Document Version: 1.0
Last Updated: February 23, 2026