Tooling API is used to fetch the metadata such as Apex classes, Apex triggers, custom objects, custom fields, etc. If we need to get the list of Custom Objects or Custom fields, there is no need to manually gather the details from the whole SF organization. Instead, we can get it with the help of Tooling API SOQL. Tooling API came as a part of Spring’ 13 release.
EX: SELECT Id, DeveloperName FROM CustomObject
Using the above query, we can get all the Custom Objects created in the org (Including Managed package objects). Here “CustomObject” is called as “Tooling API Object”. The ID represents the custom object ID, and DeveloperName represents the custom object Name.
EX: SELECT Id, DeveloperName FROM CustomField
The above Tooling API query retrieves all custom fields in the organization.
The below example will illustrate the detailed usage of Tooling API objects. We have created a Visualforce page (code snippet shown later in this article) to display custom fields and their IDs from an object.
Step 1: Execute the custom Visualforce page we built.
![](https://www.mstsolutions.com/wp-content/uploads/2020/12/image-1284.png)
Step 2:
Select the Object Types as “Standard Objects”
![Tooling Api](https://www.mstsolutions.com/wp-content/uploads/2020/12/image-1285.png)
Then all the Standard Objects in the organization will appear in List of Objects picklist.
![Tooling Api](https://www.mstsolutions.com/wp-content/uploads/2020/12/image-1286.png)
Step 3: Select a Standard Object like Account. Then, all the custom fields in Account object will show in a Page block table with the Id and API name of that custom fields.
![Tooling Api](https://www.mstsolutions.com/wp-content/uploads/2020/12/image-1288.png)
- In Controller, Schema Object is used to get all Standard objects, Custom Objects, Custom Settings, and Custom Metadata.
- Http callout along with Tooling API query is used to retrieve the custom fields from standard and custom objects.
Fetching Custom Object Fields:
To retrieve Custom Fields from Custom Object, then we should use Custom Object ID in WHERE condition. To fetch custom fields in Account, the endpoint URL is
BaseURL+’/services/data/v38.0/tooling/query/?q=Select+Id,DeveloperName+from+CustomField+
Where+TableEnumORId=\”+ a0B5B0000018IhT+ “‘;
Fetching Standard Object Fields:
To retrieve Custom Field from Standard object, then we should use Standard Object API name in WHERE condition. To fetch custom fields in Account, the endpoint URL is
BaseURL+’/services/data/v38.0/tooling/query/?q=Select+Id,DeveloperName+from+CustomField+ Where+TableEnumORId=\” + Account+ “‘;
We must add the Base URL of the organization to the Remote Site Settings as the Endpoint URL of Http Request. Using Wrapper class in controller, we display the Custom Field Id and Name of the Account object.
![Tooling Api](https://www.mstsolutions.com/wp-content/uploads/2020/12/image-1287.png)
Step 1:
- Create a Visualforce Page with picklist option to show the list of Custom Objects, Standard objects, Custom Settings and Custom Metadata.
- Create a page block table to show the list of custom field details on the selected Objects.
Visualforce Page: ToolingAPI.vfp
<apex:page controller="ToolingAPIObjectsController _AC"> <apex:form> <apex:pageBlock title="Tooling API"> <apex:pageMessages /> <apex:pageblockSection> <apex:pageBlockSectionItem> <apex:outputLabel value="Object Types"/> <apex:outputPanel> <apex:selectList value="{!toolingObjectName}" multiselect="false" size="1"> <apex:selectOption itemValue="" itemLabel="-- Select --"> </apex:selectOption> <apex:selectOption itemValue="StandardObjects" itemLabel="Standard Objects ({!standardObjectsList.size})"/> <apex:selectOption itemValue="CustomObjects" itemLabel="Custom Objects ({!customObjectsList.size})"/> <apex:selectOption itemValue="CustomSettings" itemLabel="Custom Settings ({!customSettingsList.size})"/> <apex:selectOption itemValue="CustomMetaData" itemLabel="Custom MetaData ({!customMetaDataList.size})"/> <apex:actionSupport event="onchange" action="{!reset}" reRender="Picklistvalue, CustomFieldList"/> </apex:selectList> </apex:outputPanel> </apex:pageBlockSectionItem> </apex:pageblockSection> <apex:pageBlockSection id="Picklistvalue"> <apex:pageBlockSectionItem> <apex:outputLabel value="List of Objects"/> <apex:outputPanel> <apex:selectList size="1" value="{!selectedValue}"> <apex:selectOption itemValue="" itemLabel="-- Select --"> </apex:selectOption> <apex:selectOptions value="{!listOfValues }"> </apex:selectOptions> <apex:actionSupport event="onchange" action="{!getListOfObjects}" status="processing" reRender="CustomFieldList,processing"/> </apex:selectList> </apex:outputPanel> </apex:pageBlockSectionItem> </apex:pageBlockSection> </apex:pageBlock> <apex:actionStatus id="processing"> <apex:facet name="start"> <apex:outputPanel> Processing... <img src="/img/loading.gif" /> </apex:outputPanel> </apex:facet> </apex:actionStatus> <apex:outputPanel id="CustomFieldList"> <apex:pageMessages /> <apex:pageblock title="Custom Field List" rendered="{!showBlock}"> <apex:outputLabel value="Total number of Custom Fields{!customFieldNameList.size} "/> <apex:pageBlockTable value="{!wrapper}" var="wrap"> <apex:column headerValue="Custom Field Id"> <apex:outputLink target="_blank" value="/{!wrap.customFieldId}"> {!wrap.customFieldId} </apex:outputLink> </apex:column> <apex:column headerValue="Custom Field API Name" value="{!wrap.customFieldName}" /> </apex:pageblockTable> </apex:pageblock> </apex:outputPanel> </apex:form> </apex:page>
Step 2: Create a Controller for ToolingAPI page
public with sharing Class ToolingAPIObjectsController_AC { public Boolean showBlock{get;set;} public List<MyWrapper> wrapper { get; set; } public String selectedValue {get; set; } public string toolingObjectName {get; set;} public List<SelectOption> listOfValues = new List<SelectOption>(); public String cusObjId{get;set;} public List<String> customObjectsList{get;set;} public List<String> customSettingsList{get;set;} public List<String> customMetaDataList{get;set;} public List<String> standardObjectsList{get;set;} public List<String> customFieldNameList {get;set;} public ToolingApiObjectsController _AC(){ customObjectsList = new List<String>(); standardObjectsList = new List<String>(); customSettingsList = new List<String>(); customMetaDataList = new List<String>(); for(Schema.SObjectType objTyp : Schema.getGlobalDescribe().Values()) { if(objTyp.getDescribe(). isCustom() && !objTyp.getDescribe(). getName().contains('__mdt')) { customObjectsList.add(objTyp. getDescribe().getLabel()); } if(objTyp.getDescribe(). isCustomSetting()){ customSettingsList.add(objTyp. getDescribe().getLabel()); } if(objTyp.getDescribe().getName(). contains('__mdt')){ customMetaDataList.add(objTyp. getDescribe().getLabel()); } if(!objTyp.getDescribe(). getName().contains('__')){ standardObjectsList.add (objTyp.getDescribe().getName()); } } } public List<SelectOption> getlistOfValues(){ listOfValues.clear(); if(toolingObjectName == 'CustomObjects'){ for (String customObj : customObjectsList) { listOfValues.add(new SelectOption (customObj, customObj)); } } else if(toolingObjectName == 'StandardObjects' ){ for (String standardObj : standardObjectsList) { listOfValues.add (new SelectOption(standardObj, standardObj)); } } else if(toolingObjectName == 'CustomSettings' ){ for (String cusset : customSettingsList) { listOfValues.add(new SelectOption(cusset, cusset)); } } else if(toolingObjectName == 'CustomMetaData' ){ for (String cusmetdata : customMetaDataList) { listOfValues.add(new SelectOption (cusmetdata, cusmetdata)); } } return listOfValues; } public void getListOfObjects(){ if(selectedValue != null){ String endpoint, baseURL = URL.getSalesforceBaseUrl(). toExternalForm(); showBlock = True; if(selectedValue.contains(' ')){ selectedValue = selectedValue.Replace (' ', '_'); } if(toolingObjectName == 'CustomObjects' && selectedValue != NULL){ endpoint = baseURL+'/services/data/v38.0/ tooling/query/?q=SELECT+Id+FROM+ CustomObject+WHERE+DeveloperName= \'' + selectedValue+ '\''; getListOfCustomField(endpoint); if(cusObjId != NULL){ endpoint = baseURL+'/services/data/ v38.0/tooling/query/?q=SELECT+Id, DeveloperName+FROM+CustomField+ WHERE+TableEnumORId=\'' + cusObjId+ '\''; getListOfCustomField(endpoint); } } else{ endpoint = baseURL+'/services/data/v38.0/ tooling/query/?q=SELECT+Id, DeveloperName+FROM+CustomField+WHERE+ TableEnumORId=\'' + selectedValue+ '\''; getListOfCustomField(endpoint); } } } public class MyWrapper{ public String customFieldName{get; set;} public String customFieldId{get; set;} public MyWrapper(String name,String id) { customFieldId = id; customFieldName = name; } } public void reset(){ showBlock = False; selectedValue = ''; if(listOfValues != null){ listOfValues.clear(); } } public void getListOfCustomField (String endpoint){ List<String> customFieldIdList; String response; HttpRequest req = new HttpRequest(); req.setHeader('Authorization', 'Bearer ' + UserInfo.getSessionID()); req.setHeader('Content-Type', 'application/json'); req.setEndpoint(endpoint); req.setMethod('GET'); Http h = new Http(); HttpResponse res = h.send(req); response = res.getBody(); system.debug(response); if(response.contains ('"entityTypeName":"CustomObject"')){ JSONParser parser = JSON.createParser (response); customFieldNameList = new List<String>(); customFieldIdList = new List<String>(); while (parser.nextToken() != null) { if((parser.getCurrentToken() == JSONToken.FIELD_NAME) && ((parser.getText() == 'Id')) ) { parser.nextToken(); cusObjId = (parser.getText()); } } } else{ JSONParser parser = JSON.createParser (response); customFieldNameList = new List<String>(); customFieldIdList = new List<String>(); while (parser.nextToken() != null) { if((parser.getCurrentToken() == JSONToken.FIELD_NAME) && ((parser.getText() == 'DeveloperName')) ) { parser.nextToken(); customFieldNameList . add(parser.getText()); } if ((parser.getCurrentToken() == JSONToken.FIELD_NAME) && (parser.getText() == 'Id')) { parser.nextToken(); customFieldIdList .add(parser.getText()); } } wrapper = new List<MyWrapper>(); for(Integer i=0 ; i<customFieldNameList.size() ;i++) wrapper.add(new MyWrapper (customFieldNameList[i] , customFieldIdList [i])) ; if(customFieldNameList.size() == 0){ ApexPages.Message myMessage = new ApexPages. Message(ApexPages.Severity.Info, 'Info: There is no Custom Field for this Object.'); ApexPages.addMessage(myMessage) ; showBlock = False; } } } }
How to Use Tooling API Query in Developer Console?
We can use Tooling API query even in Developer Console by selecting the ‘Use Tooling API’ checkbox in Query Editor.
![Tooling Api](https://www.mstsolutions.com/wp-content/uploads/2020/12/image-1289.png)
Reference Link:
Querying custom object and field ids via ToolingAPI
ToolingAPI in salesforce