Andy in the Cloud

From BBC Basic to and beyond…

240 thoughts on “Introduction to calling the Metadata API from Apex

  1. Pingback: Failing to update picklist on task object via metadata API | DL-UAT

  2. Hello Guys,

    I try to access read the PageLayout using the latest Metadata API i.e 33, I can read all other metadata excepting Layouts.

    Has any face the same problem.


  3. Andy, that’s indeed brilliant. Awesome stuff. However, I do have one question. Actually, the requirement is to sync two Objects in Salesforce, not only the data but the Metadata too. Let’s say there are two Objects, A and B. If a field is added or deleted in A, the same should reflect in B. Could you please suggest in detail how can I use your metadata api to achieve such functionality???

    • Thanks! There are a lot of examples for this in the metadataserviceexamples class you can use as a basis, then also look at my sobjectdataloader repo for the data side. I am afraid I just don’t have time to go into detail in this with you, sorry. Happy if you want to ask some hi level questions after having a look at the above.

  4. Hi Andy,
    This is very great and helpful API and I’ve a query about retrieving layout metadata. Is there a way I can retrieve all the fields on a specific layout provided the recordType?


  5. Hi Andy,

    I was stuck on a point I have a code which is working fine for retrieve the folder info of an org.

    MetadataService.MetadataPort service = new MetadataService.MetadataPort();
    List queries = new List();
    service.SessionHeader = new MetadataService.SessionHeader_element();
    service.SessionHeader.sessionId = UserInfo.getSessionId();
    MetadataService.ListMetadataQuery queryDocumentFolder = new MetadataService.ListMetadataQuery();
    queryDocumentFolder.type_x = ‘DocumentFolder’;
    MetadataService.FileProperties[] fileProperties = service.listMetadata(queries, 30);
    List folderNames = new List();
    for(MetadataService.FileProperties fileProperty : fileProperties)
    folderNames.add(fileProperty.fileName.replace(‘documents/’, ”));

    Now I want to make it generic so in the line “queryDocumentFolder.type_x = ‘DocumentFolder’;” instead of DocumentFolder if I pass “ApexClass” it should return all the Apex class of that org same for other component.
    Currently when I am trying to do this I am facing the exception can you please help me to come out of it?

    Thanks in Advance.


    • Sorry hard to help if you have to given me the exception your getting. However you may also like to know you can use Soql to query apex classes, just query the ApexClass object. Hope this help, if you want to proceed with Metadata API you will have to give me some more insight as to the exception message you have?

  6. The “create” method does not exist in the MetadataService.cls. Could you please update your example, or provide another example on how to use the Metadata API to create objects such as Workflow Rules using async methods?

  7. Thanks for posting this discussion. I would like to know How to get field Description from object metadata getDescription() ?? Thank you.

  8. Hi guys
    I need to pull lastModifiedDate for RecordType.
    Is this not supported by MetadataService?

    Workbench shows this information for every record type, also official Metadata API listing all the record types shows this.

    Any suggestions or do I need to make official Metadata API call and pull huge amout of RTs?

    • It should be a direct wrapper. Can you raise an issue on the GitHub site with a screenshot of what your seeing elsewhere in the docs and I will try to find it for you. Thanks.

      • I may have not described the case at hand clearly enough 🙂

        So, I’m pulling Record Types using readMetadata(‘RecordType’, ), but there is no info on lastModifiedDate.
        LastModifiedDate is included in listMetada(, ), which I guess is used by workbench and is indeed available in MetadataService, but this pulls huge amount of data in my org (over 600 RTs).

        I was wondering if there is a way to pull lastModifiedDate for RTs without querying all of them.
        Probably not, as my understanding is that lastModifiedDate is a property of a file holding metadata, not of specific metadata as such.

        Background requirement is to get picklist values for different record types, but in a web service for mobile devices, so time is of the essence. My approach for this is to create some “cache” with the values (sObject), that would be refreshed only if anything changed, thus I need lastModifiedDate for included RTs 🙂

        So my final question is: is there a way to pull lastModifiedDate for RTs without querying all of them?

      • Not via metadada API, have you looked at tooling API?

  9. Nope, not yet. I will look into it, but I’m resistant to including yet another API 🙂

  10. Hi Andrew,

    Thank you for such a fantastic class.
    I just wanted to know like if there is a way to reduce the size of the MetadataService class as it itself consumes around 500000 characters and we all know Salesforce is picky about the character limit.
    Any suggestion would be helpful.

    Warm Regards

    • This has been raised as an idea in the GitHub issues list for sure. And is a good one. Checkout some thoughts on there. Other than simply copy and pasting over what you need until it all compiles, I don’t yet have a tool or automated approach to cutting it down. Sorry.

  11. Hi Andrew,

    I tried to invoke the Metadata api from the Salesforce site but it is throwing an error like “Web service callout failed: WebService returned a SOAP Fault: UNKNOWN_EXCEPTION: Site under construction faultcode=UNKNOWN_EXCEPTION faultactor=” in the debug logs, Can you please help me to fix this

    • Check the code that initialises the end point in the metadataservice class, it might need adjusting for this execution context. Also if your running as guest this will not work as that user does not have API or admin access. For that matter I suspect your general issue is site users won’t either. What you may have to consider is a more advanced approach of using a precaptured oauth token from an admin user in the org and having the code pass that as the session id. However you need to be very very careful with this kind of elevation of privileges. What is it your doing with the metadata API, there are some things now that can be done via soql….

  12. hii…..

    How to create tab using metadata API.

    • Take a look at the examples class in the repo, if there is not one, you can probably figure it out from createObject example and by reviewing advice in my FAQ blog, linked from the readme file.

  13. Hi Andrew,
    I am recently getting readtimeout exception while fetching metadata for profiles. It occurs sometime not always, Could you please help me to fix this?.

    • There is a timeout property on the header where you set the session Id, try increasing this

      • Couldn’t find that property, although i added a line service.timeout_x = 90000; but didn’t work out, am i missing somehting

      • I think that’s the one, might be best to post your current issue on the GitHub repository as an issue, me and or others in FF or the community can view it more easily

      • ahh never mind, it worked like a charm, you are a rockstar as always ^_^

      • Ah wonderful!

  14. I have updated timeout property. Thank you very much.

  15. Hi all i am trying to automate post sandbox refresh activities and to achieve this i need to update email alerts, custom labels, outbound messages as at present we need to do manually one by one as these all are metadata so we can’t do by normal apex. so can you share any sugestions how it can be acheived. as in above examples i have seen creating fields and other stuffs.

  16. Did you already try to create connected app through metadataapi?

  17. Hello Andrew ,
    I tried with this MetadataService.AsyncResult[] results =
    service.create(new List { customField }); but gives me this errorMethod does not exist or incorrect signature: [MetadataService.MetadataPort].create(List). It seems that the create method doesn’t exist in MetadataService class that i just uploaded in my org. Big Thanks

  18. Hi All,

    This was a great discussion.

    I’m looking to retrieve all the metadata components (Objects, Fields, Pagelayouts, Validation Rules, Workflow Rules, Approval Processes) based on Last Modified Date by using Query or any kind of script.

    If anyone have any workaround for this.


    • You might want to look at the Tooling API where you can do soql over some of these metadata type objects, then come back to metadata API and build a package xml file driven by the results and passed to the retrieve API. Or you can stick with tooling API and retrieve what you need, though it only currently has a subset of Metadada types.

  19. Hi Andrew Fawcett,
    how can we enable account teams and chatter and lightning design system through apex code can you help me please.

  20. Thank You for Sharing Andrew Fawcett.
    But here i have to enable those things in other org so where can i provide user name and password,url?
    and also i created on package.xml file how can i deploy to org without using any tool like(eclipse,ant,migration,change set), is there any way to deploy through apex code or any back end process. here you provided MetadataServiceExamples class but am unable to find where you are passing username and password,here you are using MetadataDeployController how can you use ZipData prperty,getPackageXml method i tried to use same code in my org but it is not working.
    if you know anything can you provide that information.

    • The samples work only in the org they are installed in. They use UserInfo.getSessionId. If you want to do the same from one org to anther, you have to obtain an oAuth token (recommended) or login as another user via the Logon API and use the resulting session is (not recommend as you would have to store the target orgs user and password).

      • Hi Andrew,

        I tried replacing UserInfo.getSessionId from access token on another Org. But I’m getting multiple exceptions. But I’m getting INVALID_SESSION_ID exception. Then I tried updating the code as follows.

        MetadataService.MetadataPort service = new MetadataService.MetadataPort(); service.SessionHeader = new MetadataService.SessionHeader_element();

        //service.SessionHeader.sessionId = UserInfo.getSessionId();
        service.SessionHeader.sessionId = clientAccessToken;

        //I tried setting following as the endpoint_x. But was getting separate error
        //service.endpoint_x = ‘’;

        But then I was getting some other exception of “System.CalloutException: Web service callout failed: Unexpected element. Parser was expecting element ‘’ but found ‘'”

        Appriciate if you can help to figure this out. API versions of my source and target orgs are different as well. Source has 38 while target has 39. Not sure whether this might be the reason.

        Thanks a lot for your support in advanced

      • If looks like your trying to use the client access token? Just checking here, you are using an oAuth token from the user/password or web flow from oAuth? You cannot use the static client or secret id given when you setup the connected app. If you are using it. It looks like there is some unmarshalling issue. Run your code from dev console and review the debug log. You will be able to see the actual xml response returned this way. Hope this helps.

      • Many Thanks for the response! I’m using username/password to get access token. The issue i had was with remote site settings. It was pointed to the current instance. So i have changed it to target instance and it worked fine. Moving forward I need to use your solution in my source org as well as the target org. So what’s your suggestion on that?

      • For the source org you can use the running users session id so long as they have access to the API. If not you can have the admin go through the flow and store the oAuth token to be used by the code running on behalf of other users. Obviously use this approach with care

  21. Andrew,

    Need some help. I am trying to get details on profiles in my org using the API.

    I am getting a time out on getting any profile back from the API using this code
    (MetadataService.Profile) service.readMetadata(‘Profile’,new String[] { profn }).getRecords()[0]

    This call always times out, even if I turn up the timeout_x to 90000 so that it exceeds 120 seconds max on call outs and then errors out.

    Note in the above call out the variable profn is equal to a Profle Name that I got back from a call to service.listMetadata(quer, vers) where the type=’Profile’.

  22. Hi Andrew,

    Thanks for sharing such a great API.
    I am trying to deploy selected metadata to my destination org.
    My question is how can i create a zip out of the selected components to pass it as a parameter to deploy() call.

    Please suggest and thanks in advance.

  23. Hi, I am new to Sales Force so this might be a stupid question, but how can I import the .cls file into my org so that all those classes are available?

    • No worries. You can use many tools, if your familiar with command line, Google search for Salesforce Migration Toolkit

    • You can click the Deploy to Salesforce button on the readme file. This is not a Salesforce tool though. Others are IDE and also Developer Console

      • How would I import using the Developer Console? Again, many thanks, I am a bit new to this.

      • It depends if you only want a few classes, the key ones are metadataservice.cls and metadataservicetest.cls, then copy and paste is best. If it’s the whole repo it’s the Deploy to Salesforce button, or if you prefer to download the repo try the Salesforce Migration Toolkit I mentioned.

      • Got it, that clarified everything! Thank you very much for your help and this awesome wrapper!

  24. Hi, this may be a dumb question, but I am quite new to Salesforce. Could you please tell me how to use the .cls file? Do I have to import it into my SF org somehow? How do I make the classes contained in it available to my apex code in my org?

  25. Hi i am new in Salesforce i am try to delete the apex class in visual force page .. i am getting error, Compile Error: DML not allowed on ApexClass at line . please give any idea to delete the apex class in production using VF page

    • Sorry deleting apex code programmatically in apex directly via do is not supported by the platform.

      You could do this via the Metadada API, this is a WebService api so a http callout is needed. Also you need to use the deploy API operation. If you checkout my flow factory or declarative rollup summary tool in GitHub you can see examples. Also the apex Metadata API wrapper GitHub repo has a deploy example controller you can see.

  26. Hi Andrew,

    I want to update description of bulk custom fields (500 fields) at a time across multiple objects. Do we have any approach to do this?. Could you please provide me sample code for this.

    I know how to fetch the metadata details of custom fields by using Tooling API. From that, I could not able to do an update operation.

    Please check and let us know best approach to do this.


    • My best bet would be to use the Metadada API deploy operation, you can see an example in the deploy controller class and also by studying the deploy api documentation. You would need to include in the package sent to the deploy method .object files with only fields in and description, should should be enough, you can test this via a the ant tool perhaps before wasting time on coding. See the Salesforce migration toolkit for ant usage. Sorry I don’t have a ready made example for you.

  27. can we get all test classes and test methods from one particular project using tooling api then how ?

    • There is no concept of a project in the tooling API only the idea of workspace you set up by making other API calls. I have not kept up with tooling API calls, but it is possible there is an API to get this information since many ide’s provide this ui to select them. If not you will have to parse the apex code classes yourself for this. I just spent a few moments looking at the tooling API docs and didn’t see anything. You might find an answer by looking at code from IDE like MavensMate perhaps, i believe it’s code is open source? Good luck!

  28. Andrew,

    Really appreciate that you have taken the time to build this and are continuing to support it. I’m looking at using your wrapper in an isv package to dynamically add Salesforce’s url.

    Do you happen to know if this would pass the security review process?


    • If you use the component to prompt the admin to approve the connection with the Metadada API they appear to be accepting it. I have seen in the chatter group for the security review team them reference my post outlining this approach to setting up the remote site which allows the comms to work. I assume this is what you mean by “add Salesforce’s url” ?

  29. Hi Andrew Fawcett,

    Are we able to modify the metadata for a custom permission set, for example I am able to create a permission set but I would also like to enable a few check boxes under the System Permission. Like ViewEncryptedData. I would like to do this all with apex code but I couldn’t find anything, I noticed that the metadata has access to it.



    Permission Set that allows the user to Manage Encryption Keys & View Encrypted Data
    Manage Encryption



  30. Hi Andrew.

    I am battling to get a test mock class implemented for service.readMetadata on a page layout. The actual class is working fine, it is just the mock test that keeps failing with a System.NullPointerException: Attempt to de-reference a null object at the point where I do the readMetadata call. Any help would be greatly appreciated.


  31. how to get list of sharing setting and sharing rules in salesforce using metadata api?

  32. Hi, below code is giving me an exception, any idea? i have the remote site settings and i am on Spring17 release.


    System.CalloutException: Web service callout failed: WebService returned a SOAP Fault: Must specify a {}type attribute value for the {}metadata element faultcode=soapenv:Client faultactor=


    system.debug(‘printing ‘+URL.getSalesforceBaseUrl());
    MetadataService.MetadataPort service = new MetadataService.MetadataPort();
    service.SessionHeader = new MetadataService.SessionHeader_element();
    service.SessionHeader.sessionId = UserInfo.getSessionId();
    MetadataService.DuplicateRule customObject = new MetadataService.DuplicateRule();
    customObject.masterLabel=’Main Label’;
    string [] insertOperations = new string[]{‘Report’};
    string [] updateOperations = new string[]{‘Report’};

    MetadataService.SaveResult[] sr = service.createMetadata(new MetadataService.Metadata[]{customObject});

    • This could be a bug witb the wrapper code not supporting the more complex sharing metadata types. Can you post an issue on the GitHub repo please

  33. Hi Andrew,

    This is impressive. I’m trying to access metadata (Apex classes,VF pages,components,WF rules etc…) on Org B from Org A. I have the access token (retrieved via oAuth) to Org B. Can you use the same methodology to access them?

  34. MetadataService.MetadataPort isn’t found in the MetadataService WSDL. I am actually using C# to set field permissions on a salesforce object.

  35. Hi Andrew Fawcett,

    I am struggling to write an apex code to add new values to a standard picklist field, Can you please share some sample

  36. Hi People,

    Can anyone share apex code sample to add new values to a standard picklist field as a metadata service

  37. Could you please tell me if it is possible to install a managed package from app exchange also utilizing the metadata api?

  38. Hi Andrew,

    Thank you for sharing info on the Metadata api calls from Apex. I am trying to build a SandboxPostCopy script so that it can automate some of the post refresh activities. One of the setting I am trying to update is the remote site settings endpoints.

    After looking into some salesforce docs and online resources, I see that Metadata API is the only way to update RemoteSiteSettings. To access metadata api, I will need to configure the instance url as an endpoint which again requires accessing metadata api. Is there any other way to update the remote site settings through apex from the post copy script. Thanks in advance!

    • This is a catch for sure. Do you find your sandbox is always spinning up on the same instance? If so add this to your production org remote sites. If not, you can deploy my domain to get a fixed URL.

  39. Hi Andrew,
    I have come up with some custom Apex coding to Read Report Folder and displaying users list within custom Report Folder using your MetadataService class and would like to post it as a blog in my website Is it fine with you and I will refer to your blog as source for MetadataService class and keep the header declaration as intact – is that fine with you ?

  40. Pingback: Custom Reports Folder Sharing List using Metadata API – It's getting cloudy here…

  41. Pingback: Salesforce MetaData API Usage – Create Custom Field | Sharon Maliakkal

  42. Hi Andrew, Iam able to fetch data from Metadata API by using both listmetadata and readmetadata method by passing the fullname of listmetadata to Read Metadata inorder to retrieve other labels.Now i created two webservice mocks for listmetadata and readmetadata .when i try to test the main class with the both the webservice classes,only one (either listmeta or readmeta)is able to cover and eventually test class is failing with a stacktrace error,
    Any help is appreciable ,Thanks in advance

  43. Hi Andy, Would you Explain Why readmetadata method in Metadataport is not invoked in MetaData Service Test Class ?

    • It’s a complex API and mocking those responses didn’t seem valuable. Most of the code is system generated by salesforce as well. I appreciate this means not 100% coverage. If it’s an issue feel free to raise a GitHub request and we can look at it in the future. 👍🏻

  44. Hi Andy, I’m using your Metadata API to get a list of RemoteSites but the results do not include the actual URL only the names of the metadata fields and the ID of the Remote Site. Because this object is not exposed I cannot retrieve the fields from this ID using a SOQL query. For example, I have the Remote Site name as Google below but I cannot get the Remote Site URL which is “” Any suggestions?

    These are the results

    fileName=remoteSiteSettings/GoogleHome.remoteSite, fileName_type_info=(fileName,, null, 1, 1, false), fullName=GoogleHome,

    • I’ve added these lines into the public class FileProperties but no joy…

      public String url;
      private String[] url_type_info = new String[]{‘url’,’’,null,’1′,’1′,’false’};

      • The listMetadata response only lists some details of the Metadata types. To get all details you need to use readMetadata method

    • You need to use the readMetadata method once you know the full Metadata name of the remote site, which the listMetadata API returns. You can see examples of both in the MetadaraServiceExamples.cls class. Btw have you considered using Named Credentials? Assuming your wanting to avoid hard coding a URL is your motivation that is?

      • I see several different readMetadata methods (readMetadata_element , readMetadataResponse_element) which one do I use and now that I have the Remote Site name how do I invoke it?

      • There is only one readMetadata method, check out the examples in the metadataserviceexamples class

      • Would this work?

        MetadataService.RemoteSiteSetting rss = (MetadataService.RemoteSiteSetting) service.readMetadata(‘Google’, new String[] { ‘URL’ }).getRecords()[0];

  45. Andrew, I’m not sure I understand your response. I was referring to your Metadata Service class which has about three different variations of readMetaData methods. In any case, I did use the right readMetaData method and was unable to pull back the URL for the RemoteSite. It simply reads as “null.” This may be one of those fields that Salesforce doesn’t want to make accessible. Thanks for your blog, I find it very informative and interesting.

  46. Hi Andrew,
    Is there any way to get list of standard objects fields. I have tried using Partner API, But I am getting callout exception. Can you suggest on this?

  47. Hi Andrew,
    I am facing an issue while in the xml response while solving a problem statement regarding security settings from metadata class stating that “Web service callout failed: Unable to parse callout response. Apex type not found for element referrerPolicy”, and before this i got a similar error with “Web service callout failed: Unable to parse callout response. Apex type not found for element hstsOnForcecomSites”,i solved this thing by adding this newly added metadata field in the class,but now i am unable to trace the error for the first error, is there any way to find that error?any help would be greatly appreciated and Thanks in advance

    • Have you downloaded the latest file from GitHub? It seems these are fields that are not in the wsdl used to generate the class code. Sometimes this happens, your approach is one way to solve it. But if the missing info is complex it can be hard to guess. Please check the Apex Metadata api for your type and also check the wsdl. Did you by any chance change the version of Metadata api used by the class? If so this can also cause the issue, as the server will return xml not supported by the code since it was generated from an earlier version. If you need a new api version check for the latest in GitHub or follow the notes in the readme to generate a new one (though I think the latest was recently uploaded). Hope this helps. If not raise an issue on the GitHub sure and myself or another can try to help. Easier than chatting here. Andy

      • Thanks for the valuable suggestions Andy!! I Solved The issue by adding addditional required code in my metadata class by debugging the response,now its working fine

      • Thanks! Would you mind sharing snippets of what you added on the GitHub repo please?

  48. Hi Andy, I was writing a test class for some code that calls your wrapper to retrieve and modify picklist values. I was wondering if it’s possible to interrogate the request object’s parameters in the doInvoke method in the mock class? The use-case is that I would like to differentiate between a request for one picklist and another. Ideally I would also like to be able to see the metadatatype being requested, though this is optional at this point as so far my code just asks for ‘CustomField’ metadatatype . The type of request I am dealing with it readMetadata().

    • Yep you should be able to cast the ‘request’ parameter passed into the doInvoke method to the request type and then assert on the contents of it. Have a read through the readMetadata method code to figure out the request type or do System.debug(String.valueOf(request));

  49. Hi Andy, thanks for this tool.
    I’ve written a SandboxPostCopy class and it was used yesterday for the first time when we refreshed our sandbox. I see this line in the debug logs so I don’t think it’s worked. It’s from WebServiceCallout.invoke() in MetadataService.listMetadata(); Is there something extra I have to do to use Metadata API with SandboxPostCopy?

    CALLOUT_REQUEST|[9218]|listMetadata_element:[apex_schema_type_info=(, true, false), asOfVersion=43.0, asOfVersion_type_info=(asOfVersion,, null, 1, 1, false), field_order_type_info=(queries, asOfVersion), queries=(ListMetadataQuery:[apex_schema_type_info=(, true, false), field_order_type_info=(folder, type_x), folder=null, folder_type_info=(folder,, null, 0, 1, false), type_x=WorkflowOutboundMessage, type_x_type_info=(type,, null, 1, 1, false)]), queries_type_info=(queries,, null, 0, -1, false)]::SOAPAction=”” Accept=text/xml User-Agent=SFDC-Callout/44.0 SFDC_STACK_DEPTH=1 Content-Type=text/xml; charset=UTF-8

    EXCEPTION_THROWN|[9218]|System.CalloutException: Web service callout failed: WebService returned a SOAP Fault: INVALID_SESSION_ID: Invalid Session ID found in SessionHeader: Illegal Session faultcode=sf:INVALID_SESSION_ID faultactor=


    • This is by design the user context for sandbox copy classes does not expose a session id. This is a platform restriction. There was a discussion on twitter about this recently with no clear workaround other than having a vf page host the logic, which of course is not as automated as one would like.

      • Thanks for the quick response. Shame there’s no proper workaround but now I know I’ll manually work around it! Thanks!

  50. Hi Andy, I am working on creating a script to create custom site. Thanks to the examples in git, I can do that. However, I wanted to know if I can also create site subdomain via MetadataService to create a domain, if no domain exists. Thanks!

Leave a Reply to brcline Cancel reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s