Update Custom Metadata Record in an External Salesforce Org Using SOAP API
Org to Org Integration Demystified
Background:
Recently, I worked on a project where I needed to update a custom metadata record in an external Salesforce org. Our source org held a list of configurations, each corresponding to an external org. Whenever a configuration was updated in the source org, it had to be reflected in the custom metadata record of the respective external org.
Use Case for this blog post:
In this post, we'll write Apex code to update a field value in a custom metadata-type record.
The Custom Metadata Type details:
Label - Presentify Integration Settings
API Name - Presentify_Integration_Setting__mdt
Record Name - Template_Presentation_ID
Field API Name - Value__c
Code
Below is a rough draft of the code. Feel free to refactor it according to your requirements & make it better.
public class customMetadataUtility {
// Method to retrieve the Access Token for an external Salesforce org
public static String getAccessTokenOfExternalOrg(String instanceUrl) {
// Step 1 - Implement your own logic to get the Access Token for the external org
// Example: Use a named credential or an authentication flow
// Step 2 - Return the Access Token
return 'YOUR_ACCESS_TOKEN';
}
public static HttpResponse updateCustomMetadata(String instanceUrl, String templatePresentationId) {
// Retrieve the access token
String accessToken = getAccessTokenOfExternalOrg(instanceUrl);
// Construct the API endpoint URL for SOAP API
String apiEndpoint = instanceUrl + '/services/Soap/m/61.0';
// Construct the SOAP request body
String body = '<?xml version="1.0" encoding="UTF-8"?>'
+ '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">'
+ '<soapenv:Header xmlns="http://soap.sforce.com/2006/04/metadata">'
+ '<SessionHeader>'
+ '<sessionId>'+accessToken+'</sessionId>'
+ '</SessionHeader>'
+ '</soapenv:Header>'
+ '<soapenv:Body xmlns="http://soap.sforce.com/2006/04/metadata">'
+ '<updateMetadata>'
+ '<metadata xsi:type="CustomMetadata">'
+ '<fullName>Presentify_Integration_Setting__mdt.Template_Presentation_ID</fullName>'
+ '<label>Template Presentation ID</label>'
+ '<protected>false</protected>'
+ '<values>'
+ '<field>Value__c</field>'
+ '<value>'+templatePresentationId+'</value>'
+ '</values>'
+ '</metadata>'
+ '</updateMetadata>'
+ '</soapenv:Body>'
+ '</soapenv:Envelope>';
// Set up the HTTP request
HttpRequest req = new HttpRequest();
req.setEndpoint(apiEndpoint);
req.setMethod('POST');
req.setHeader('Authorization', 'Bearer ' + accessToken);
req.setHeader('Content-Type', 'text/xml');
req.setHeader('SOAPAction', '""');
req.setBody(body);
// Send the HTTP request and get the response
Http http = new Http();
HttpResponse response = http.send(req);
// Check the response status and return info or throw an error
if (response.getStatusCode() == 200) {
return response;
}else{
throw new CalloutException('Failed to update metadata: ' + response.getBody());
}
}
}
Gotchas
Access Token Logic: The code doesn’t include logic to generate the access token. You can implement this using named credentials, authentication flows, or connected apps to get the access token. The
instanceUrl
is passed into thegetAccessTokenOfExternalOrg
method to identify which org to get the access token for (it is optional though)Name of the Custom Metadata Record in the request body
This is stored in the
<fullName>
tagIt has two parts to it, the
API Name of your Custom Metadata
&the Name of your Custom Metadata Record
, joined by a.
Example -
Custom_Metadata__mdt.Record_Name
Updating Multiple Fields: The above example updates one field (
Value__c
). To update multiple fields, include additional<values>
tags:<values> <field>FIELD_1_API_NAME__c</field> <value>FIELD_1_Value</value> </values> <values> <field>FIELD_2_API_NAME__c</field> <value>FIELD_2_Value</value> </values>
Call the code
customMetadataUtility.updateCustomMetadata('<INSTANCE_URL_OF_THE_EXTERNAL_ORG>', '<VALUE_TO_BE_UPDATED>');