Calling and extending the Business Central API v2.0
how to call Business Central API v2.0 with OAuth
Also searched as
- Business Central REST API v2.0 tutorial
- how to create custom API page in Business Central
- BC API v2.0 authentication setup
Short answer
The Business Central API v2.0 is a REST/OData endpoint at api.businesscentral.dynamics.com/v2.0/{tenant}/{environment}/api/v2.0, authenticated with Azure AD OAuth 2.0. It exposes standard entities like customers and items, and lets you publish your own with an AL API page.
Applies to: Dynamics 365 Business Central (SaaS and on-premises with API access enabled), API v2.0.
Authenticate and call the API
- 1In Azure AD (Entra ID), register an app, grant it the Dynamics 365 Business Central API permission (Automation.ReadWrite.All or a narrower delegated/application scope), and generate a client secret or certificate.
- 2In Business Central, open the Microsoft Entra Applications page and register the same client ID with the permission set needed (D365 BUS FULL ACCESS or a custom set scoped down for the integration).
- 3Acquire an OAuth token from https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token using client credentials (app-to-app) or the authorization code flow (user context), requesting scope https://api.businesscentral.dynamics.com/.default.
- 4Call GET https://api.businesscentral.dynamics.com/v2.0/{tenant}/{environment}/api/v2.0/companies to retrieve the company id GUID you need for company-scoped calls.
- 5Query a standard entity, e.g. GET .../companies({id})/customers, and use OData query options ($filter, $select, $expand, $top) to shape the response.
- 6For writes, POST/PATCH with the If-Match header (ETag from a prior GET) on updates to satisfy Business Central's optimistic concurrency control.
- 7To expose custom data, create an AL page of type API with ApplicationArea, APIPublisher, APIGroup, APIVersion, EntityName and EntitySetName properties, publish the extension, and it appears automatically under the custom API path.
v1.0 versus v2.0 and custom API versions
v2.0 is the current general-availability surface and is what Microsoft recommends for new integrations; v1.0 remains available mainly for backward compatibility. Both sit alongside any custom API pages you publish, which get their own version segment (e.g. v1.0, v2.0, or a custom string) under APIPublisher/APIGroup rather than Microsoft's.
Custom API pages are reached at a different URL segment than the standard Microsoft entities: .../api/{publisher}/{group}/{version}/companies({id})/{entitySetName}, which keeps custom extensions from colliding with Microsoft's own evolving standard API surface.
Concurrency, ETags, and PATCH failures
Business Central enforces optimistic concurrency: every record returned carries an @odata.etag value, and a PATCH or DELETE must send it back in an If-Match header. Omitting it, or sending a stale value after another process updated the record, returns a 412 Precondition Failed.
For high-volume integrations, re-GET the record immediately before a retry rather than caching ETags for long periods - Business Central records change frequently from posting routines, jobs, and user edits.
Choosing between standard entities, $expand, and $batch
Standard entities cover the common master data and transactional objects (customers, items, sales orders, journals) but not every table; anything not exposed needs a custom API page or the older SOAP/OData v4 web service pattern.
$expand lets you retrieve a header and its lines in one call (e.g. salesOrders with $expand=salesOrderLines) which is usually cheaper than separate round trips; for bulk operations across many records, use the $batch endpoint to combine multiple requests into a single HTTP call and reduce throttling exposure.
Common pitfalls
- !Requesting the wrong OAuth scope (a generic Graph scope instead of the Business Central resource) and getting 401 errors that look like a permissions problem but are actually a token audience mismatch.
- !Forgetting to also register the app inside Business Central's Microsoft Entra Applications page - Azure AD registration alone is not sufficient.
- !Sending PATCH/DELETE without an If-Match header and hitting unnecessary 412 errors, or worse, using If-Match: * which bypasses the concurrency check entirely.
- !Assuming a table exists as a standard API entity when it does not - check the API entity list or build a custom API page rather than guessing endpoint names.
- !Hardcoding a company id instead of resolving it per environment, which breaks the integration the moment it is deployed to a sandbox or a different tenant.
How an ERP-grounded AI assistant handles this
ERPray, connected read-only to a Business Central environment via the API, can answer questions like which sales orders are missing a shipment date or summarize open customer balances without a developer writing OData filters by hand, and can point to the exact standard entity or custom API page a given integration should target.
Frequently asked questions
Do I need a Business Central developer license to call the API?
No - calling the API only needs an appropriate Business Central user/permission license and an Azure AD app registration. A developer license is only needed to build and publish custom AL extensions such as custom API pages.
Why does my API call return an empty companies list?
The token's audience or tenant is wrong, or the app has not been granted access within Business Central's own Microsoft Entra Applications setup even though Azure AD shows the permission granted - both sides need to match.
What is the difference between application and delegated permissions here?
Application permissions let a background service call the API as itself (client credentials flow, no signed-in user); delegated permissions call on behalf of a signed-in Business Central user and respect that user's own record-level permissions.
Can I get webhooks instead of polling?
Yes - Business Central supports the standard OData webhook subscription mechanism (POST to a notificationUrl-bearing subscription resource), which is generally preferable to polling for near-real-time integrations.
Related
Fixing "You do not have the following permissions on TableData (table): (permission)" in Business Central AL
This runtime error means the current user's assigned permission sets do not grant the required Insert, Modify, Delete, Read, or Execute right on that specific table. It is most common right after installing or updating a custom AL extension, because Business Central checks object-level permissions even for tables an extension owns.
How-toCreating and selecting custom report layouts in Business Central
Business Central reports can render through a Word layout (simple, single-level documents like invoices) or an RDLC layout (complex, multi-level, grouped reports). Custom layouts are uploaded and assigned per report through the Report Layout Selection page, or shipped inside an AL extension with the rendering(...) property.
How-toHandling OData 429 Too Many Requests throttling in D365 Finance and Operations
D365 F&SCM protects shared AOS capacity by throttling OData and custom service calls, returning HTTP 429 with a Retry-After header once a client sends too many requests too quickly. The durable fix is to honor Retry-After with backoff and redesign high-volume or frequent-polling integrations to use batching, business events, or Data management instead of tight request loops.
Error fixFixing "Cannot create a record in (table). The record already exists" in D365 F&SCM data entity imports
This is the standard kernel duplicate-key exception, thrown when the Data Management Framework tries to insert a staging row into a target table whose unique or alternate key already matches an existing record. It almost always means the entity's insert-vs-update logic did not recognize the target row as an update, not that you have a true accidental duplicate in your source file.
Error fixFixing "There are currently no batch servers available for processing" in D365 F&SCM
This message means the batch framework cannot find any AOS instance flagged as a batch server and available for the batch group the job is assigned to. The fix is almost always in server configuration (System administration > Servers) or batch group assignment, not in the batch job itself.
Error fixFixing "The CIL object was not found" in Dynamics AX 2012
This error appears when the AOS tries to execute compiled CIL for a class or method that has not actually been regenerated since a code change was imported or edited, so the .NET runtime has nothing matching to run. The fix is a full compile followed by a full CIL generation and an AOS restart, not just a partial or incremental rebuild.
AI for ERPAI for Dynamics 365 Business Central, on-premises or SaaS, beyond Copilot
AI for Business Central beyond Copilot: grounded question answering over BC's data via OData and APIs, for on-premises and SaaS tenants alike.
Stuck on Microsoft Dynamics 365 Business Central?
Talk to engineers who work inside Microsoft Dynamics 365 Business Central every week, and who build private AI that answers these questions from your own ERP data.