How to get a field's description via API?

Unfortunately, description seems to be the one field that is not included in the getDescribe() method (See full list of available information here). One alternative that you may be able to use instead is to pull the inline help text which is set alongside of the description. I don't know your use-case though, so I'm not sure if that would help you much or not.

String fieldHelpText = Object_Name__c.Field_Name__c.getDescribe().getInlineHelpText();

The down side of using the Help Text is that any contents are visible in Standard View pages to all users which have access to the field.

Again, I don't know the full scenario for why you need this functionality, but you might also want to look into using Custom Settings. You could create a map of each field and its description (or whatever information you're trying to gather). The data can be filled in pretty quickly through the DataLoader or Excel connector.


This is indeed an odd omission from Apex Describe. If you can tolerate an making SOAP API call to the Salesforce Metadata API then this will return the label. Note this will be the label as defined and will not consider any translations via Translation Workbench.

    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[] { 'Test__c.MyField__c' }).getRecords()[0];     
    System.debug(customField.label);

You can download the MetadataService and MetadataServiceTest classes that help wrap this SOAP API from this repo. You will also need to have your users add a Remote Site entry (ironically to Salesforces own servers). There is a way to semi-automate this here.


Another way to get this data is via the Tooling API which can be called from Apex with REST calls. The query itself would look like this:

Select Label, QualifiedApiName, Description from FieldDefinition Where EntityDefinition.QualifiedApiName='Account'

Where EntityDefinition.QualifiedApiName is the API name of the object you're interested in. To try this from the developer console make sure you check 'Use Tooling API'. For a full example of this query being sent from Apex see Salesforce Field Auditor. The following code shows the general gist of how the query is sent and the data deserialized.


// QUERY 1 - Get the object's Id and Field's Label, API Name, Data Type, and Description on all fields of the selected object
req.setEndpoint(instanceName + '/services/data/v48.0/tooling/query/?q=Select+EntityDefinition.DurableId,Label,DeveloperName,DurableId,QualifiedApiName,DataType,Description+from+FieldDefinition+Where+EntityDefinition.QualifiedApiName=\'' + selectedObject + '\'');       
HttpResponse res1 = h.send(req);
String responseBody = res1.getBody(); 
       
String objectId = null;
        
// Deserialize the response
Map<String, Object> payload1 = (Map<String, Object>)JSON.deserializeUntyped(responseBody);
        
        for (Object data : (List<Object>)payload1.get('records'))
        {
            Map<String, Object> record = (Map<String, Object>)data;

            if(objectId == null){

                Object entityDefinition = (Object)record.get('EntityDefinition');
                Map<String, Object> eDefMap = (Map<String, Object>)entityDefinition;
                objectId = (String) eDefMap.get('DurableId');
            }
           
            FieldAuditData fData = new FieldAuditData();
            fData.fieldLabel = (String)record.get('Label');
            fData.developerName = (String)record.get('DeveloperName');
            fData.durableId = (String)record.get('DurableId');
            fData.apiName = (String)record.get('QualifiedApiName');
            if(blacklistedFields.contains(fData.apiName)){
                continue;   // system field - ignore
            }
            fData.dataType = (String)record.get('DataType');
            fData.description = (String)record.get('Description');
  
            if(fData.apiName.contains('__c')){
                customResults.add(fData);
                fData.isCustom = true;
            } else {
                standardResults.add(fData);
                fData.isCustom = false;
                if(fieldMap.containsKey(fData.developerName)){ 
                    Schema.DescribeFieldResult f = fieldMap.get(fData.developerName).getDescribe();
                    fData.helpText = f.getInlineHelpText();
                }               
            } 
            
            results.put(fData.durableId, fData);
        }

Tags:

Apex