Discover user organizations

Your client application may connect to multiple Dataverse environments. Use the Global Discovery Service to find which environments the user of your application can access.

In Power Apps you can select from a list of environments available to you. The Global Discovery Service is the source of that data. Within your own app, you can provide a select control to allow users to choose which environment they want to use. Their choice will determine which environment your app must connect to.

With Dataverse, server and organization allocation may change as part of datacenter management and load balancing. Therefore, the Global Discovery Service provides a way to discover which server is serving an instance at a given time.

More information:

Global Discovery Service

The Global Discovery service, sometimes called GDS, is a set of OData v4.0 endpoints that are available for 5 different clouds.

Note

While both the Dataverse Web API and the Global Discovery Service are OData v4.0 endpoints, they are separate endpoints with different behaviors.

The following table provides the GDS location for each cloud.

Cloud URL and Description
Commercial https://globaldisco.crm.dynamics.com
Used by private sector companies. This is the most commonly used cloud.
GCC https://globaldisco.crm9.dynamics.com
Government Community Cloud. Used by public sector employees and contractors in the United States.
USG https://globaldisco.crm.microsoftdynamics.us
Used by United States Federal government employees and contractors. Also known as GCC High.
DOD https://globaldisco.crm.appsplatform.us
Used by Unites States Department of Defense employees and contractors.
China https://globaldisco.crm.dynamics.cn
Used by companies in China to comply with regulatory requirements.

More information:

Limitations

The Global Discovery Service does not return information where:

  • The user's account is disabled.
  • Users have been filtered out based on an instance security group.
  • The user has access as a result of being a delegated administrator.

If the calling user has access to no instances, the response simply returns an empty list.

Authentication

The calling user must acquire an OAuth 2.0 token from Microsoft Entra ID, and then add that token in the Authorization header of the API calls. More information: Use OAuth authentication with Microsoft Dataverse.

CORS support

The Discovery Service supports the CORS standard for cross-origin access. For more information about CORS support see Use OAuth with Cross-Origin Resource Sharing to connect a Single-Page Application.

Use Insomnia to connect to the Global Discovery Service

You can use the same approach described for the Dataverse Web API here: Use Insomnia with Dataverse Web API, but instead of the environment variables described in that topic, use the following to access the commercial cloud.

{
   "cloudUrl": "https://globaldisco.crm.dynamics.com",
   "globalDiscoUrl": "{{cloudUrl}}/api/discovery/v2.0/",
   "redirecturl": "https://localhost",
   "authurl": "https://login.microsoftonline.com/common/oauth2/authorize?resource={{cloudUrl}}",
   "clientid": "51f81489-12ee-4a9e-aaae-a2591f45987d"
}

Then, in the Authorization tab, choose OAuth 2 and set or verify the following values:

Field Value
GRANT TYPE Implicit
AUTHORIZATION url _.authurl
CLIENTID _.clientid
REDIRECT URL _.redirecturl

Use GET _.globalDiscoUrl as the Request URL and select Send.

You should now be able to query the Global Discovery Service using Insomnia.

Service Documents

To access the Global Discovery service for each cloud, append /api/discovery/v2.0/ to the URL. Perform a GET request on this url to view the service document, which contains only a single EntitySet: Instances.

Append $metadata to the cloud URL and send a GET request to view the CSDL (Common Schema Definition Language) service document. This XML document provides details on the Instance entity and the alternate keys defined for it.

Instance EntitySet

The following table describes the properties of the Instance Entity from the $metadata CDSL Service document.

Property Type Description
ApiUrl String The location of web services client applications should use.
DatacenterId String The Id of the data center where the instance is located.
DatacenterName String The name of the data center where the instance is located. This value is typically null.
EnvironmentId String The EnvironmentId for the instance.
FriendlyName String A name for the instance that is displayed in powerapps.com and other client applications that allow selecting instances.
Id Guid The OrganizationId for the environment.
IsUserSysAdmin Boolean Whether the calling user has the system administrator role for the environment.
LastUpdated DateTimeOffset When the environment was last updated.
OrganizationType Int32 The type of the organization. Values correspond to the OrganizationType EnumType
Purpose String Information for the purpose provided when the environment was created.
Region String A 2-3 letter code for region where the environment is located.
SchemaType String For internal use only.
State Int32 Whether the organization is 0:enabled or 1:disabled.
StatusMessage Int32 One of the following values:
0:InstanceLocked
1:PendingServiceInstanceMove
2:InstanceFailed
3:Provisioning
4:InActiveOrganizationStatus
5:NewInstance
6:InstancePickerReady
TenantId Guid The Id of the tenant associated to the instance
TrialExpirationDate DateTimeOffset The date when the trial period for the instance expires.
UniqueName String The Unique Name for the instance.
UrlName String The name used for the URL.
Version String The current version of the environment.
Url String The application url for the environment.

You can use these property names with the OData $select query parameter to retrieve just the data you need. In most cases, all you will need are the FriendlyName and ApiUrl properties. For example:

Request:

GET https://globaldisco.crm.dynamics.com/api/discovery/v2.0/Instances?$select=ApiUrl,FriendlyName HTTP/1.1
Authorization: Bearer <truncated for brevity>

Response:

HTTP/1.1 200 OK
Content-Length: 625
Content-Type: application/json; odata.metadata=minimal
odata-version: 4.0

{
  "@odata.context":"https://10.0.1.76:20193/api/discovery/v2.0/$metadata#Instances(ApiUrl,FriendlyName)",
  "value":[
    {
      "ApiUrl":"https://yourorganization.api.crm.dynamics.com",
      "FriendlyName":"Your Organization"
    }
  ]
}

Use the FriendlyName property for your application UI so the user will recognize the name of the environment. Use the ApiUrl to connect to Dataverse.

The rest of the properties are primarily for filtering.

Filtering

There are two ways you can filter the instances returned:

  • Using key values
  • Use OData $filter query options

Use one of the key values

You can use the Id or UniqueName value to filter the list to return a only the specified instance.

Note

Unlike the Dataverse Web API, the Global Discovery Service doesn't provide for retrieving a specific Instance using the Id or any of the alternate keys defined for it. GDS always returns an array of values.

Both of these queries will an array with a single item:

GET https://globaldisco.crm.dynamics.com/Instances(6bcbf6bf-1f2a-4ab9-9901-2605b314d72d)?$select=ApiUrl,FriendlyName,Id,UniqueName
GET https://globaldisco.crm.dynamics.com/Instances(UniqueName='unq6bcbf6bf1f2a4ab999012605b314d')?$select=ApiUrl,FriendlyName,Id,UniqueName

You can also use any of the following alternate key values: Region, State, Version to filter on specific values. For example, use the query below to return only those instances where the Region is NA representing North America.

GET https://globaldisco.crm.dynamics.com/Instances(Region='NA')?$select=FriendlyName,Region,State,Version,ApiUrl

Use OData $filter query options

You can use OData $filter query options as well with any of the properties that apply, including the alternate key properties.

You can use the following comparison, logical and grouping operators:

Operator Description Example
Comparison Operators
eq Equal $filter=IsUserSysAdmin eq true
ne Not Equal $filter=IsUserSysAdmin ne true
gt Greater than $filter=TrialExpirationDate gt 2022-07-14T00:00:00Z
ge Greater than or equal $filter=TrialExpirationDate ge 2022-07-14T00:00:00Z
lt Less than $filter=TrialExpirationDate lt 2022-07-14T00:00:00Z
le Less than or equal $filter=TrialExpirationDate le 2022-07-14T00:00:00Z
Logical Operators
and Logical and $filter=TrialExpirationDate gt 2022-07-14T00:00:00Z and IsUserSysAdmin eq true
or Logical or $filter=TrialExpirationDate gt 2022-07-14T00:00:00Z or IsUserSysAdmin eq true
not Logical negation $filter=not contains(Purpose,'test')
Grouping Operators
( ) Precedence grouping (contains(Purpose,'sample') or contains(Purpose,'test')) and TrialExpirationDate gt 2022-07-14T00:00:00Z

You can use the following string query functions:

Function Example
contains $filter=contains(Purpose,'test')
endswith $filter=endswith(FriendlyName,'Inc.')
startswith $filter=startswith(FriendlyName,'A')

Note

Unlike the Dataverse Web API, Global Discovery Service search strings are case sensitive.

Use Dataverse ServiceClient

For .NET applications you can use Dataverse.Client.ServiceClient.DiscoverOnlineOrganizationsAsync Method to call the Global Discovery Services.

 // Set up user credentials
var creds = new System.ServiceModel.Description.ClientCredentials();
creds.UserName.UserName = userName;
creds.UserName.Password = password;

//Call DiscoverOnlineOrganizationsAsync
DiscoverOrganizationsResult organizationsResult = await ServiceClient.DiscoverOnlineOrganizationsAsync(
        discoveryServiceUri: new Uri($"{cloudRegionUrl}/api/discovery/v2.0/Instances"),
        clientCredentials: creds,
        clientId: clientId,
        redirectUri: new Uri(redirectUrl),
        isOnPrem: false,
        authority: "https://login.microsoftonline.com/organizations/",
        promptBehavior: PromptBehavior.Auto);

return organizationsResult;

While the DiscoverOnlineOrganizationsAsync method uses the same OData endpoint and enables that it be passed in the discoveryServiceUri parameter, it does not return data in the shape of an Instance. Data is returned as an DiscoverOrganizationsResult Class that includes a OrganizationDetailCollection Property which contains a collection of OrganizationDetail Class instances. This class contains the same information as the Instance types returned by the OData service.

Note

While the DiscoverOnlineOrganizationsAsync.discoveryServiceUri parameter accepts a URL to the Global Discovery Service, any $select or $filter query options used will be ignored. The DiscoverOnlineOrganizationsAsync.discoveryServiceUri parameter is optional and if not provided will default to the Commercial cloud.

Use CrmServiceClient

For .NET Framework applications you can continue to use the CrmServiceClient.DiscoverGlobalOrganizations Method to call the Global Discovery Service.

  // Set up user credentials
  var creds = new System.ServiceModel.Description.ClientCredentials();
  creds.UserName.UserName = userName;
  creds.UserName.Password = password;

  // Call to get organizations from global discovery
  var organizations = CrmServiceClient.DiscoverGlobalOrganizations(
        discoveryServiceUri:new Uri($"{cloudRegionUrl}/api/discovery/v2.0/Instances"), 
        clientCredentials: creds, 
        user: null, 
        clientId: clientId,
        redirectUri: new Uri(redirectUrl), 
        tokenCachePath: "",
        isOnPrem: false,
        authority: string.Empty, 
        promptBehavior: PromptBehavior.Auto);

  return organizations.ToList();

Like the ServiceClient.DiscoverOnlineOrganizationsAsync method, the CrmServiceClient.DiscoverGlobalOrganizations method also does not return data as an Instance. It returns a OrganizationDetailCollection which contains a collection of OrganizationDetail Class instances that contains the same information as the Instance types returned by the OData service.

See Also

Sample: Global Discovery Service Sample (C#)
Sample: Access the Discovery service using CrmServiceClient
Sample: Blazor WebAssembly with Global Discovery