I am looking for something like, API sObject name for the Custom metadata types, the way we have for ApexClass and ApexPage. I am trying to generate a list of Custom metadata type labels, CreatedBy, LastModifiedBy for our audit purpose.

Tried something like this:

Select Name, LastModifiedBy.Name, CreatedBy.Name From Metadata.CustomMetadata

but ended up with an error:

ERROR at Row:1:Column:16 First SObject of the FROM statement must be a valid SObject type.


From @Roti's suggestion, I have tried using EntityDefinition object after retriving the Metadata developernames, but my new entList is getting as empty.

Set<String> metadataTypes = new Set<String>();
for(String sObjectType : Schema.getGlobalDescribe().keySet()){

//for(String cmtd: metadataTypes){
    //System.debug('cmtd: ' +cmtd);

List<EntityDefinition> entList = [SELECT DeveloperName, Label, LastModifiedBy.Name, LastModifiedDate 
                                  FROM EntityDefinition WHERE DeveloperName IN :metadataTypes];
System.debug('entList: ' +entList);
for(EntityDefinition ent: entList){
    System.debug('DeveloperName: ' +ent.DeveloperName);
    System.debug('Label: ' +ent.Label);
  • 1
    +1, its a good question but someone who did not understand question might have downvoted. agreed that It is important to mention why its downvoted by user. – salesforce-sas Sep 26 '19 at 16:54

I was just about to post an answer, but Adrian Larson kind of mentioned it a bit in his answer.

Custom Metadata are a subset of Custom Objects, so they will be accessed through there. However, going through the global describe will just give you the SObjectType, not all the audit information you're looking for. I would take the SObjectTypes that you get from the describe, and then put their developer names in a Set and query the CustomObject information from there. Do note though that you can only query the CustomObject table through the Tooling Api, so you would have to either callout to that, or use another table like EntityDefinition. However, EntityDefinition does not have the CreatedBy information, just LastModifiedBy and LastModifiedDate.

Here is an example query

[SELECT DeveloperName, Label, LastModifiedBy.Name, LastModifiedDate FROM EntityDefinition WHERE DeveloperName IN :customMetadataNames]

'customMetadataNames' is the Set that you have collected the CustomMeatadata developer names in from going through the SObjectTypes.

Edit: I forgot to add the Label initially, but it is now in the query as well.

Edit #2: I used DeveloperName instead of QualifiedApiName (DeveloperName doesn't include the namespace prefix or the mdt suffix). The correct query should be:

[SELECT QualifiedApiName, Label, LastModifiedBy.Name, LastModifiedDate FROM EntityDefinition WHERE QualifiedApiName IN :customMetadataNames]

Following from the code posted in the updated question, here is how I would revise it to get the correct name from EntityDefinition:

Set<String> metadataTypes = new Set<String>();
for(String sObjectName: Schema.getGlobalDescribe().keySet()){

List<EntityDefinition> entList = [SELECT QualifiedApiName, Label, LastModifiedBy.Name, LastModifiedDate 
                                  FROM EntityDefinition WHERE QualifiedApiName IN :metadataTypes];
System.debug('entList: ' +entList);
for(EntityDefinition ent: entList){
    System.debug('QualifiedApiName: ' + ent.QualifiedApiName);
    System.debug('Label: ' + ent.Label);

Documentation for references: EntityDefinition

| improve this answer | |
  • This is interesting. Now I need to learn how to make Tooling Api work with my Anonymous window, for my testing purposes. – Austin Evans Sep 26 '19 at 17:04
  • EntityDefinition doesn't need Tooling Api. But if you need the CreatedDate, then yea, you will need Tooling Api for CustomObject. I don't believe you can actually use the Tooling Api within the execute anonymous window, but I'm not sure. But if it's just for testing purposes, you can just use the query editor and select "Use Tooling Api". – Roti Sep 26 '19 at 17:24
  • Getting my EntityDefinition list as empty. Please refer my question with my changes. – Austin Evans Sep 26 '19 at 18:13
  • The issue was that I said DeveleoperName earlier, but you should actually be using QualifiedApiName from EntityDefinition. My mistake. – Roti Sep 26 '19 at 19:28
  • No need to be sorry. I learned something new today. Thanks to you. – Austin Evans Sep 26 '19 at 19:31

If you want to get all of your custom metadata types, you can loop through the global describe and inspect the API Names to see if they end in the metadata suffix.

List<String> metadataTypes = new List<String>();
for (String sObjectType : Schema.getGlobalDescribe().keySet())
    if (sObjectType.endsWith('__mdt')
| improve this answer | |
  • I get it. But, how can I query labels and other audit fields once I get the list of records? – Austin Evans Sep 26 '19 at 16:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.