I have used the following code to add new picklist values to the picklist field called "Tags__c" in contact object. The code works and the new picklist values are getting created successfully but they are not added to any record types and hence i have to manually add them to the record types to view the new values in UI. I need to do assign the existing record types for the new picklist values created through apex metadataservice code.

public static void updatePicklist()
    MetadataService.MetadataPort service = new MetadataService.MetadataPort();             
    service.SessionHeader = new MetadataService.SessionHeader_element();
    service.SessionHeader.sessionId = UserInfo.getSessionId();
    MetadataService.CustomField customField = (MetadataService.CustomField) service.readMetadata('CustomField', new String[] { 'Contact.Tags__c' }).getRecords()[0];
    metadataservice.PicklistValue two = new metadataservice.PicklistValue();
    two.fullName= 'Sample 1';
    metadataservice.PicklistValue three = new metadataservice.PicklistValue();
    three.fullName= 'Sample 2';
        new MetadataService.Metadata[] { customField })[0]);   

Can someone suggest me a solution for this?

2 Answers 2


The RecordType object has a picklistValues property that you can use to make values available to a record type.

Once you've added your picklist value, you can retrieve the record type, update the picklistValues property with the values that should be available, and then make another update call to save the metadata.


So to actually do this is a little more complex.

First you have to get the possible values for the field. This is necessary because updating the record type values requires the full list of available values. There's no way to append.

I've just used the Account 'Industry' field for my example. You'd swap in your object and field;

// Get the values for the picklist
MetadataService.CustomField picklistField = (MetadataService.CustomField) service.readMetadata(
            'CustomField', new String[] { 'Account.Industry' }

After that you need to get the picklist values from the field and add your new value to the list.

MetadataService.PickListValue[] pickVals = picklistField.picklist.picklistValues;
MetadataService.PickListValue newPickVal = new MetadataService.PickListValue();
newPickVal.fullName = 'New Picklist Value';

To add your value to ALL record types you'd need to get your record type names somehow. Since you're using Apex you can just use SOQL or a describe call if you want. There's documentation on both so I'm not going to cover it here.

After you get you list of record types, you need to retrieve them.

    String[] recordTypeNames; // get your list of record types either through a query or a describe call and put them into a list        

    // Get the record type from the API
    MetadataService.Metadata[] mdRecordTypes = service.readMetadata(
                    'RecordType', recordTypeNames
MetadataService.RecordType[] recordTypes = (MetadataService.RecordType[]) mdRecordTypes;

Next, initialize the RecordTypePicklistValue object that you're going to use to specify the picklist values for each record type. Then create a new RecordTypePicklistValue for the field you're adding to.

// initialize the list of record type picklist values
MetadataService.RecordTypePicklistValue[] rtPickValues = new MetadataService.RecordTypePicklistValue[]{};
MetadataService.RecordTypePicklistValue rtPickValue = new MetadataService.RecordTypePicklistValue();

// Create the recordtypepicklist and add it to the list of picklist fields for the record type
rtPickValue.picklist = 'Industry';
rtPickValue.values = pickVals;

Finally, got through all RecordTypes and set the picklistValues to the values you just created and make an update call.

// loop through the record types and set the picklist values
for(MetadataService.RecordType RT : recordTypes){
    RT.PicklistValues = rtPickValues;

// Update the record type
                new MetadataService.Metadata[] { mdRecordTypes });

There are a lot of code samples in the apex-mdapi repo that can show you additional samples if you need them.

  • If its not too much to ask, can you please post some sample code.
    – Ean
    Commented Feb 28, 2017 at 10:54
  • Edited to include a sample Commented Feb 28, 2017 at 23:07
  • Great!.This is very helpful.
    – Ean
    Commented Mar 1, 2017 at 8:00
  • @JohnTowers Am getting null value in this line MetadataService.CustomField picklistField = (MetadataService.CustomField) service.readMetadata( 'CustomField', new String[] { 'Account.Industry' } ).getRecords()[0]; Can someone help me?. Commented May 6, 2018 at 16:31
  • Are you actually trying to update the Industry picklist values? Or a different field? As of Winter '17 (API version 38.0) standard picklist fields are no longer CustomFields but StandardValueSets. This specific example may no longer work. But if you're trying to modify a custom field you should still be able to switch out the object/field in this example with your own metadata. Commented May 8, 2018 at 1:09

I do have different approach using tooling api instead of Apex Metadata Service. Actually, Apex Metadata Service requires to import all code (whether it's related to your implementation or not).

I know this is not a relevant answer as question clearly states 'Using Metadata Service' but I think this approach is to achieve same requirement and new salesforce way approach and can be helpful to others.

1. Make first HTTP callout to insert/remove new picklist value:

Method: PATCH

URL: /services/data/v41.0/tooling/sobjects/CustomField/00N540000071QJG (Replace Custom field Id with your custom field)

Payload: Custom field metadata with updated picklist value as given here: https://gist.github.com/ayub-ansari/eb4217f43244c5d54c1510898ce85f59.

(Please note that you can get the metadata of field by making this same HTTP call with method GET without any payload. I use workbench for this POC).

2. Make second HTTP callout to include new picklist values under record type:

Method: PATCH

URL: /services/data/v41.0/tooling/sobjects/RecordType/012f20000009x5X (Replace Record Type Id with your one)

Payload: Custom field metadata with updated picklist value as given here: https://gist.github.com/ayub-ansari/27c0c4b9a8ea14d65ab546145f679b4d.

(Please note that you can get the metadata of field by making this same HTTP call with method GET without any payload. I use workbench for this POC).

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .