Domain 5 β€” Module 6 of 9 67%
20 of 26 overall
Domain 5: Extend the Platform Free ⏱ ~14 min read

Dataverse APIs: Web API & Organisation Service

Master the two ways to talk to Dataverse programmatically. Learn OData queries, batch operations, retry policies, bulk processing, and OAuth authentication.

Two languages for Dataverse

Simple explanation

Think of Dataverse as a library with two service desks.

The Web API desk (REST/OData) speaks HTTP β€” any programming language can walk up and make requests. It is like the public service desk: open to everyone, uses standard protocols.

The Organisation Service desk (.NET SDK) speaks C# β€” it is the staff-only entrance, faster for .NET developers, with typed objects and IntelliSense.

Both desks access the same books (data). You choose based on your language: building a JavaScript app? Use the Web API. Writing a C# plug-in? Use the Organisation Service. Building an external Python integration? Web API.

Same data, different access patterns β€” choose based on your platform
FeatureWeb API (REST/OData)Organisation Service (.NET SDK)
ProtocolHTTP (REST).NET classes (IOrganizationService)
Available fromAny language (JS, Python, C#, etc.)C# / .NET only
Query syntaxOData ($select, $filter, $expand)QueryExpression or FetchXML
Batch operations$batch endpoint (OData batch)ExecuteMultipleRequest
Used inClient scripts, external apps, PCF, Azure FunctionsPlug-ins, custom workflow activities, .NET apps
AuthenticationOAuth 2.0 bearer tokenSDK handles auth (or OAuth for external)
Typed objectsNo β€” JSON objectsYes β€” Entity, EntityReference, ColumnSet

Web API operations

// Retrieve a record (GET)
GET /api/data/v9.2/accounts(00000000-0000-0000-0000-000000000001)
    ?$select=name,revenue
    &$expand=primarycontactid($select=fullname,emailaddress1)

// Create a record (POST)
POST /api/data/v9.2/accounts
Content-Type: application/json
{ "name": "LogiFlow", "revenue": 5000000 }

// Update a record (PATCH)
PATCH /api/data/v9.2/accounts(00000000-0000-0000-0000-000000000001)
Content-Type: application/json
{ "revenue": 6000000 }

// Delete a record (DELETE)
DELETE /api/data/v9.2/accounts(00000000-0000-0000-0000-000000000001)

// Query with filter (GET)
GET /api/data/v9.2/contacts?$filter=lastname eq 'Nakamura'&$select=fullname,emailaddress1

API limits and retry policies

Dataverse enforces rate limits to protect platform performance:

LimitThresholdWhat Happens
API requests6,000 per 5-minute window per web serverHTTP 429 (Too Many Requests)
Concurrent requests52 per userHTTP 429
ExecuteMultiple1,000 requests per batchError if exceeded
Payload size128 MB per requestHTTP 413

Handling 429 responses

// Retry-After header tells you how long to wait
HttpResponseMessage response = await client.SendAsync(request);

if (response.StatusCode == (HttpStatusCode)429)
{
    int retryAfterSeconds = int.Parse(
        response.Headers.GetValues("Retry-After").First());
    
    await Task.Delay(TimeSpan.FromSeconds(retryAfterSeconds));
    response = await client.SendAsync(request); // Retry
}

Best practices for retry:

  • Always respect the Retry-After header
  • Implement exponential backoff (1s, 2s, 4s, 8s…)
  • Set a maximum retry count (e.g., 5 attempts)
  • Log retries for monitoring

Bulk operations

MethodAPIMax Per BatchUse Case
$batchWeb API1,000 operationsBatch HTTP requests in one call
ExecuteMultipleOrg Service1,000 requestsBatch SDK operations in one call
BulkDeleteBothMillions of recordsBackground deletion of large datasets
Elastic tablesWeb APIMassive volumesIoT/telemetry data ingestion
Exam tip: OAuth authentication pattern

External applications authenticate to Dataverse using OAuth 2.0:

  1. Register an app in Microsoft Entra ID
  2. Grant it Dataverse API permissions (user_impersonation or app-level)
  3. Get a token from https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token
  4. Include the token in requests: Authorization: Bearer {token}
  5. Tokens expire β€” implement refresh logic

For service-to-service (no user), use client credentials flow (application permissions). For user-delegated access, use authorization code flow.

Question

What happens when you exceed Dataverse API rate limits?

Click or press Enter to reveal answer

Answer

You receive an HTTP 429 (Too Many Requests) response with a Retry-After header indicating how many seconds to wait. Your code should respect this header, wait the specified time, and retry. Implement exponential backoff with a maximum retry count.

Click to flip back

Question

What is the difference between $batch and ExecuteMultiple?

Click or press Enter to reveal answer

Answer

$batch is the Web API's batching mechanism (bundles multiple HTTP requests into one). ExecuteMultiple is the Organisation Service's equivalent (bundles multiple SDK requests). Both reduce round-trips and improve performance. Maximum 1,000 operations per batch for both.

Click to flip back

Question

Which OAuth flow should you use for a background service calling Dataverse?

Click or press Enter to reveal answer

Answer

Client credentials flow (application permissions). The service authenticates with its own identity (app ID + client secret or certificate) without any user interaction. Register the app in Entra ID, grant Dataverse application permissions, and create an application user in Dataverse with appropriate security roles.

Click to flip back

Knowledge Check

An external application needs to synchronise 5,000 contact records to Dataverse nightly. Currently it sends 5,000 individual POST requests and frequently hits HTTP 429 errors. What is the best fix?

Next up: Azure Functions for Power Platform β€” processing heavy workloads, triggers, and managed identity authentication.