I would like to know about how can I distinguish whether a Custom Object OWS is set to Private or Public read-only via Apex. As far as I know and find referenced here Get object sharing setting on Organization-Wide Defaults, if I look into Schema.getGlobalDescribe and try to instantiate the MyCustomObject__Share object I will be able to guess whether MyCustomObject is set to private/public read-only or public read/write.

Then my question comes when I wonder how may I guess whether the setting is either private or public read-only. I guess it is possible to do it but I haven't been able to find out the how-to. I would appreciate any help on your side.

Thank you so much. Martín.

  • Why do you need to do this? What use-case do you have for needing to query this rather than just knowing if the current user can access the object? Apr 10, 2015 at 8:17
  • Hi, thanks for answering. I have a WebService where I store copies of some Users with their respective RoleIds. Then I have some triggers in Salesforce and I would like to notify the MyCustomObject changes to all the users in my WS which are allowed to see that object.
    – Martin
    Apr 10, 2015 at 9:25
  • In addition, is it possible to query if some user or role can access some record?
    – Martin
    Apr 10, 2015 at 11:41

3 Answers 3


After much research time and some headaches... I've found a solution: You can obtain the Organization Wide Default Settings of a Custom Object by using the Metadata API (http://www.salesforce.com/us/developer/docs/api_meta/). It is a Soap Web Service which is provided by Salesforce and you can use it to get many of the configurations that you have set up for your organization.

The WSDL is provided in the API section of your setup panel in the Salesforce Portal. But it is not that trivial as compiling the WSDL... You will find some errors related to "anyType" types contained in the WSDL. This can be solved by replacing these "anyType" tokens by "string". Then, after a correct compilation of the WSDL to Apex, you will try to execute some requests which certainly won't work. You would receive some error like "callout response field not found in your ReadResult class: fullName". You can try to manually solve this issue.... but in my opinion it was a waste of time. There's much effort to exert just to make it work. It is better to know that someone has been working on this: https://github.com/financialforcedev/apex-mdapi/blob/master/apex-mdapi/src/classes/MetadataService.cls .

It is very easy, just copy the code of the MetadataService.cls and insert it in a new Apex class of your Force.com organization. Then, you can just perform in your Execute Anonymous something like:

MetadataService.MetadataPort metadataWS = new MetadataService.MetadataPort();
metadataWs.SessionHeader = new MetadataService.SessionHeader_element();
metadataWs.SessionHeader.sessionId = UserInfo.getSessionId();
MetadataService.ReadCustomObjectResult rs = (MetadataService.ReadCustomObjectResult) metadataWS.readMetadata('CustomObject', new String[] {'MyCustomObject__c', 'MyOtherCustomObject__c'});
for (MetadataService.Metadata md : rs.getRecords()) {
    if (md != null) {
        MetadataService.CustomObject obj = (MetadataService.CustomObject) md;
        System.debug('Custom object full name: ' + obj.fullName);
        System.debug('Label: ' + obj.label);
        System.debug('Sharing model: ' + obj.sharingmodel);
    } else {
        System.debug('Empty metadata.');

I hope this may help other people wondering about this same topic as it has been a complex topic for me.


You can actually now get this through the Tooling API! It is on the Entity Definition table.

So you can run a query like this:

List<EntityDefinition> sharingModel = [Select InternalSharingModel, ExternalSharingModel FROM EntityDefinition WHERE QualifiedApiName =: objectName];

Even if the Object has an OWD of Controlled by Parent, it will make the jumps for you and give you the end result.


  • This was helpful.. Exactly what I was searching for Aug 24, 2019 at 19:48

Partially answering my own question: One can watch the access level that every user has to every record by querying to UserRecordAccess (https://www.salesforce.com/developer/docs/api/Content/sforce_api_objects_userrecordaccess.htm). Something like:

SELECT RecordId, HasReadAccess, MaxAccessLevel FROM UserRecordAccess WHere UserId = '005D0000004LEbWIAW' AND RecordId = 'a0Kc000000FSWwhEAH'.

It is mandatory to set both conditions in the WHERE clause (UserId and RecordId), otherwise one would get an exception.

But still some doubts: What if I want to know either the permissions of a big set of users (for example, 1000 users) to one record or the permissions of one user to a big set of records (for example, 10 000 records)? Wouldn't it be better to query (if possible) the Organization Wide Settings of the objects which I'm interested in?

  • any update on this? Mar 9, 2018 at 14:48
  • I am slogging through this a bit too. I seem to be able to get the accessibility of the account e.g.AccountShare aShare = new AccountShare(AccountId=aid, UserOrGroupId=UserInfo.getUserId(),AccountAccessLevel='Edit',OpportunityAccessLevel='None');
    – dschueler
    Apr 24, 2018 at 22:46

You must log in to answer this question.

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