The Dynamics 365 Business Central API, Explained
A practical, platform-neutral guide to the Dynamics 365 Business Central API - the v2.0 REST stack built on OData v4, how OAuth2 (delegated and service-to-service) authentication works, how to use sandbox environments for safe development, the request and throughput limits you must design around, webhook change notifications, and the integration patterns that actually work for SMEs. Written by a partner that implements both Dynamics 365 and Odoo for SMEs across Canada, the UK, and the US.
What Is the Dynamics 365 Business Central API?
The Dynamics 365 Business Central API is the modern REST API stack Microsoft exposes for integrating BC with external systems and other Microsoft services. The recommended surface is version 2.0, built on OData v4, JSON payloads, and standard HTTP verbs (GET, POST, PATCH, DELETE). Microsoft documents it as the preferred way to integrate Business Central online with anything outside the product itself - a custom web storefront, a third-party logistics provider, a data warehouse, a Power Automate flow, or a partner-built automation.
The API exposes business entities as resources - companies, customers, items, sales orders and quotes and invoices, purchase documents, general-ledger entries, journals, vendors, and dimensions - and supports OData query options like $filter, $select, $expand, and $batch. The v2.0 endpoint pattern is https://api.businesscentral.dynamics.com/v2.0/{environmentName}/api/v2.0, with individual resources under /companies({id})/{entity}. For most SME integration work, this is the only surface you need.
If you are comparing BC to a platform like Odoo, the parallel is Odoo's XML-RPC and JSON-RPC external APIs plus its OCA REST layers - both vendors expose a programmatic surface over the same business data the UI edits. The strategic question for an SME is never 'does the ERP have an API?' (both do) but 'how mature, documented, and throttled is that API, and who maintains the integration when the vendor ships a major release?'
Business Central API Endpoints and Resources
Business Central online offers two endpoint variants. The common endpoint is https://api.businesscentral.dynamics.com/v2.0/{environmentName}/api/v2.0. The direct tenant endpoint adds the user domain: https://api.businesscentral.dynamics.com/v2.0/{userDomain}/{environmentName}/api/v2.0. Environment names can be discovered through the environments endpoint (documented under the Business Central web services lifecycle API), which is the safest way to resolve a target environment programmatically rather than hard-coding a name.
Once you have a company, the resource pattern is consistent: GET /companies returns the list, then /companies({id})/{entity} addresses a resource within that company - for example /companies({id})/customers, /companies({id})/salesOrders, or /companies({id})/generalLedgerEntries. Standard OData options shape the response: $filter for predicates, $select to trim payloads, $expand to pull related entities in one round trip, and $batch to submit up to 100 operations in a single POST.
Two practical limits shape how you write client code: the maximum page size is 20,000 entities, and the maximum batch size is 100 operations. The request body cannot exceed 350 MB, a single request times out at 10 minutes of execution (HTTP 504), and a single environment can hold up to 300 companies. Designing around these up front is far cheaper than discovering them at go-live.
- Common endpoint: https://api.businesscentral.dynamics.com/v2.0/{environmentName}/api/v2.0
- Direct tenant endpoint: https://api.businesscentral.dynamics.com/v2.0/{userDomain}/{environmentName}/api/v2.0
- Discover environments via the Business Central environments lifecycle endpoint
- Resource pattern: /companies({id})/{entity} with $filter, $select, $expand, $batch
- Operational limits: 20,000-entity pages, 100-operation batches, 350 MB body, 10-minute timeout (HTTP 504)
OAuth2 Authentication: Delegated vs Service-to-Service
Authentication for the Business Central API is Microsoft Entra ID (formerly Azure AD) and OAuth 2.0. Basic authentication and web service access keys are deprecated for Business Central online and must not be used for new integrations. Every modern BC API integration acquires an OAuth2 access token from Microsoft Entra ID and presents it as a bearer token on each request.
Microsoft supports two OAuth2 flows. Delegated flow impersonates a signed-in user - it relies on that user's context and licenses, so it fits interactive scenarios where a human is present. Service-to-Service (S2S) flow, also called client credentials, is the headless automation path: an application registration in Entra ID is granted API.ReadWrite.All and/or Automation.ReadWrite.All application permissions on Business Central, then registered inside BC on the Microsoft Entra Applications page. S2S is what you want for any scheduled job, middleware connector, or partner automation that runs without a user.
The S2S token request is a standard client-credentials POST to https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token with grant_type=client_credentials, the client_id and client_secret of the app registration, and scope=https://api.businesscentral.dynamics.com/.default. The returned access token is short-lived and should be cached and refreshed before expiry - the most common integration bug we see is a partner that fetches a fresh token on every call and silently doubles its request volume.
| Dimension | Delegated flow | Service-to-Service (S2S) |
|---|---|---|
| User context | Impersonates a signed-in user | No user - headless app |
| Licenses | Consumes the user's BC license | Governed by S2S permissions in BC |
| Permissions | Delegated scopes consented by the user | Application permissions (API.ReadWrite.All / Automation.ReadWrite.All) |
| Setup | App registration + user consent | App registration + register in BC Microsoft Entra Applications page |
| Best fit | Interactive client apps, Power Automate user flows | Scheduled jobs, middleware, partner automation, webhooks |
Sandbox Environments for API Development
A Business Central sandbox environment is purpose-built for development, testing, training, and experimentation. Extensions can be deployed directly from Visual Studio Code, debuggers attached, and production data optionally copied in so you can exercise realistic volumes without touching live transactions. Sandboxes run on a different performance tier than production, so they are explicitly not suitable for reliable benchmarking - design your load tests against that limitation.
For licensing, the base Business Central subscription (Essential or Premium) includes one production environment plus three sandbox environments, with additional environments purchasable as part of additional production environment bundles. Crucially for API work, sandbox environments use the same REST API endpoints as production - you simply substitute the sandbox environment name in the endpoint URL. This means the same client code, the same OAuth2 app registration, and the same OData queries work against both; only the environment segment changes.
The practical discipline for an SME in Canada, the UK, or the US is to treat the sandbox as the contract: every change to your integration - a new entity mapped, a new filter clause, a revised retry policy - is proved against the sandbox first, then promoted. This is also where rate-limit behaviour diverges (sandboxes are throttled more aggressively than production), so a flow that 'worked in dev' can still fail at go-live if it was never tested against realistic data volumes.
API Rate Limits, Throttling, and Retry Strategy
Business Central enforces throughput limits that sit on top of the per-request limits above. Microsoft publishes the current set in its API limits documentation, and the headline figures matter for any integration that moves more than a trivial volume of records. Production environments are typically throttled around 600 API requests per minute; sandbox environments around 300 requests per minute. Individual OData and SOAP requests also run concurrently under a small fixed queue, so a poorly-tuned batch job can stall even when the per-minute ceiling is nowhere near saturated.
When a limit is exceeded, Business Central returns HTTP 429 (Too Many Requests) for rate violations and HTTP 504 (Gateway Timeout) when a single request exceeds the 10-minute execution ceiling. A robust client implements exponential backoff with jitter on 429, respects any Retry-After header, and splits long-running operations into paged or batched chunks that finish well under the timeout. This is not optional engineering - it is the difference between an integration that survives month-end close and one that silently stalls at the worst possible moment.
For SMEs the implication is concrete: budget for throttling-aware middleware from day one. Off-the-shelf iPaaS connectors (Power Automate, Zapier, Make) handle backoff for you but cap your control; a purpose-built integration gives you full control over retry semantics, idempotency keys, and dead-letter handling but is more to maintain. Flectic's guidance is to start with whichever side of that tradeoff matches your team's appetite, and revisit once transaction volumes cross roughly 50,000 records per day.
- Production: ~600 requests/minute; Sandbox: ~300 requests/minute
- HTTP 429 = throttled (back off and retry); HTTP 504 = single request exceeded 10 minutes
- Implement exponential backoff with jitter on 429 and honour Retry-After
- Split long-running jobs into paged/batched chunks well under the timeout
- Budget for throttling-aware middleware from day one - it is cheaper than retrofitting it
Webhooks and Change Notifications
Polling the Business Central API for changes is wasteful and burns your request budget against the rate ceiling. Microsoft addresses this with webhook subscriptions: you register a callback URL against a resource (for example, /companies({id})/customers) and Business Central POSTs a notification to your endpoint when a create, update, or delete occurs on that resource. Webhooks are exposed on the API v2.0 surface and are documented under the API Page type reference.
Each subscription carries a validation token handshake (BC sends a validation request when you create the subscription; your endpoint must echo the token back to confirm ownership) and a clientState secret you can use to verify the notification origin. Notifications tell you that something changed and which entity changed - they do not carry the payload, so your handler must follow up with a GET to fetch the new state. Designing for this two-step pattern avoids stale data and keeps the notification handler fast.
For SME integrations the rule of thumb is simple: use webhooks for record-level events that drive downstream automation (a new sales order triggers fulfilment, a vendor change syncs to procurement) and reserve polling for the small set of cases where the entity genuinely has no webhook support.
- 01Subscribe to a resource
POST a subscription payload to /companies({id})/subscriptions referencing the resource you want to monitor (e.g. customers) and your HTTPS callback URL.
- 02Complete the validation handshake
BC sends a validation request with a validationToken. Your endpoint must respond within a short window with the token echoed back to confirm you own the callback URL.
- 03Receive and verify notifications
On each change, BC POSTs a notification containing the resource id and your clientState secret. Verify the secret, then issue a GET to fetch the updated record.
- 04Renew before expiry
Subscriptions expire (Microsoft documents the default lifetime in the API reference). Schedule a renewal job to refresh subscriptions before they lapse, or you will silently stop receiving notifications.
SME Integration Patterns That Hold Up
The integrations that survive in production for SMEs share a small set of traits. They are idempotent (every write carries a stable correlation id so a retry after a 504 does not create a duplicate invoice). They are throttling-aware (they respect 429 and page large reads rather than hammering $top). They are observable (every failure is logged with enough context to reproduce, and a dead-letter queue catches anything that cannot be auto-retried). And they isolate the ERP from the downstream system - the API client is the only thing that knows BC's schema; everything downstream talks to a normalised domain model the integration owns.
The patterns that fail are the mirror image: polling in a tight loop, fire-and-forget writes with no correlation id, embedding BC field names directly into a commerce storefront, and assuming the sandbox's rate ceiling matches production. Each of these is a go-live incident waiting to happen.
Because Flectic implements both Dynamics 365 and Odoo, we tune these patterns to the platform in front of us. The discipline - idempotency, backoff, observability, isolation - is platform-neutral. The specific limits, auth model, and webhook shape are what change between BC's v2.0/OData v4 surface and Odoo's XML-RPC/JSON-RPC surface, and that is exactly the kind of detail a partner should own so the SME does not have to.
Frequently asked questions
Is the Business Central API REST or SOAP?
The recommended Business Central API (v2.0) is REST, built on OData v4 with JSON payloads. Business Central still exposes a legacy SOAP web services surface for backward compatibility, but Microsoft positions the v2.0 REST API as the preferred path for new integrations and has announced deprecation of OData page endpoints starting with the 2027 release wave 1.
Can I use basic authentication with the Business Central API?
No. Basic authentication and web service access keys are deprecated for Business Central online. New integrations must use OAuth 2.0 through Microsoft Entra ID, either delegated (for interactive, user-context flows) or service-to-service / client credentials (for headless automation, scheduled jobs, and partner integrations).
What are the main Business Central API limits I should design around?
Four limits matter most: a maximum page size of 20,000 entities, a maximum batch of 100 operations per $batch, a 350 MB request body ceiling, and a 10-minute execution timeout (HTTP 504 if exceeded). On top of those, expect around 600 requests per minute in production and 300 in sandbox, with HTTP 429 returned when you exceed the rate.
Do sandbox environments use the same API as production?
Yes. Sandbox environments use the same v2.0 REST/OData v4 endpoints as production - you only change the environment name segment in the URL, and the same OAuth2 app registration and client code work against both. Note that sandboxes are throttled more aggressively than production, so an integration that passes in a sandbox can still fail under realistic production load.
How many sandbox environments do I get with Business Central?
The base Essential or Premium subscription includes one production environment plus three sandbox environments. Additional sandbox environments come bundled with additional production environments (three sandboxes per additional production environment) - you cannot purchase a sandbox on its own.
Does Flectic only work with the Business Central API?
No. Flectic is platform-neutral and implements both Dynamics 365 (including Business Central) and Odoo for SMEs across Canada, the UK, and the US. The integration discipline - idempotency, throttling-aware retries, observability, isolation - is the same; the specific API surface, auth model, and limits differ between platforms.
Designing a Business Central integration that actually survives go-live?
Flectic implements Dynamics 365 and Odoo integrations for SMEs across Canada, the UK, and the US - throttling-aware middleware, idempotent writes, and webhook patterns tuned to your transaction volume. We can help you scope the right integration architecture in a single focused call.
Sources
- v2.0 is the recommended REST API surface, built on OData v4 with standard HTTP verbs — https://learn.microsoft.com/en-us/dynamics365/business-central/dev-itpro/api-reference/v2.0/
- Operational limits: 20,000-entity pages, 100-operation batches, 350 MB request body, 300 companies per environment — https://learn.microsoft.com/en-us/dynamics365/business-central/dev-itpro/administration/operational-limits-online
- Request execution timeout is 10 minutes; HTTP 504 Gateway Timeout returned when exceeded — https://learn.microsoft.com/en-us/dynamics365/business-central/dev-itpro/api-reference/v2.0/dynamics-current-limits
- Rate-limit guidance: HTTP 429 handling, execution time limited to 10 minutes, retry semantics — https://learn.microsoft.com/en-us/dynamics365/business-central/dev-itpro/api-reference/v2.0/dynamics-rate-limits
- S2S authentication uses the OAuth 2.0 Client Credentials flow; requires app registration with API.ReadWrite.All / Automation.ReadWrite.All and registration inside BC — https://learn.microsoft.com/en-us/dynamics365/business-central/dev-itpro/administration/automation-apis-using-s2s-authentication
- Production and sandbox environment entitlements: 1 production + 3 sandbox environments with base subscription; 3 additional sandboxes per additional production environment — https://learn.microsoft.com/en-us/dynamics365/business-central/dev-itpro/administration/environment-types
- Environments lifecycle endpoint used to discover environment names programmatically — https://learn.microsoft.com/en-us/dynamics365/business-central/dev-itpro/webservices/api-get-environments
- OData page endpoints will be deprecated starting 2027 release wave 1 in favour of API v2.0 — https://www.eonesolutions.com/blog/business-central-will-deprecate-odata/
- Basic auth / web service access keys deprecated for Business Central online SaaS; OAuth2 is the replacement — https://demiliani.com/2021/02/08/dynamics-365-business-central-soap-and-basic-authentication-deprecation/
- API rate limit changed from per-second to ~600 requests/minute production and ~300 requests/minute sandbox — https://www.eonesolutions.com/blog/change-in-business-central-api-limit/