Update Custom Metadata with Apex in my org

This can be accomplished with Apex Metadata API. Please check out this trailhead module:

https://trailhead.salesforce.com/en/content/learn/modules/apex_metadata_api


There's a nifty gitHub library from Andrew Fawcett that makes doing this somewhat easier. Motivation and detail on his blog


The Metadata.Operations class gives the ability to update/retrieve/insert metadata.

To answer your question about updating Custom Metadata, you'd be using the Metadata.Operations.enqueueDeployement();

I've provided the apex class you can create in your own org to reproduce.

1st steps: Create a Custom Metadata Type. If you'd like to use the code I provide verbatim, then follow these steps

a. Create Custom Metadata Type, name it "Test Custom Metadata".

b. Create a custom field named "Custom Field 1" of type Text.. api name would be Custom_Field_1__c

c. Click on Manage Test Custom Metadata(create a custom metadata record), and enter in the values for label : "Before_Change", that will populate the name with Before_Change as well. Enter in any text for the Custom_Field_1__c, for me, I put 'Testing before changes'.(This will be updated once the code is run)

d. Your custom metadata is all set up, and now it's time to create the apex class

e. Create an Apex Class named MetadataDeploy

f. Populate the following apex class with the code below.

public without sharing class MetadataDeploy implements Metadata.DeployCallback{

public List<FieldWrapper> listField{get;set;}
public class FieldWrapper
{
    public String fieldName {get; set;}
    public String fieldAPIName {get; set;}
}

public static String updateCustomMetadata()
{
    try {
    Test_Custom_Metadata__mdt tcm = getMetaDataRecords()[0]; //retrieving custom metadata records, using the first.
    Id customMetadataId = tcm.Id;
    system.debug('CustomMetadata Id ' + customMetadataId);
    Metadata.CustomMetadata customMetadata = new Metadata.CustomMetadata();
    customMetadata.fullName = 'Test_Custom_Metadata.Before_Change'; //custom metadata name
    customMetadata.label = 'Before_Change';
    // customMetadata.id = customMetadataId;
    Metadata.CustomMetadataValue customField1 = new Metadata.CustomMetadataValue(); //the values you're changing/updating
    customField1.field = 'Custom_Field_1__c'; //the custom field API Name that you're wanting to insert/update a value of
    customField1.value = 'FIeld Test 1 after';
    customMetadata.values.add(customField1);//add the changes to list of changes to be deployed
   
    // if(customMetadataId != null) //if a custom metadata record exists, add the id here
    // {
    //     Metadata.CustomMetadataValue customId = new Metadata.CustomMetadataValue();
    //     customId.field = 'Id';
    //     customId.value = customMetadataId;
    //     customMetadata.values.add(customId);
    // }
    
    Metadata.DeployContainer mdContainer = new Metadata.DeployContainer();
    mdContainer.addMetadata(customMetadata);
    
    MetadataDeploy callback = new MetadataDeploy();
    // Id jobId = Metadata.Operations.enqueueDeployment(mdContainer, null);
    
    Id jobId = Metadata.Operations.enqueueDeployment(mdContainer, callback);
    
    system.debug('jobId is ' + jobId);
    
    // Metadata.DeployContainer metaDeploy1 = new Metadata.DeployContainer();
    // metaDeploy1.addMetadata(approvalConfigToInsert);
    // Id AsynchResult1 = Metadata.Operations.enqueueDeployment(metadeploy1, null);
    // system.debug('jobId ' + mdContainer);
    return 'Success';
        
    } catch (Exception e) {
            return e.getMessage();
    }
    }
    public static list<Test_Custom_Metadata__mdt> getMetaDataRecords()
    {
        list<Test_Custom_Metadata__mdt> tcm = [Select Id, label FROM Test_Custom_Metadata__mdt];
        return tcm;
    }
   

    // find all sObjects available in the organization
    public void handleResult(Metadata.DeployResult result, Metadata.DeployCallbackContext context) {
        if(result.status == Metadata.DeployStatus.SUCCEEDED)
        {
            //success
            System.debug(' ===>'+ result);
        }else{
            //not success
            System.debug(' ===> fail '+ result);
        }
        
    }

}

Open up your developer console, and execute MetadataDeploy.updateCustomMetadata();

You can check the results in deployment status, or the logs where it says QueueableHandler.

Check the Custom Metadata Record and see if it updated to 'FIeld Test 1 after', if it did, it successfully deployed the change.

TLDR: You can update Custom Metadata by using the Metadata.Operations.enqueueDeployment(metadataContainer, callback). The metadataContainer is basically setting up the package to deploy, which would be Metadata.CustomMetadata, filling out the values that you want to change (Metadata.CustomMetadataValue), and placing it in the metadata container(Metadata.DeployContainer.add(customMetadata). The callback is a way for the results to be handled, so if it failed or succeeded, you can get a response back.