23 KiB
Design Document
Project: Salesforce Composite Envelope Builder
Version: 1.0
Date: February 23, 2026
Author: Paul Huliganga
1. Architecture Overview
1.1 System Context
┌──────────────────┐
│ Salesforce User │
└────────┬─────────┘
│
▼
┌─────────────────────────────────────────┐
│ Salesforce Platform │
│ ┌──────────────┐ ┌───────────────┐ │
│ │ Screen Flow │───▶│ Apex Class │ │
│ │ (Template │ │ (Composite │ │
│ │ Selection) │ │ Builder) │ │
│ └──────────────┘ └───────┬───────┘ │
│ │ │
└──────────────────────────────┼───────────┘
│
▼ HTTPS/REST API
┌──────────────────────┐
│ Docusign REST API │
│ (Composite │
│ Templates) │
└──────────────────────┘
1.2 Component Architecture
┌────────────────────────────────────────────────────────┐
│ Salesforce Org │
│ │
│ ┌─────────────────────────────────────────────────┐ │
│ │ Presentation Layer (Screen Flow) │ │
│ │ - Language selection │ │
│ │ - Template display (checkbox collection) │ │
│ │ - Success/error messaging │ │
│ └──────────────────┬──────────────────────────────┘ │
│ │ │
│ ┌─────────────────▼──────────────────────────────┐ │
│ │ Business Logic Layer (Apex) │ │
│ │ │ │
│ │ ┌─────────────────────────────────────────┐ │ │
│ │ │ DocusignCompositeEnvelopeBuilder │ │ │
│ │ │ - @InvocableMethod entry point │ │ │
│ │ │ - Input validation │ │ │
│ │ │ - Composite JSON construction │ │ │
│ │ │ - Envelope ID return │ │ │
│ │ └──────────────────┬──────────────────────┘ │ │
│ │ │ │ │
│ │ ┌─────────────────▼──────────────────────┐ │ │
│ │ │ DocusignAPIService │ │ │
│ │ │ - API authentication │ │ │
│ │ │ - HTTP callout construction │ │ │
│ │ │ - Response parsing │ │ │
│ │ │ - Error handling │ │ │
│ │ └──────────────────┬──────────────────────┘ │ │
│ │ │ │ │
│ │ ┌─────────────────▼──────────────────────┐ │ │
│ │ │ DocusignCredentials │ │ │
│ │ │ - Credential retrieval │ │ │
│ │ │ - Token management │ │ │
│ │ └─────────────────────────────────────────┘ │ │
│ └──────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────┐ │
│ │ Data Layer │ │
│ │ - Named Credential (Docusign API creds) │ │
│ │ - Custom Settings (configuration) │ │
│ └──────────────────────────────────────────────┘ │
└───────────────────────────────────────────────────────┘
│
▼ HTTPS REST API
┌──────────────────────┐
│ Docusign Platform │
└──────────────────────┘
2. Detailed Component Design
2.1 DocusignCompositeEnvelopeBuilder (Main Class)
Purpose: Invocable Apex class that combines multiple Docusign templates into a single envelope
Responsibilities:
- Receive template IDs from Screen Flow
- Validate inputs
- Construct composite template JSON
- Delegate API call to service class
- Return envelope ID to Flow
Methods:
// Flow-invocable entry point
@InvocableMethod(
label='Send Composite Docusign Envelope'
description='Combines multiple templates into one envelope'
)
public static List<Result> sendCompositeEnvelope(List<Request> requests)
// Private helper methods
private static String buildCompositeEnvelopeJSON(
List<String> templateIds,
String recordId,
String language,
Map<String, String> customFields
)
private static void validateInputs(Request req)
private static List<String> sortTemplatesAlphabetically(List<String> templateIds)
Inner Classes:
public class Request {
@InvocableVariable(required=true label='Template IDs')
public List<String> templateIds;
@InvocableVariable(required=true label='Salesforce Record ID')
public String recordId;
@InvocableVariable(required=false label='Language')
public String language; // 'en' or 'es'
@InvocableVariable(required=false label='Email Subject')
public String emailSubject;
@InvocableVariable(required=false label='Custom Fields')
public Map<String, String> customFields; // For merge fields
}
public class Result {
@InvocableVariable(label='Envelope ID')
public String envelopeId;
@InvocableVariable(label='Success')
public Boolean success;
@InvocableVariable(label='Error Message')
public String errorMessage;
}
2.2 DocusignAPIService (Service Class)
Purpose: Handles all Docusign REST API interactions
Responsibilities:
- Construct HTTP requests
- Make callouts to Docusign API
- Parse responses
- Handle errors and retries
- Log API interactions
Methods:
public static String createCompositeEnvelope(
String envelopeJSON,
DocusignCredentials creds
)
public static HttpResponse callDocusignAPI(
String endpoint,
String method,
String body,
Map<String, String> headers
)
public static String parseEnvelopeId(HttpResponse response)
private static void logAPICall(
HttpRequest req,
HttpResponse res,
Long durationMs
)
private static void handleAPIError(HttpResponse response)
2.3 DocusignCredentials (Credential Management)
Purpose: Retrieve and manage Docusign API credentials securely
Responsibilities:
- Fetch credentials from Named Credential or Custom Settings
- Handle token refresh (JWT/OAuth2)
- Provide credential object to service layer
Methods:
public static DocusignCredentials getInstance()
public String getAccessToken()
public String getAccountId()
public String getBaseUrl()
private static String refreshAccessToken() // JWT or OAuth2 refresh
public class CredentialException extends Exception {}
Properties:
public String baseUrl { get; private set; }
public String accountId { get; private set; }
public String accessToken { get; private set; }
public DateTime tokenExpiry { get; private set; }
3. Data Flow
3.1 Sequence Diagram: Send Composite Envelope
User Flow Apex Service Docusign API
│ │ │ │ │
│ Select │ │ │ │
│ Templates │ │ │ │
├────────────▶│ │ │ │
│ │ │ │ │
│ │ Invoke Apex │ │ │
│ │ Action │ │ │
│ ├──────────────▶│ │ │
│ │ (templateIds) │ │ │
│ │ │ │ │
│ │ │ Validate inputs │ │
│ │ ├────────┐ │ │
│ │ │ │ │ │
│ │ │◀───────┘ │ │
│ │ │ │ │
│ │ │ Build JSON │ │
│ │ ├────────┐ │ │
│ │ │ │ │ │
│ │ │◀───────┘ │ │
│ │ │ │ │
│ │ │ Get credentials │ │
│ │ ├───────────────────▶│ │
│ │ │ │ │
│ │ │◀───────────────────┤ │
│ │ │ (creds) │ │
│ │ │ │ │
│ │ │ Call API │ │
│ │ ├───────────────────▶│ │
│ │ │ (JSON, creds) │ │
│ │ │ │ │
│ │ │ │ POST /envelopes │
│ │ │ ├─────────────────▶│
│ │ │ │ │
│ │ │ │ 201 Created │
│ │ │ │ {envelopeId} │
│ │ │ │◀─────────────────┤
│ │ │ │ │
│ │ │ envelopeId │ │
│ │ │◀───────────────────┤ │
│ │ │ │ │
│ │ Result │ │ │
│ │ (envelopeId) │ │ │
│ │◀──────────────┤ │ │
│ │ │ │ │
│ Success │ │ │ │
│ Message │ │ │ │
│◀────────────┤ │ │ │
│ │ │ │ │
3.2 Error Handling Flow
Apex Service Docusign API
│ │ │
│ Call API │ │
├────────────────▶│ │
│ │ POST /envelopes │
│ ├─────────────────▶│
│ │ │
│ │ 400 Bad Request │
│ │ (error JSON) │
│ │◀─────────────────┤
│ │ │
│ │ Parse error │
│ ├──────┐ │
│ │ │ │
│ │◀─────┘ │
│ │ │
│ │ Throw exception │
│ │ │
│ Catch exception │ │
│◀────────────────┤ │
│ │ │
│ Log error │ │
├──────┐ │ │
│ │ │ │
│◀─────┘ │ │
│ │ │
│ Return Result │ │
│ (success=false, │ │
│ errorMessage) │ │
│ │ │
4. Docusign Composite Template JSON Structure
4.1 Request Format
{
"status": "sent",
"emailSubject": "Please review and sign these forms",
"compositeTemplates": [
{
"compositeTemplateId": "1",
"serverTemplates": [
{
"sequence": "1",
"templateId": "TEMPLATE_ID_FORM_A"
}
]
},
{
"compositeTemplateId": "2",
"serverTemplates": [
{
"sequence": "2",
"templateId": "TEMPLATE_ID_FORM_B"
}
]
},
{
"compositeTemplateId": "3",
"serverTemplates": [
{
"sequence": "3",
"templateId": "TEMPLATE_ID_FORM_C"
}
]
}
]
}
4.2 Apex JSON Construction
Approach: Use Map<String, Object> + JSON.serialize() for dynamic construction
List<Object> compositeTemplates = new List<Object>();
Integer sequence = 1;
for (String templateId : sortedTemplateIds) {
Map<String, Object> template = new Map<String, Object>{
'compositeTemplateId' => String.valueOf(sequence),
'serverTemplates' => new List<Object>{
new Map<String, Object>{
'sequence' => String.valueOf(sequence),
'templateId' => templateId
}
}
};
compositeTemplates.add(template);
sequence++;
}
Map<String, Object> envelope = new Map<String, Object>{
'status' => 'sent',
'emailSubject' => emailSubject,
'compositeTemplates' => compositeTemplates
};
String envelopeJSON = JSON.serialize(envelope);
5. API Integration Details
5.1 Endpoint
POST https://{baseUrl}/restapi/v2.1/accounts/{accountId}/envelopes
Where:
{baseUrl}: e.g.,na3.docusign.net(from Named Credential){accountId}: Docusign account GUID (from Named Credential or Custom Settings)
5.2 Headers
Authorization: Bearer {access_token}
Content-Type: application/json
Accept: application/json
5.3 Authentication
JWT (JSON Web Token) - Preferred:
- Use RSA key pair stored in Named Credential
- Generate JWT, exchange for access token
- Token valid for 1 hour, cache and refresh as needed
OAuth2 Authorization Code - Alternative:
- User-based authentication
- Access token + refresh token
- Requires user interaction for initial authorization
5.4 Response Codes
| Code | Meaning | Action |
|---|---|---|
| 201 | Created | Success - parse envelope ID |
| 400 | Bad Request | Invalid JSON or parameters - log and return error |
| 401 | Unauthorized | Token expired - refresh and retry |
| 403 | Forbidden | Insufficient permissions - log and return error |
| 429 | Too Many Requests | Rate limit - retry after delay |
| 500 | Server Error | Docusign issue - log and return error |
6. Governor Limit Considerations
6.1 Heap Size
- Limit: 6 MB (synchronous), 12 MB (asynchronous)
- Mitigation:
- Serialize JSON incrementally
- Avoid loading large objects into memory
- Process template IDs in batches if needed (future enhancement)
6.2 CPU Time
- Limit: 10,000 ms (synchronous)
- Mitigation:
- Minimize loops and complex logic
- Delegate heavy work to Docusign API
6.3 Callouts
- Limit: 100 callouts per transaction, 10-second timeout per callout
- Mitigation:
- Single API call per envelope
- Use asynchronous callouts (@future) for bulk operations (future enhancement)
6.4 SOQL Queries
- Limit: 100 queries per transaction
- Mitigation:
- Minimize queries in loop (not applicable for this design)
- Cache credentials if fetched via SOQL
7. Security Design
7.1 Credential Storage
Option 1: Named Credential (Preferred)
- Credentials encrypted by Salesforce
- No code changes needed for credential updates
- OAuth flows managed by platform
Option 2: Protected Custom Settings
- API credentials stored encrypted
- Accessible only via Apex
- Manual token refresh required
7.2 Access Control
- Apex class runs in user context (sharing rules enforced)
- Users must have:
- Permission to execute Flows
- Read access to Salesforce record
- Docusign send permission (managed via Docusign)
7.3 Data Protection
- No sensitive data logged in debug statements
- API credentials never exposed in logs or error messages
- HTTPS for all API communication
8. Testing Strategy
8.1 Unit Tests
Test Coverage Goal: >75% (Salesforce requirement)
Test Classes:
DocusignCompositeEnvelopeBuilderTestDocusignAPIServiceTestDocusignCredentialsTest
Test Scenarios:
- Success case: 3 templates combined, envelope created
- Edge case: 1 template (minimum)
- Edge case: 14 templates (maximum)
- Error case: Invalid template ID
- Error case: API returns 400
- Error case: API returns 401 (token expired)
- Error case: API timeout
- Mock callouts: Use
HttpCalloutMockfor Docusign API
8.2 Integration Tests
Manual Testing:
- Create test Docusign templates in sandbox
- Configure Named Credential with sandbox credentials
- Execute Screen Flow with various template combinations
- Verify envelope creation in Docusign sandbox
- Verify documents written back to Salesforce
8.3 Performance Tests
- Test with maximum templates (14)
- Measure Apex CPU time
- Verify heap size usage
- Test concurrent requests (multiple users)
9. Deployment Architecture
9.1 Deployment Components
Metadata to Deploy:
- Apex classes:
DocusignCompositeEnvelopeBuilder.clsDocusignAPIService.clsDocusignCredentials.cls- Test classes (3 files)
- Named Credential configuration
- Remote Site Settings (for Docusign API URL)
- Permission Sets (optional, for access control)
9.2 Deployment Steps
-
Sandbox deployment (via VS Code or CLI):
sf project deploy start --target-org sandbox -
Run unit tests:
sf apex run test --wait 5 -
Validate production (without deployment):
sf project deploy validate --target-org production -
Deploy to production:
sf project deploy start --target-org production
9.3 Rollback Plan
- Version control: Git repository tracks all changes
- Destructive changes: Remove Apex classes if needed
- Flow modification: Update Flow to call old logic temporarily
10. Monitoring & Maintenance
10.1 Logging
Debug Logs:
- Log API request/response (sanitized, no credentials)
- Log execution time
- Log errors with stack traces
Custom Object (Optional):
- Store API call history in custom object
Docusign_API_Log__c - Fields: Timestamp, Envelope ID, Template Count, Status, Error Message
10.2 Alerts
- Email alerts for repeated API failures
- Platform Event for real-time monitoring (future enhancement)
10.3 Maintenance Tasks
- Monitor Docusign API rate limits
- Review logs for errors
- Update templates as business needs change
- Refresh API credentials before expiry
11. Future Enhancements
11.1 Phase 2 Features
- Dynamic recipient selection: Override template recipients
- Conditional form selection: Show/hide forms based on Salesforce data
- Bulk sending: Send envelopes to multiple records
- Template caching: Cache template metadata to reduce API calls
11.2 Technical Improvements
- Asynchronous processing: Use
@futureor Queueable for large batches - Retry logic: Automatic retry for transient failures
- Rate limit handling: Intelligent backoff and retry
- Analytics dashboard: Lightning component for usage reporting
12. Glossary
| Term | Definition |
|---|---|
| Composite Template | Docusign feature to combine multiple templates into one envelope |
| Invocable Method | Apex method callable from Screen Flows, Process Builder |
| Named Credential | Salesforce feature for secure external credential storage |
| JWT | JSON Web Token - authentication method for server-to-server integration |
| Governor Limits | Salesforce platform resource limits (CPU, heap, callouts) |
Document Status: Draft
Next Steps: Review with stakeholders, begin Apex development
Estimated Effort: 3-5 days development + 2 days testing