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