The Business Central API has quietly become one of the cleanest REST APIs in the Microsoft enterprise stack. In 2026, it is what most modern BC integrations are built on. Yet most documentation is either too shallow (Microsoft’s quick start) or too deep (the AL source). This article is the practical middle ground we wish existed when we were ramping up.
We will cover authentication, endpoint structure, query patterns, custom APIs, webhooks, rate limiting, and the integration patterns we use every week in production.
The two flavors of Business Central API
BC exposes two API surfaces. Knowing which one to use matters.
The standard API (v2.0) is Microsoft’s officially supported, OData REST API. It covers most BC entities (customers, vendors, items, invoices, journal entries) and is stable across BC versions. Use it for production integrations.
The custom API pattern lets developers expose their own AL pages as REST endpoints. Use it when you need to expose business logic the standard API does not cover. Be aware: your custom API is your responsibility to version and document.
Authentication: OAuth 2.0, no shortcuts
BC API authentication is OAuth 2.0 with Microsoft Entra (formerly Azure AD). Two flows matter.
Client credentials flow: server-to-server integration with no user context. Register an Entra app, grant admin consent for BC, use client_id and client_secret to obtain a token. This is the right pattern for backend integrations.
Authorization code flow: user-context integration where actions are performed on behalf of a specific user. Use this for user-facing apps that need delegated access.
Keep tokens server-side. Never embed client secrets in client-side code. Rotate secrets regularly. Use certificate-based auth for high-security scenarios.
Endpoint structure and discovery
The base URL pattern is: https://api.businesscentral.dynamics.com/v2.0/{tenant-id}/{environment}/api/v2.0/companies({company-id})/{entity}
Discover available entities by calling the root endpoint without a specific entity. The response is OData metadata describing all available collections.
Most queries follow standard OData syntax: $filter, $select, $top, $skip, $expand, $orderby. Combine them to pull exactly what you need without round-trips.
Pagination and rate limits
The BC API returns paginated results. Default page size is 20,000 records, but in practice you should respect the @odata.nextLink in the response and not hardcode page sizes.
Rate limits apply per tenant: 600 requests per minute per environment in 2026. Heavy integrations should implement exponential backoff on 429 responses. Burst protection is real and triggers in seconds.
When pulling large datasets (more than 100,000 records), use changefeeds or scheduled extracts rather than synchronous calls.
Writing data: POST, PATCH, and idempotency
Writing data via the BC API has subtle gotchas.
POST creates a new entity. The response includes the new ID and ETag. Store both for future updates.
PATCH updates an existing entity. The If-Match header with the latest ETag prevents lost updates. If you skip ETags, you will silently overwrite concurrent changes.
Idempotency: BC does not natively deduplicate POST requests. If you retry a creation after a timeout, you can end up with duplicate records. Use a unique business key (e.g., your external order number) and a quick GET before POST to check.
Batch operations: BC supports the OData $batch endpoint for multiple operations in one request. Use it for bulk creates and updates. Limits apply (typically 100 operations per batch).
Custom APIs: when and how
The standard API covers most needs but not all. Common gaps: posting actions (e.g., post journal, release order), business logic that spans multiple entities, computed values not exposed by standard pages.
To build a custom API, create an AL page of type API, set the APIPublisher, APIGroup, APIVersion and EntityName properties, and expose the fields you need. Microsoft has clear documentation on the property set.
Version your custom APIs from day one. Use semantic versioning in the APIVersion property. Maintain breaking changes only in new major versions. Document your custom APIs with OpenAPI or similar so integrators know what to expect.
Webhooks for change notification
Polling the API for changes is the wrong pattern at scale. BC supports webhooks via the Microsoft Graph subscription model.
Register a subscription specifying the entity, change types and notification URL. BC posts notifications to your URL when matching changes occur. Subscriptions expire (typically 3 days) and must be renewed programmatically.
Webhooks are at-least-once delivery. Build your handler idempotent. The notification includes the changed entity ID but not the full payload, so you still GET the entity to retrieve the latest state.
Integration patterns we use weekly
Five integration patterns we apply in production BC environments.
Pattern one: middleware-light. Use Power Automate or Azure Logic Apps for low-volume workflows (less than 10,000 events per day). Faster to build, easier to maintain.
Pattern two: middleware-heavy. Use a dedicated integration service (Azure Function, custom .NET, MuleSoft) for high-volume, mission-critical flows. More resilience, observability, retry control.
Pattern three: event-driven. Webhooks plus a queue (Service Bus, Storage Queue). The right pattern for asynchronous integration with downstream systems.
Pattern four: scheduled ETL. For large data movement (BI, data lake), use Azure Data Factory with the BC connector. Reduces API load and gives you incremental loading.
Pattern five: customer-facing API gateway. Expose a curated subset of BC data through your own API gateway with rate limiting, authentication and observability. Never expose BC API directly to customer applications.
Common mistakes we see
Mistake one: hardcoded tenant IDs. The tenant ID is environment-specific. Hardcoding it breaks at every environment promotion.
Mistake two: synchronous bulk operations. Pulling 200,000 records in a single GET, timing out, retrying, timing out again. Use changefeeds.
Mistake three: ignoring rate limits. Building integrations that work in dev with 10 records and explode in prod with 100,000.
Mistake four: no idempotency. Retrying POST on timeout, creating duplicate invoices.
Mistake five: no monitoring. Building an integration and never instrumenting it. The first failure you hear about is from the finance team three months later.
The Asio Services way: API-first integrations
We build every BC integration with the assumption that another system will need the same data tomorrow. That means clear authentication, versioned custom APIs, observability from day one, and documentation that survives the developer who wrote it.
If you are designing a BC integration architecture, or auditing an existing one, we can help you choose the right patterns and avoid the common mistakes.
→ Book a free discovery call with Asio Services. We will review your integration architecture and recommend where to simplify.



