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
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.
| Feature | Web API (REST/OData) | Organisation Service (.NET SDK) |
|---|---|---|
| Protocol | HTTP (REST) | .NET classes (IOrganizationService) |
| Available from | Any language (JS, Python, C#, etc.) | C# / .NET only |
| Query syntax | OData ($select, $filter, $expand) | QueryExpression or FetchXML |
| Batch operations | $batch endpoint (OData batch) | ExecuteMultipleRequest |
| Used in | Client scripts, external apps, PCF, Azure Functions | Plug-ins, custom workflow activities, .NET apps |
| Authentication | OAuth 2.0 bearer token | SDK handles auth (or OAuth for external) |
| Typed objects | No ā JSON objects | Yes ā 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:
| Limit | Threshold | What Happens |
|---|---|---|
| API requests | 6,000 per 5-minute window per web server | HTTP 429 (Too Many Requests) |
| Concurrent requests | 52 per user | HTTP 429 |
| ExecuteMultiple | 1,000 requests per batch | Error if exceeded |
| Payload size | 128 MB per request | HTTP 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-Afterheader - Implement exponential backoff (1s, 2s, 4s, 8sā¦)
- Set a maximum retry count (e.g., 5 attempts)
- Log retries for monitoring
Bulk operations
| Method | API | Max Per Batch | Use Case |
|---|---|---|---|
| $batch | Web API | 1,000 operations | Batch HTTP requests in one call |
| ExecuteMultiple | Org Service | 1,000 requests | Batch SDK operations in one call |
| BulkDelete | Both | Millions of records | Background deletion of large datasets |
| Elastic tables | Web API | Massive volumes | IoT/telemetry data ingestion |
Exam tip: OAuth authentication pattern
External applications authenticate to Dataverse using OAuth 2.0:
- Register an app in Microsoft Entra ID
- Grant it Dataverse API permissions (
user_impersonationor app-level) - Get a token from
https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token - Include the token in requests:
Authorization: Bearer {token} - 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.
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?
š¬ Video coming soon
Next up: Azure Functions for Power Platform ā processing heavy workloads, triggers, and managed identity authentication.