Illustration showing requests waiting to be let through an API limiter.
ยท 7 min read

Business Central API Limits: Explained for 2026

Business Central OData APIs limit each user to 6,000 requests per 5 minutes and 5 concurrent connections. Learn how the limits work and how to avoid 429 errors.

TL;DRBusiness Central OData APIs are rate limited per user: 5 concurrent requests, up to 100 queued connections, and 6,000 requests per 5-minute rolling window. Exceed any of these and you get HTTP 429 Too Many Requests. The main ways to stay under the limits are $batch for writes, $expand for reads, webhooks instead of polling, and Data-Access-Intent: ReadOnly for reporting queries.

When building integrations or pulling data from Business Central, you’ll quickly run into one of its most frustrating constraints: API rate limits. As Microsoft has deprecated SOAP APIs and is removing them from the platform in 2026, this post covers the OData v4 limits that govern modern integrations.

The Old System: Environment-Level Limits

For most of Business Central’s life as a SaaS product, API limits were applied at the environment level. All OData requests, no matter which user or service account made them, shared a single pool:

  • Sandbox environments: 300 requests per minute
  • Production environments: 600 requests per minute

These limits were straightforward to reason about. If you had a busy integration and a developer hitting the API at the same time, you shared the same bucket. For simple, low-frequency integrations this was fine. For anything requiring near-real-time sync or high-volume data pulls, it was a constant source of 429 Too Many Requests errors.

The New System: Per-User Rate Limits

Starting in late 2023, Microsoft began rolling out a per-user rate limiting model for OData requests. Instead of a single shared pool for the environment, each user or service principal now has its own quota. The current limits are:

LimitValue
Max concurrent requests5 per user
Max queued connections100 per user
Request speed (rate)6,000 per user per 5-minute sliding window

Here’s what each limit means in practice:

Concurrent requests are requests being actively processed at that moment. Once you hit 5, additional requests start queuing. Queued connections is the total of active and waiting requests combined; exceed 100 and Business Central starts rejecting requests outright. The speed limit of 6,000 per 5-minute window works out to about 20 requests per second on average, but it’s a rolling window rather than a fixed interval, so bursts can still trigger throttling even when your overall rate looks fine.

When a limit is breached, the API returns HTTP 429 Too Many Requests. The response includes a Retry-After header that tells your client how many seconds to wait before retrying.

The Single-User Trap

The per-user model is more generous than the old environment limit when you have many users distributing load across the system. But it creates a new problem for integrations: if your entire integration runs under a single service account (which is the most common setup), you are still effectively limited to a single user’s quota.

An integration that polls for new orders, syncs inventory, and fetches customer data all under one service principal will quickly saturate that account’s 6,000-requests-per-5-minutes quota. The fix is to distribute load across multiple service principals, but this adds operational complexity and isn’t always practical.

Working Within the Limits

A few strategies can cut down how many requests you burn through.

Use $batch for Writes

The OData $batch endpoint lets you bundle multiple create, update, or delete operations into a single HTTP request. Each batch counts as one request against your rate limit, making it much more efficient for bulk writes. A sync that might normally require hundreds of individual PATCH calls can often be collapsed into a handful of batch requests.

When reading data, avoid making separate requests for each related entity. The $expand parameter lets you fetch parent and child records in a single call. For example, fetching sales orders with their lines and payment terms in one request:

GET /companies({id})/salesOrders?$expand=salesOrderLines,paymentTerm

With hierarchical data, a single $expand call can replace a dozen individual lookups.

Use Read-Only Intent (Read Replicas)

For GET requests that don’t need up-to-the-millisecond data, such as reports, dashboards, and exports, you can instruct Business Central to route the request to a read-only database replica instead of the primary database. This is done by adding a request header:

Data-Access-Intent: ReadOnly

This doesn’t necessarily make individual queries faster, but it splits the read workload away from the primary database so your reporting and export traffic isn’t competing with day-to-day transactions. For API pages and AL queries, you can set DataAccessIntent = ReadOnly directly in the object definition.

Use Webhooks Instead of Polling

If your integration repeatedly polls for new or changed records, replace that pattern with Business Central webhooks. Webhooks push notifications to your endpoint when an entity is created, updated, or deleted, eliminating the constant polling that eats through your rate limit quota.

Filter Aggressively

Every request that returns data you don’t need is a wasted slot in your rate limit quota. Use $select to only return the fields you actually need, and use $filter with lastModifiedDateTime to only fetch records that have changed since your last sync.

There are two caveats to be aware of with this approach, both related to how Business Central handles concurrent transactions.

First, records can be missed entirely. Because transactions commit concurrently, a record can be committed after your sync starts but carry a timestamp earlier than your checkpoint. Your delta sync quietly skips it. There’s no built-in row version or change tracking column on standard API pages to close this gap, so most integrations work around it with periodic full syncs, which partly defeats the efficiency gain.

Second, depending on your environment’s transaction isolation configuration, your GET requests may return records from transactions that are still in progress. If that transaction is later rolled back, your integration has consumed data that never actually existed in the final state of the database. It’s worth understanding which isolation level your environment is using, especially if your integration feeds downstream systems or financial reporting.

Develop Custom API Pages

Exposing standard Business Central pages as web services is the quickest way to get data out, but it’s the slowest at runtime. Standard pages carry overhead from UI logic, triggers, and fields your integration doesn’t need. Custom API pages are purpose-built AL objects that expose only the data you specify, with much faster query performance. If you’re regularly pulling large datasets, the upfront development cost is usually worth it.


Skuno BI: Skip the Rate Limit Engineering

All of the techniques above work, but they add up. You’re writing retry logic with exponential backoff, managing batch sizes, distributing requests across multiple service principals, and building custom API pages for performance. When Business Central pushes a major update (like the removal of v1.0 APIs), you’re also responsible for migrating your integration to the new schema before fields disappear.

Skuno BI is built specifically for Business Central and takes a different approach. Rather than querying the OData API at runtime, Skuno BI syncs your data through an event-driven architecture that handles rate limiting, batching, and retries internally. You get higher effective throughput without needing to spread workload across multiple users or develop custom API pages.

It works for more than dashboards too. If you’re building data pipelines or downstream integrations, Skuno BI gives you a stable, consistent data layer to build on. Its schema doesn’t drop fields between Business Central releases, so your pipelines don’t break when Microsoft deprecates or restructures API endpoints. It also exposes a serialized row version column on every table, which gives you reliable delta syncs without the concurrency gaps that come with filtering by lastModifiedDateTime in the standard APIs.

Because Skuno BI stores your data in a purpose-built OLAP database, analytical queries never touch Business Central’s OLTP server. This matters for two reasons: your team’s ERP performance doesn’t degrade when someone runs a heavy report, and you don’t need to develop and maintain custom database indexes in Business Central to make reporting queries fast. Those indexes speed up reads but slow down every write operation on the tables they cover, which is a real cost on a transactional system that your whole business depends on.

If you’re spending more time engineering around rate limits than building your actual product, it’s worth a look.


Frequently Asked Questions

What are Business Central's current API rate limits?

Each user or service principal is limited to 5 concurrent requests, up to 100 queued connections, and 6,000 requests per 5-minute rolling window. These per-user limits replaced the old environment-level model starting in late 2023.

What does HTTP 429 mean in Business Central?

HTTP 429 Too Many Requests means you've exceeded one of the rate limits. The response includes a Retry-After header that tells your client how many seconds to wait before retrying.

How do I avoid hitting the API limit in Business Central?

The most practical strategies are: use $batch to combine multiple write operations into a single request, use $expand to fetch related records in one call, replace polling with webhooks, and add Data-Access-Intent: ReadOnly to reporting queries so they hit a read replica rather than the primary database.

What were Business Central's old API limits?

Before per-user limits, all requests in an environment shared a single pool: 300 requests per minute for sandbox environments and 600 per minute for production. Microsoft began replacing this model in late 2023.

Why is my Business Central integration getting throttled even at low volumes?

The most common cause is running all requests under a single service principal. Every call from that account counts toward one quota. Distributing load across multiple service principals, or reducing request count with $batch and $expand, usually resolves it.

Can webhooks help with Business Central rate limits?

Yes. If your integration polls repeatedly for new or changed records, replacing that pattern with Business Central webhooks eliminates those requests entirely. Webhooks push change notifications to your endpoint so you only call the API when you need to act on something.

Is lastModifiedDateTime reliable for delta syncs in Business Central?

Not entirely. Because Business Central processes transactions concurrently, a record can be committed with a timestamp earlier than your sync checkpoint, causing your delta sync to skip it silently. Most integrations compensate by running periodic full syncs alongside their delta syncs.

← All posts