Creating the Merge Call using Apex Call
This topic describes the details and sample code to send your Merge request to Conga Platform, using the bearer token you already obtained in the getAuth() method found in Authentication using Apex Call.
Now that you have a bearer token saved in
theauthTokenvariable, the next step is to create and send
the Mergerequest to Conga. Here are the goals for this method:
- Method Declaration
- Creating an HTTP request
- Set our Endpoint, Request Method, Headers, and Body for the API call
- Create an Http container to hold our response
- Creating our Http Instance
- Sending our Http request
- Checking the Response Status
- Logging the Response
- (Optional) Parsing the Response
Step-by-step Breakdown of startMerge()
Method Declaration - public static void startMerge()
The method startMerge() is declared as private and static, just like the getAuth() method.
Private means it can only be called from within the same class. Static means it belongs to the class itself rather than an instance of the class. This method is responsible for taking the existing authToken and using it to initiate the actual merge process against Conga Merge endpoint.
Creating an HTTP Request - HttpRequest mergeRequest = new HttpRequest();
A new instance of HTTP Request in created. This object is used to configure and send our HTTP request to the Merge API endpoint. Similar to the auth call, this is the container for all request details.
Setting Endpoint URL - mergeRequest.setEndpoint(mergeURL);
The endpoint for the HTTP request is set to the mergeURL. This should already be defined at the top of your class: private static final String mergeUrl = 'https://coreapps-rlspreview.congacloud.com/api/ingress/v1/Merge'; This URL tells the request where to send the merge instructions within Conga Platform.
Specifying the HTTP Method - mergeRequest.setMethod('POST');
The HTTP method is set to POST. This method uses POST here because you are sending data (the merge configuration and merge fields) to the server, which will then process that data and generate a merged document.
Setting Request Headers -
mergeRequest.setHeader('Authorization', 'Bearer ' + authToken);mergeRequest.setHeader('Content-Type','application/json');mergeRequest.setHeader('Accept','application/json');
Authorization:
This header includes the bearer token that was retrieved in
getAuth().The format is
Bearer <tokenValue>.Without this header, the Conga API will not recognize or authorize the request.
Content-Type:
Set this to application/json to indicate that the body of the request is JSON
The Conga Merge endpoint expects a JSON payload describing templates, destinations and merge data.
Accept:
This header indicates what type of response is expected to handle.
Setting application/json tells the API a JSON response is expected back.
Building the Request Body - Overview
The request body for the merge call is a JSON object made up of several key pieces:
- LegacyOptions– optional legacy configuration (like output file name).
- templateSources– the template(s) to merge against.
- destinations– where to store the merged output.
- jsondata– the actual merge field data in JSON format.
You will construct each of these as Apex collections (Map and List), then serialize them into a single JSON object that can be sent in the body.
Adding Legacy Options - mergeData.put('LegacyOptions', new
Map<String, String>{'OFN' => 'mergingFromCongaDrive'});
These are some Legacy Options that can be mapped to our top-level mergeData map.
- OFN stands for Output File Name.
- In this example, the output file name will be set to"mergingFromCongaDrive".
- This value can be changed to anything you'd like your merged document to be named.
mergeData.put('templateSources', new List<Map<String, String>>{
new Map<String, String>{
'integrationName' => 'conga',
'fileId' => fileId
}
});
integrationName - Typically set to 'conga' when using Conga Drive as the integration.
fileID - this is the ID of the template stored in Conga Drive. This was defined earlier as:
private string final String fileId= 'bd533afe-173b-4347-90eb-56f9f2b55db4';This is wrapped in a List<Map<String, String>> because the API supports multiple templates. In this example it is only one.
mergeData.put('destinations', new List<Map<String, String>>{
new Map<String, String>{
'integrationName' => 'conga',
'folderId' => 'root'
}
});
This section describes where the merged output should be stored. integrationName - Set to 'conga', indicating Conga Drive as the integration destination.
folderId - 'root' indicates the final merged document will be stored in the root folder. If using a specific folder id, replace 'root' with the appropriate folder ID. Just like templateSources, ths can be multiple values to indicate multiple destinations.
Preparing the Merge Field Data (jsonData) -
mergeData.put('jsondata', JSON.serialize(new Map<String, String>{
'firstname' => 'SampleData',
'lastname' => 'SampleData'
}));
The Map<String,
String> that holds field names and their values:- firstname→"SampleData"
- lastname→"SampleData"
- The keys ('firstname','lastname') should match the merge fields defined in your Conga template.
- The JSON.serialize(...) calls that serialized JSON string into
the jsondata key of our outer mergeData map.Important: JSONdata itself is expected as a string in the top-level JSON.
- You must serialize the inner map first, rather than embedding it directly as a nested JSON object.
- You can expand this map with as many merge fields as you need—simply add more key-value pairs that match your template fields.
Serializing the Full Merge Payload -
Once you have assembled all parts
of mergeData, convert the entire map into a JSON string: mergeRequest.setBody(JSON.serialize(mergeData)); At this point, the request body is a complete,
valid JSON object containing legacy options, template info, destinations, and
the serialized jsondata string.
Creating an HTTP Instance -
The send method dispatches the request to the Conga Merge API. The body constructed is sent to the /Merge endpoint. The Authorization header ensures our request is authenticated. Conga then processes the request, runs the merge and returns details about the results.
Checking and Logging the Response - System.debug('Merge Response: ' +
response.getBody());
- Status or result of the merge.
- Information about the generated document (location, ID, etc.), depending on the specific API contract.
- Additional checks can be added here, similar to the auth method:
Check
response.getStatusCode()for 2xx to confirm success.Log or handle errors if you receive a 4xx or 5xx code.
Full startMerge() Method Example
Here is the full startMerge() method including everything above.
private static void startMerge() {
System.debug('Merge process has begun...');
// Create our HTTP request for the Merge API
HttpRequest mergeRequest = new HttpRequest();
// Set the endpoint for the merge call
mergeRequest.setEndpoint(mergeUrl);
// Use POST since we are sending a JSON body
mergeRequest.setMethod('POST');
// Add the Bearer token and JSON headers
mergeRequest.setHeader('Authorization', 'Bearer ' + authToken);
mergeRequest.setHeader('Content-Type', 'application/json');
mergeRequest.setHeader('Accept', 'application/json');
// Build the JSON payload
Map<String, Object> mergeData = new Map<String, Object>();
// Legacy options (such as output file name)
mergeData.put('LegacyOptions', new Map<String, String>{
'OFN' => 'mergingFromCongaDrive'
});
// Template source - which template to merge against
mergeData.put('templateSources', new List<Map<String, String>>{
new Map<String, String>{
'integrationName' => 'conga',
'fileId' => fileId
}
});
// Destination - where the merged file should be stored
mergeData.put('destinations', new List<Map<String, String>>{
new Map<String, String>{
'integrationName' => 'conga',
'folderId' => 'root'
}
});
// Merge field data for the template
mergeData.put('jsondata', JSON.serialize(new Map<String, String>{
'firstname' => 'SampleData',
'lastname' => 'SampleData'
}));
// Serialize the entire payload and set it as the request body
mergeRequest.setBody(JSON.serialize(mergeData));
// Send the request and capture the response
HttpResponse response = new Http().send(mergeRequest);
// Log the full response for verification and troubleshooting
System.debug('Merge Response Status Code: ' + response.getStatusCode());
System.debug('Merge Response Body: ' + response.getBody());
}
Putting It All Together
initiateMerge()- is the entry point: it first callsgetAuth()to retrieve the bearer token, then callsstartMerge()to perform the actual merge.getAuth()- handles all aspects of authentication and populates the authToken.startMerge()- uses that token to build and send a JSON-based merge request containing:- Legacy options
- Template sources
- Destinations
- Merge field data
- From here, you can enhance the solution by:
- Mapping real Salesforce data into jsondata.
- Handling success and error conditions more
robustly based on
response.getStatusCode(). - Parsing the JSON response to capture the resulting document ID or link and attaching it back to a Salesforce record.
