Andy in the Cloud

From BBC Basic to and beyond…

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

  1. nice post. Can you please also write an intro for Tooling API? thx

  2. I’m playing around with your retrieve demo and was wondering how you retrieve more than one type in a single call. For example, I’m trying to get profiles and custom object types. I tried modifying the retrieveMedatadataItem() method and have something like this:

    MetadataService.PackageTypeMembers packageType = new MetadataService.PackageTypeMembers(); = ‘Profile’;
    packageType.members = new String[] {‘Admin’};

    MetadataService.PackageTypeMembers packageType2 = new MetadataService.PackageTypeMembers(); = ‘CustomObject’;
    packageType.members = new String[] { ‘Account’,’Contact’ };

    AsyncResult = service.retrieve(retrieveRequest);

    But this only brings back CustomObject.

    What am I doing wrong?

    • There is a bug in the above code, you are not setting up the packageType2 variable.

      • Thanks Andrew. I realized my mistake too after my post. Ahh, the pitfalls of copy and paste!

      • Ah no worries. Note that the Profile info is only complete as far as the other components you retrieve in the request. So for example, you will only get VF page permissions if you also include those in the package manifest. Though the permission set objects do not give all profile info, you may want to look at using SOQL to query those (under the covers the platform creates a permission set per profile).

  3. Hi Andrew, I am absolutely grateful for this wonderful post. I was trying to tweak the generate code for couple of days but even after trying was missing some points, your code finally helped me to get through it. Unfortunately SFDC documentation is nil and SFDC must provide much more support for WSDL2APEX for this very useful feature. Thanks again.

  4. Pingback: Updating Layouts in Apex | Andy in the Cloud

  5. I have setup the demo in my sandbox, but for some components in the metadataretrieve page, i get the following errors –

    1. ApexClass – Collection size 2,298 exceeds maximum size of 1,000.
    2. CustomField – IO Exception: Read timed out
    Error is in expression ‘{!listMetadataItems}’ in page metadataretrieve

    I have an idea how to handle the first error, what do i do about the second error?

  6. Hi Andrew, thanks for posting and for the good work you have done here. I just completed some work to effectively create universal picklists based on this library. This saves my client a lot of headaches in updating multiple picklists all over the place and of course, reduces errors caused by mismatches between these lists.

  7. Hi Andrew, firstly, thanks very much for the excellent post. It was of great help. I am trying to access the metadata in one sandbox from another sandbox and it gives me error that the session Id is invalid. I believe this is because I first need to login to the target sandbox before I execute any query on it, but I am new to Apex and not sure how to do it from the Metadata API context. Below is my createservice() method, and I think the login part with the username and password needs to be included within this but not sure how. Can you please correct this and help here?

    public static MetadataService.MetadataPort createService() {
    MetadataService.MetadataPort service = new MetadataService.MetadataPort();
    service.SessionHeader = new MetadataService.SessionHeader_element();
    service.SessionHeader.sessionId = UserInfo.getSessionId();
    return service;

    Also I ‘m not sure if I need to send an AuthToken during the login process and if Yes, how? Will be of great help if you can shed some light on this.

    Many Thanks!

    Best Regards,

    • Hi,

      Yes you do need to login to the other org to get the correct Session ID. Take a look at this answer on StackExchange for an example of how to use the Salesforce API Web Service to perform a login from Apex.

      You can also go via the oAuth web flow (user enters user name password and redirects back to your page) to obtain an AuthToken (which will last longer if you want to make multiple metadata calls over a longer period of time and aviods you having to store the user/password). Once you have the oAuth token you can pass this in the sessionId field as well. I don’t have an example of this to hand unfortunately, though have been meaning to find one.

      The above user name and password option should work fine, just be careful what you do with the user and password used for security reasons. Maybe not so much of an issue if its your own sandboxes i guess.

      Hope this helps!



  8. Thanks very much Andy! That really helped. Now my code is able to login to the target Org. I am trying to retrieve the details of the workflow alerts such as the name, description, sender, recipients, and email template. But I am able to retrieve only the alert fullname. For emailalert.description, emailalert.senderAddress, emailalert.template i get an error saying that the variables do NOT exist. But as per the Metadata API documentation these variables are available under workflowalert. Below is my code, can you please take a look and let me know if you see what I am missing here?

    MetadataService.MetadataPort service = MetadataService.createService();

    List queries = new List();
    MetadataService.ListMetadataQuery queryEmailAlert = new MetadataService.ListMetadataQuery();
    queryEmailAlert.type_x = ‘WorkflowAlert’;

    MetadataService.FileProperties[] properties = service.ListMetaData(queries,30);

    for(MetadataService.FileProperties emailalert:properties){
    system.debug(‘Email Alert Name:::’+emailalert.fullname);
    system.debug(‘Created By:::’+emailalert.CreatedByName);

    Many Thanks in advance,

  9. Sure Andrew, I have posted the issue in GitHub here –
    Can you please take a look and share your thoughts? Many Thanks!

  10. Hi Andrew,

    I have updated the post in github with the latest status and findings. Could I please request you to take a look and share your thoughts since this is very urgent on my side to meet one my deliveries. Many Thanks!

    • No problem, i’ve found the solution for you, unfortunately at this time it appears GitHub is having some issues. I have tried updating the issue by responding via email, you will need the attached class files (custom MetadataService.cls based on the one i used in the Spring’14 metadata api blog) and the following sample code, but i did get it to work! 🙂

      // Read Workflow Alert
      MetadataService.WorkflowAlert wfa =
      (MetadataService.WorkflowAlert) service.readMetadata(‘WorkflowAlert’,
      new String[] { ‘Account.Test’ }).getRecords()[0];
      System.debug(‘Description ‘ + wfa.description);
      System.debug(‘Sender Address ‘ + wfa.senderAddress);

  11. Hi Andrew,

    Is there any limitation on number of Objects/Fields that can be created in one call ?

    • Yes the Salesforce Metadata API documentation states that only 10 items per ‘create’ call can be passed. In Apex you can only make 10 outbounded calls per request, so maximum in theory of 100. You could also deploy an entire object via the ‘deploy’ call, see the deploy examples, though these do need a client side peace of code.

  12. Hi Andrew, while doing a webservice callout, is it possible to print the response XML to take a complete look at what is received? If yes can you please explain how?

  13. Yes, if you enable HTTP callout in the Debug log levels this will be in your Salesforce debug logs.

  14. Thanks very much Andrew! I need help on designing a requirement. It mayn’t me related to this thread but don’t know how to reach you elsewhere, so posting it below, apologies if it’s wrongly placed here. Can you please take a look and share your thoughts?

    Display an Emails related list under Contacts that displays all the emails sent to the Contact from Salesforce (from Email alerts, or Triggers, etc).

    Basically whenever an automated email is sent from Salesforce, the details of the email(From, To, Date, Subject, Body, Attachments) should be saved along with the contact as a related list for future reference.

    I understand whenever the email is sent from trigger or other classes through OutboundEmailHandler then it can be done within the code. But I’m not sure how to capture the automated emails that are sent from workflow alerts. Will appreciate any help on this.
    Many thanks!

  15. Hi Andy,

    Love the work that you have done here! I am curious to find out how things are coming along now that Spring 14 is out. Are you planning a v30.0 update to this wrapper?

    • Yes I am indeed! Cannot wait, all my dev orgs are in EU instances and I need to wait till the 18th! Soon though!

  16. Hi Andrew,
    the class MetadataPort within the MetadataService.cls does not contain the method readMetaData(), so i can not write this in my apex code ‘service.readMetadata. Can you help me please.

    • This is because i have not released the Spring’14 version of it yet, you can get a preview version of it here in the meantime, though it is incomplete. Once the Spring’14 rollout completes on all instances (specifically my EU ones!) i will release it before the end of the month formally with full support for all metadata types (only some are supported in the preview version).

  17. Awesome!!! Thanks a lot buddy for this awesome post. I spent hours reading salesforce metadata API documentation but I could not find anything. But after going through your apex library in Github I was able to create new object an fields in couple of hours.

    But now I am stuck in another issue. As per my requirement I have to add components to Home Page Layout through Apex, and my client has suggested to use Metadata API. I found two wrapper classes “HomePageLayout” and “HomePageComponent”,, but I am not able to add components to HomePageLayout . I am stuck in this big time. Could you help me please

    Thanks in Advance

  18. Hi Andrew,
    I’m using the MetadataService to get the Flows (I use the listMetadata method) and for each element i want to get the flow object (I use the readMetadata method).
    this is my code :
    MetadataService.Flow flow = (MetadataService.Flow) service.readMetadata(‘Flow’, new String[] { ‘fullNameOfTheFlow’ }).getRecords()[0];

    And this the error:
    Incompatible types since an instance of MetadataService.Metadata is never an instance of MetadataService.Flow

    Can you please tell me how to get the Flow object from the fullName ?

    • This is not yet supported on the wrapper, there are some challanges, I hope to release support within the next week or so. Can you open an issue on the GitHub repo in the meantime please.

  19. Pingback: Apex Metadata API and Spring’14 : Keys to the Kingdom! | Andy in the Cloud

  20. @Andrew very helpfull post, i have a question here .. i am trying to update a class by using metadata api.. but as soon i re zip the three components like: .cls, meta-xml and package.xml and convert it to base64 string and assign it to content the update_x methord gives me an error like: INVALID_TYPE: This type of object is not available for this organization faultcode=sf any idea why its giving me this ?? i appreciate for any help as i am banging my head with this for a week.

    • You have to use the deploy method, take a look at the deploy demo described on the readme file

  21. Hi Andrew.Must thank you for this wonderful post. I was playing around within the apex-mdapi and stucked with a problem . Not able to find the bug in the MetadataDeploy page when clicking on Deploy button , gives me null pointer . Also the Metadata brwoser page , not able to retieve the tree.

    Note that i’m new to this and want to learn. Please help. Thanks in advance.

    • That is odd, can you raise an Issue on the GitHub site and I’ll try and take a look asap for you!

      • Thanks Andrew, got a solution for MetadataDeploy page. But , can you please guide me as to how to retrieve the JSON in MetadataBrowser page . When i click on Retrieve button on that page , it says no nodes selected ..It displays me the empty list.

        I cannot say this is an issue but somewhere i’m making a mistake. Please help ASAP.

      • This is because you have not registered the Metadata API end point URL with your orgs Remote Site settings.

      • Hi Andrew ! I’m stuck on with an issue . Your help will be greatly appreciated . In the Metadatabrowser page , when i click on Retrieve button , it does not show me the list and prompts me a “Selected Nodes” message . I know that its the JSON , but it shows me the empty list .

        Any pointers on this ?

        Please help me. Stuck from last 3 days.

      • Have you added a Remote Site setting to your org for the Metadata API? If not, try running the Metadata Retrieve Demo and if it displays an error follow the instructions shown to add a Remote Site setting and then try again.

      • I’ve raised a GitHub issue to improve the error handling on the MetadataBrowser page so that it will display the approprite error message if the Remote Site has not been setup.

  22. @ Andrew

    After Changing the “Port Type” name attribute, I created a WSDL to APEX class(“MetadataServiceImported” class) out of that. However, when I tried to see the contents of the generated apex class the following message displayed. Same is happening with the “Metadataservice” class also. Any idea regarding this ?


    An internal server error has occurred
    An error has occurred while processing your request. The support team has been notified of the problem. If you believe you have additional information that may be of help in reproducing or correcting the error, please contact Salesforce Support. Please indicate the URL of the page you were requesting, any error id shown on this page as well as any other related information. We apologize for the inconvenience.

    Thank you again for your patience and assistance. And thanks for using!

    Error ID: 915341540-14795 (-1437854107)

    • Is there any reason why your creating your own? And not using the one in the repository I already created? Try that one and see if you get the same error.

  23. Hi Andrew Fawcett,
    I try to create a field using metadata api i got following error how to solve this error.

    System.CalloutException: IO Exception: Read timed out
    Error is in expression ‘{!createField}’ in component in page createfields

    Class.rajesh.MetadataService.MetadataPort.readMetadata: line 8513, column 1
    Class.rajesh.MetadataController11.UpdateFieldLevelSecurity: line 844, column 1
    Class.rajesh.MetadataController11.createField: line 298, column 1

    please help me……………………

    • This is Salesforce error and time out we cannot change as apex developers. Can you try sending less information at a time?

  24. Hi Andrew Fawcett,

    I displayed custom objects and related custom fields(Here object will come dynamically through URL)with delete command link and edit command link using schema methods and wrapper class .My requirement is When i click delete command link this command link related custom object and custom field how to delete from database?this is my last requirement related to project

    please help me…………

  25. Hi Sir,
    How to create User Using metadata api?

    • You don’t need the metadata API for this, you can use DML in apex or partner API in other languages to inset a record into the User object.

  26. Hi Andrew Fawcett,

    Using schema methods and wrapper class I displayed all custom objects with in the pageblocktable one column.another column name is created dates(column name).How to retrieve all custom objects related created dates(column name) with in the pageblock table column(means created Dates column)?

    Note:i posted lot of blogs no reply

    help me………

    • I try to respond to all your questions on GitHub, I gave you some sample code the other day for adding fields to layouts did you see it?

      Please raise this question on GitHub and I will try to help also. Please also keep in mind I provide support mostly in my personal time.

      Please raise this on GitHub I have some ideas I can share with you there.

  27. Hi Andrew Fawcett,
    How to create Multi select field using Metadata api?

  28. Hi Andrew Fawcett,
    Using metadata api I created Multipicklist from visualforce page.I want to How to display Dynamically comming multipicklist values as checkboxes.

  29. Hi Andrew Fawcett,
    Every time i will create Multselectipicklist Fields and other fields Using metadata api From visualforce page.I displayed all fields dynamically (without using fieldset)in an visualforce page, on that time i want how to display all multiselectpicklists as checkboxes Dynmically?

    Note:Not single multiselectpicklist field I want to Every time comming multiselectpicklist field as checkboxes

    I displayed all comming multipicklists as checkboxes but problem is Created multiselect picklists also visible and multiselectpicklist related vales as checkboxes also visible .

    My code i pasted on Github issue .

    please help me…………

    • Thanks for raising on the GitHub Metadata API repository, please continue to do this.


      – You don’t need to also post such specific questions here in future.

      – Please do not post requests for help and questions that very specific this on my blog in future.

      – Please use GitHub or StackExchange for such issues, it is much much easier to talk and share code. 🙂

      Thank you.

  30. Hi Andrew Fawcett,
    Using metadata api how to update created field datatype dynamically?

    • I don’t understand your question sorry. Have you taken a look at the examples in MetadataServiceExamples.cls in the GitHub repository?

  31. Hi Andrew Fawcett,
    Using visualforce page how to schedule a batch Dynamically.Like below link’

    please help me…….

  32. Pingback: Apex Metadata API Streamlined and Simplified for Summer’14 | Andy in the Cloud

  33. Hi Andrew Fawcett,

    Is there any way we can create Apex class using Metadata API?
    We have a requirement of converting code from a different language to apex. Our last hurdle is that we are not able to save the result as an Apex Class. We used the API to create Pages which has the create() call enabled but with Apex Class no luck.

    Please kindly suggest some method.

    Best Regards,

    • For ApexClass and ApexTrigger metadata types, the CRUD methods are not supported by Salesforce. You have to use the deploy operation, take a look at the Deploy Demo in the GitHub repository. Its not ideal. There is another API called the Tooling API that will also do this, without having to use a zip component on the client! Take a look at this repository and the demo class file within it for an example,

  34. Did anyone try creating FieldSets? I can add fields in FieldSet as availableFields but not as displayedFields ? Please see simple code below. Developer console throws an error for fieldSet.displayedFields.add(myAvailableField);

    Error Message: Metadata API Exception Attempt to de-reference a null object

    //FieldSet Field
    fieldSet.availableFields = new List();
    MetadataService.FieldSetItem myAvailableField = new MetadataService.FieldSetItem();

    //Field 1
    myAvailableField.field = ‘UnitPrice’;

    //Field 2
    myAvailableField = new MetadataService.FieldSetItem();
    myAvailableField.field = ‘Product2.LastModifiedDate’;

    • I cannot check this on detail at present, but wanted to check you had seen the examples in MetadataServiceExamples.cls? I think there is an example of this in that?

  35. why is there a compile error “Compile Error: Invalid type: MetadataService.AsyncResult ” while saving the following code

    public with sharing class MetadataController {

    public MetadataService.AsyncResult result {get;set;}
    in apex class.

    • I don’t see why, have you used the MetadataService class from the repo? Can you maybe post a more complex code sample via a GitHub Issue if so.

  36. how should i use the MetadataService class from the repo. can you guide step by step.
    My requirement is to fetch all the validation rules for a custom object using a apex class.

    • You can click the Deploy to Salesforce button to deploy the code to your org, or Clone the repo to your local machine, or download the MetadataService.cls and MetadataServiceTest.cls individually and copy paste into your developer org.

  37. Hi Andrew,

    I am working with metadata service class and try to get list views. I need to setup a remote site to get it working otherwise there is an error “unauthorized endpoint…… ” .

    Is there any way to set endpoint dynamically as I may need to package my solution and install in another org. This is “” in my org but could be different in other orgs.

    Is there any way to make it dynamic ?

    Thanks in advance!

  38. Thanks for this Andrew!

    Another issue I have anyone might help. I am retrieving list view filters , I can get list view filters for opportunity closing this month in one org (My Dev org) but when try the same code in another org (this org have namespace enabled for managed package . Does this makes any difference ?) it is returning null (no filters at all ), tried with different list views but can not succeed.

    Do you have any Idea about what might be the issue? I am stuck in this


  39. Here is my class code,

    public with sharing class GetListViews{

    private static MetadataService.MetadataPort createService()
    MetadataService.MetadataPort service = new MetadataService.MetadataPort();
    service.SessionHeader = new MetadataService.SessionHeader_element();
    service.SessionHeader.sessionId = UserInfo.getSessionId();
    return service;
    public void readListView()
    MetadataService.MetadataPort service = createService();

    MetadataService.ListView listView =
    (MetadataService.ListView) service.readMetadata(‘ListView’,
    new String[] { ‘Opportunity.ClosingThisMonth’ }).getRecords()[0];

    for(MetadataService.ListViewFilter filter : listView.filters)
    System.debug(‘Filter ‘ + filter.field + ‘ ‘ + filter.operation + ‘ ‘ + filter.value);


    I am stuck in this issue . Any kind of help is appreciated .

    Thanks in advance!

  40. Hi Andrew,

    Thanks for the great post. I am able to create fields but I am unable to update Field Level Security Permissions for these fields against any profile. When I execute the updateFieldLevelSecurity() method I get a CalloutException. When I checked the fullname on the MetadataService.Profile is not getting set.

    Am I missing something? Please Help.
    Thanks in Advance!!

  41. Hi Andrew ,

    Just confirmed that orgs with namespace (for managed packages) are not returning list view filters . Tested with one of my Dev org and this returns list view filters. Then added a namespace (setup -> create -> package -> edit -> add namespace) , after that list view filters are returning null.

    So, does this means that metadata api stops working with this kind of orgs? Or is there some other way to call metadata for such orgs ? or is there some kind of issue/ bug ?

    Please let me know. This is kind of urgent thing, if you can help with just telling me if this is possible or not.

    Thanks !

    • Got a solution my self . Pasting so could help someone in the same problem 🙂

      adding namespace prefix with two underscores solves my problem.

      List view name : Opportunity.NAMESPACE__ClosingThisMonth

      Example :

      public void readListView()
      MetadataService.MetadataPort service = createService();

      /* Instead of this ..
      MetadataService.ListView listView =
      (MetadataService.ListView) service.readMetadata(‘ListView’,
      new String[] { ‘Opportunity.ClosingThisMonth’ }).getRecords()[0];*/

      //I use this
      MetadataService.ListView listView =
      (MetadataService.ListView) service.readMetadata(‘ListView’,
      new String[] { ‘Opportunity.NAMESPACE__ClosingThisMonth’ }).getRecords()[0];

      for(MetadataService.ListViewFilter filter : listView.filters)
      System.debug(‘Filter ‘ + filter.field + ‘ ‘ + filter.operation + ‘ ‘ + filter.value);

      Best Regards!

      • Awesome, namespaces can make naming things in the metadata api very tricky, I often use the Developer Workbench to list them to get the correct names. Sorry i didn’t get to this sooner to suggest this. Though as they say, there is only one good way to learn! 🙂 Glad you sorted it and enjoy the API!

  42. Pingback: Apex Metadata API Q&A | Andy in the Cloud

  43. Andy,

    Do you have a example to ‘retrieve’ the package from one environment and deploy the same in some other environment using the metadata api?

  44. Hi Sir,
    Is it possible salesforce integration with xero?

    • Zero has Api’s and Apex can make web call outs, so I would say yes. Though I have no experience in this. Try using Google and Salesforce StackExchange perhaps.

  45. Hi Andrew

    I’m trying to create an ApexClass using the tooling api by forking the following project:

    When I have the ApexClass list, I’m casting it into sObject_x list and then adding it as a parameter in create() webservice call. It always gives me “INVALID_TYPE” exception. Please could you help?

    Thanks in advance.

    • To provide more info:

      Intially, I tried something like:

      List sObjects = new List();
      sObjects = testClassList;
      ToolingAPIWSDL.SaveResult[] saveResult = toolingAPI.create(sObjects);

      And, then I tried the following, but both of them gave the same exception – Invalid_Type.

      List sObjects = new List();

      for(ToolingAPIWSDL.ApexClass newTestClass : testClassList) {
      ToolingAPIWSDL.sObject_x newSObject = new ToolingAPIWSDL.sObject_x();
      String[] tempFieldstoNull = new String[]{};
      newSObject.fieldsToNull = tempFieldstoNull; //null
      newSObject.Id = null;
      newSObject.ApexClass = newTestClass;
      ToolingAPIWSDL.SaveResult[] saveResult = toolingAPI.create(sObjects);

  46. Pingback: Metadata API and SOAP using Google REST Console and Anonymous Apex | jdope

  47. Hi Andrew,

    Thank you very much for this useful post. I managed to create new custom labels with translations, but was unable to read them back using readMetadata method. Will it be possible to read and update an existing custom label and its translation using MetadataService?

    Many Thanks

    • Your very welcome thank you! This should be possible, can you raise a request for an example on the github issue list and I will take a look

      • Thank you very much for your prompt reply. I will raise an issue on github.
        Really appreciating your help.
        Many Thanks,

  48. Thank you very much for your prompt reply. I will raise an issue on github.
    Really appreciating your help.

    Many Thanks,

  49. Andy,
    This looks fantastic. It opens up a whole lot of functionality. Thank you. I’m glad it is a passion of yours.
    I have recently taken over a Salesforce installation that has had far too many (inexperienced) hands on it. There are different naming conventions for fields and many fields that are just left abandoned. What I’d really like to do is change the API name of some of the fields so that they actually relate to their use and function.
    I’d like to use your Metadata classes to create a method that changes the API name of a field. I imagine that it would need to create a field under the new name but same field type, copy all the data from the old into the new, replace all references to the old with the new and then remove the old field.
    I then thought ‘I can’t be the only one who has this bug bear’. Are you aware of anyone who has such a piece of code?

    Thanks, Greg.

    • Thanks Greg, really appreciate the words. As regards your use case, it is indeed a frustrating one, and costs time as developers have to map what they see on the screen to less obvious API names. So yes aware of the problem, though not of anyone as yet who has attempt to overcome it with this API.

      You can use the Metadata API to automate a lot of what can be done under the Setup menu for sure. However it will not bypass any of the integrity constraints Salesforce enforce. So if you cannot rename or delete a field in the UI, due to references, the Metadata API will also reflect the same. As regards developing a tool to help do this, i’d say its certainly got its challanges, but i’m not a none-starter. Some initial challange will be in finding the dependencies to unhook before the field can be renamed/deleted. There is no API for this, though maybe you can parse the error message returned when attempting to do so?

      Thanks for your support and good luck if you attempt this mission! 🙂

Leave a 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