If I query fields by using:

task_fields = pd.DataFrame(sf.query(
    "SELECT QualifiedApiName, Label FROM FieldDefinition WHERE EntityDefinition.Label IN ('Task')")[

Then I get for example the Recurrence Activity Field. Which is not visible in object manager. How can I filter on fields that are visible in the object manager?

  • Please note Task and Event are both types of Activity, and they share some fields, potentially complicating this question.
    – Adrian Larson
    Apr 8, 2022 at 16:23

1 Answer 1


EntityParticle would be the best source for this for objects you'll typically interact with:

Represents each element of a field that can be presented in a user interface. Contrast EntityParticle with FieldDefinition, which represents each element of a field defined in the Metadata API.

And reference IsLayoutable

If true, the field can be assigned to a layout.

As such, you can do the following:

SELECT QualifiedApiName, 
(SELECT IsLayoutable FROM Particles) 
FROM FieldDefinition 
WHERE EntityDefinition.Label = 'Task' ORDER BY QualifiedApiName ASC

Where IsLayoutable = true should highlight the fields that are displayed in the UI (Setup).


  • That will return available fields for both Activity & Task that are presented separately in the Object Manager

  • I said "should" - as there's a small amount of exceptions across several objects. For Task, this is

    • Email
    • Phone
  • I also said "objects you typically interact with" as there are some objects that display in Object Manager that are not layoutable so all fields would be false even though fields display. I found a couple examples in my dev org

Since you're using simple-salesforce and doing a sub-query - I'd suggest flattening the data before passing it to pandas.

data = sf.query("SELECT QualifiedApiName, (SELECT IsLayoutable FROM Particles) FROM FieldDefinition WHERE EntityDefinition.Label = 'Task' ORDER BY QualifiedApiName ASC")

records = [];
for rec in data['records']:
    if(rec['Particles'] is not None):
        records.append(dict(QualifiedApiName=rec['QualifiedApiName'], isLayoutable=rec['Particles']['records'][0]['IsLayoutable']))
        records.append(dict(QualifiedApiName=rec['QualifiedApiName'], isLayoutable=False))


That should print

QualifiedApiName IsLayoutable
0 AccountId False
1 ActivityDate True
2 CallDisposition True
3 ... ...
  • Thanks for the elaborate reply. I see that there's no evident way to just get the fields shown in the object manager. However for me this is "close enough". As it is not exactly the same I think showing the boolean value of "IsLayoutable" next to all fields available for the tooling API is the best. However if I use your exact query string and export it to csv then I don't get just the "IsLayoutable" boolean but an orderedDict with all properties of particles. I will accept it as an answer if you could show how to only get the boolean value of "IsLayoutable"
    – ThaNoob
    Apr 10, 2022 at 20:28
  • How exactly are you executing that query that you get that result? I presume, based on the example you shared in the question it's simple salesforce (python)? Apr 11, 2022 at 1:31
  • Hi Kris, it is simple_salesforce. I don't know how to share the code decently in a comment but this is what I use: pd.DataFrame(sf.query("SELECT QualifiedApiName, Label, DataType, Description, IsNillable, (SELECT IsLayoutable FROM Particles) FROM FieldDefinition WHERE EntityDefinition.Label = 'Task' ")['records']).
    – ThaNoob
    Apr 11, 2022 at 6:12
  • 1
    You'll just want to pull the sub-query records out before assigning it to the dataframe (see relevant question). Updated answer to show how I did it. Apr 11, 2022 at 13:32
  • Thanks for the very well structured answer.
    – ThaNoob
    Apr 11, 2022 at 16:38

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .