Microsoft Dynamics 365 Business Central is a standard ERP for the growing mid-market and widely used in Germany. Anyone running a Shopware 6 shop with BC as the leading system sooner or later faces an integration question: how do customers, items, prices and stock flow reliably, traceably and, ideally, in real time between the two worlds? This guide shows how a Business Central Shopware integration is built cleanly on the technical side - with OData v4, webhooks, Azure Service Bus and a clear middleware strategy - and which B2B scenarios become feasible without expensive add-on modules.
Dynamics 365 BC in the German Mid-Market
Germany is a core market for Dynamics 365 Business Central: with 1,264 recorded user companies it ranks second behind the United States (3,475) and accounts for 11.78% of recorded BC installations (6sense). The target group is clearly anchored in the mid-market: 4,327 companies with 100-249 employees run BC, plus 2,966 with 20-49 and 2,309 with 250-499 employees (6sense).
As a cloud-native ERP, Business Central is designed to tie up little hardware of your own: updates, extensions and security fixes come from the Microsoft ecosystem instead of being renegotiated as a version jump every year. Running BC therefore gives you a modern backbone for a Shopware integration - and an interface layer that is documented and can be versioned.
1,264 BC user companies in Germany, second behind the United States with 3,475 (6sense) - 4,327 companies with 100-249 employees form the largest size band (6sense) - 6,000 OData requests per user in a sliding 5-minute window, a maximum of 5 of them processed concurrently (Microsoft Learn) - webhook subscriptions expire after three days unless they are renewed (Microsoft Learn).
Integration Architecture: Direct vs. Middleware
The first architectural decision is fundamental: connect BC directly to Shopware or via a middleware layer? Both approaches have their place. A direct integration calls the Shopware Admin API from BC (or vice versa) - fast to build but tightly coupled. A middleware decouples both systems via a broker, buffers peak loads and enables central mapping, logging and retry. Especially for B2B projects with blanket agreements, tiered pricing and multiple shops, experience shows there is no way around a middleware. Our experience from ERP integrations in Shopware shows that starting lean today pays off tomorrow with a scalable architecture.
| Criterion | Direct integration | Middleware architecture |
|---|---|---|
| Time-to-live | Fast (weeks) | Longer (months) |
| Coupling | Tight - system outage breaks sync | Loose - queue buffers outages |
| Retry & dead-letter | Build it yourself | Built-in via Service Bus |
| Data transformation | Scattered in the plugin | Central mapping layer |
| Monitoring | Two log sources | Central observability |
| Multiple shops / languages | Hard to scale | Natively supported |
| Ideal for | Small B2C scenarios | B2B, multichannel, stock-critical |
OData v4 API: Endpoints and Rate Limits
Business Central has offered an OData v4 REST API as its standard interface for several versions now - the older SOAP variant is considered deprecated for new development (Microsoft Learn). Through OData you can work with companies, customers, items, sales orders, vendors and many other entities, both from standard and custom pages. What matters for stable integrations are the official per-user limits: BC OData v4 allows 6,000 requests in a sliding 5-minute window (Microsoft Learn), which works out to about 20 requests per second. On top of that: a maximum of 5 requests processed concurrently, at most 100 simultaneous connections including queued ones, and a request queue of 95 (Microsoft Learn). When one of these limits is exceeded, BC responds with HTTP 429 and the client has to react with retry logic and a cool-off period (Microsoft Learn).
For a clean integration this means: the middleware must handle throttling, retry with exponential backoff and 429 responses. Ignoring this leads to integrations that collapse under load. For more on this, see our article on middleware in e-commerce.
### Retrieve customers (Standard API v2.0)
GET https://api.businesscentral.dynamics.com/v2.0/{tenant}/{env}/api/v2.0/companies({companyId})/customers?$top=100
Authorization: Bearer {token}
Accept: application/json
### Update a single item
PATCH https://api.businesscentral.dynamics.com/v2.0/{tenant}/{env}/api/v2.0/companies({companyId})/items({itemId})
Authorization: Bearer {token}
If-Match: {etag}
Content-Type: application/json
{
"unitPrice": 129.00,
"inventory": 42
}
### Create a SalesOrder (from Shopware)
POST https://api.businesscentral.dynamics.com/v2.0/{tenant}/{env}/api/v2.0/companies({companyId})/salesOrders
Authorization: Bearer {token}
Content-Type: application/json
{
"customerNumber": "K-10042",
"externalDocumentNumber": "SW-ORDER-98312",
"orderDate": "2026-05-02"
} Webhook Subscriptions for Real-Time Events
Polling is expensive and slow: every request counts against the per-user limit, and between two runs the shop sits on stale data. As the counter-design, BC officially supports webhook subscriptions via the subscriptions endpoint of API v2.0. A subscription has a maximum lifetime of three days and must be renewed before it expires - otherwise the event stream ends silently (Microsoft Learn). Production-grade integrations therefore implement a renewal job that extends subscriptions on time and logs failures.
A common best practice is to combine webhook triggers for real-time events with periodic API reconciliation - the latter catches lost events. You get the speed of a push model with the reliability of a pull.
POST /api/v2.0/subscriptions
{
"notificationUrl": "https://middleware.example.com/bc/webhooks",
"resource": "api/v2.0/companies({companyId})/items",
"clientState": "xictron-prod-items-v1",
"expirationDateTime": "2026-05-05T12:00:00Z"
}
// Renewal pseudocode (middleware)
foreach (sub in activeSubscriptions) {
if (sub.expiresIn < 24h) {
PATCH /api/v2.0/subscriptions(sub.id)
{ "expirationDateTime": now + 3d }
}
} Subscriptions expire after a maximum of three days (Microsoft Learn). Without automated renewal the real-time sync breaks silently - usually on a weekend when nobody is watching. Alerting on missing webhook events belongs in every production BC integration.
$batch for Bulk Sync: Thousands of Records Efficiently
At initial go-live or for price list rollouts, thousands of items or prices often need to land in BC. Pushing every request individually through the OData endpoint blows through the rate limits in minutes. The solution is the $batch endpoint: it bundles multiple create, update and delete operations into a single HTTP request (Microsoft Learn). That is a win both for rate-limit accounting and for transactional semantics, since all operations in a changeset can be treated atomically.
A batch size between 50 and 200 operations per request has proven practical - depending on payload size, network latency and the complexity of the target entity. We cover the B2B side of the architecture and how to embed such bulk operations in larger processes in our article on B2B sales digitalization.
POST /api/v2.0/$batch HTTP/1.1
Content-Type: multipart/mixed; boundary=batch_xictron_001
Authorization: Bearer {token}
--batch_xictron_001
Content-Type: multipart/mixed; boundary=changeset_items_001
--changeset_items_001
Content-Type: application/http
Content-Transfer-Encoding: binary
PATCH companies({id})/items({itemIdA}) HTTP/1.1
Content-Type: application/json
{"unitPrice":119.00,"inventory":120}
--changeset_items_001
Content-Type: application/http
Content-Transfer-Encoding: binary
PATCH companies({id})/items({itemIdB}) HTTP/1.1
Content-Type: application/json
{"unitPrice":89.50,"inventory":58}
--changeset_items_001--
--batch_xictron_001-- Azure Service Bus for Asynchronous Queues
For more demanding integrations, a queue between BC and Shopware is a stable building block. Azure Service Bus acts as an asynchronous broker: Shopware events such as new orders or customer registrations are written to queues, the middleware consumes, maps and writes them into BC. The other way around, item, price and stock changes from BC flow via webhooks into queues and from there into Shopware. Dead-letter queues catch faulty messages without blocking the main stream; exponential backoff prevents hammering on failing endpoints.
Alternatives such as self-hosted brokers, generic queues based on RabbitMQ or Kafka, or lightweight SaaS middleware layers are technically just as viable - what matters is that sync flows are not synchronously chained to the HTTP availability of the end systems. Generic iPaaS patterns address the same principle; we do not recommend specific third-party vendors but build the right solution based on your requirements.
Every queue message must allow idempotent processing: re-delivering the same order twice must not create duplicate sales orders in BC. External document numbers, Shopware order UUIDs and upsert logic belong in every implementation - regardless of the broker you choose.
Data Model Mapping: BC ↔ Shopware
The technical foundation of every integration is an explicit, documented mapping between BC and Shopware entities. Changes to this mapping are the most common source of bugs when they only live in a single developer's head. We therefore version the mapping as JSON or YAML and validate it in CI - alongside mappings for order statuses, payment methods and currencies.
| Business Central | Shopware 6 | Sync direction | Trigger |
|---|---|---|---|
| Customer | customer | Bidirectional | Webhook + Shopware hook |
| Item | product | BC → SW | Webhook items |
| Item Variant | product (variant) | BC → SW | Webhook itemVariants |
| Unit price / Sales price | product.price | BC → SW | Webhook + nightly $batch |
| Inventory | product.stock | BC → SW | Webhook inventory |
| Sales Order | order | SW → BC | Shopware order hook |
| Sales Invoice | order.invoice | BC → SW | Webhook + reconciliation |
| Customer Price Group | rule / customer_group | BC → SW | Nightly $batch |
B2B Scenarios: Blanket Agreements and Tiered Prices
The real value of a BC integration shows itself in B2B. Blanket agreements, customer-specific assortments, tiered prices, budget controls and approval workflows are almost always maintained in BC - Shopware is the sales channel. Shopware 6 CE offers a powerful rule-builder system that does not require paid extensions: customer groups, company accounts and individual price rules can be mirrored via custom plugins and the Admin API. More context in our articles on B2B pricing strategies, customer-specific assortments and B2B self-service portals.
- Blanket agreements maintained as blanket sales orders in BC - API-mirrored in Shopware as a customer-specific assortment with remaining quantities
- Tiered prices derived SKU-specific from BC price lists and modelled as rule-builder rules in Shopware CE (quantity and customer-group triggers)
- Customer-specific prices from contract data via the rule builder in Shopware CE - without licence-bound package solutions
- Credit limits and payment terms from BC translated into Shopware checkout rules (block on breach)
- Approval workflows for large orders natively in Shopware as a custom development, mirrored in BC as sales-quote status
- Company accounts and offer management as CE-compatible patterns - Shopware-native implementation with BC as the source of truth
- Bidirectional real-time sync for stock - critical when inventory is tight and multiple channels compete for stock
- Multiple shops on one BC company - product visibility per shop managed through channel mapping
Error Handling and Reconciliation
Integrations rarely fail spectacularly - they fail quietly: a webhook is missing, a price is stale, an item looks different in the shop than in BC. That happens above all when error handling and reconciliation are implemented after the fact. Teams that build the failure paths in from the start notice a missing message the same day - not when the stocktake fails to add up.
- Idempotency keys per message (Shopware order UUID, BC ETag) prevent duplicate postings on retries
- Dead-letter queues with alerting - faulty messages must not block healthy flows
- Exponential backoff on HTTP 429 and 5xx - Microsoft requires retry logic with a cool-off period (Microsoft Learn)
- Nightly reconciliation via
$batch- catches missed webhook events and acts as a safety net - Structured logs with correlation IDs spanning Shopware, middleware and BC - otherwise post-mortem debugging becomes nearly impossible
- Business alerts on quantity drift (e.g. ">5% stock difference between shop and BC")
Typical Pitfalls in BC-Shopware Projects
- Underestimating rate limits - 6,000 requests per 5 minutes per user (Microsoft Learn) are consumed faster than many assume, especially with synchronous price lookups per page view
- Webhook expiration not automated - subscriptions end silently after three days; monitoring is mandatory
- Missing idempotency - retry logic without clean keys duplicates orders or invoices in BC
- Time zones and date formats - BC works in UTC internally, Shopware admins think in local time; logic bugs around discounts and campaign windows are common
- Multi-currency scenarios - prices, taxes and rounding rules must be consistent per country and currency, otherwise shop and ERP drift apart
- Tax logic - BC calculates based on business posting groups, Shopware based on tax rules; mapping errors cost compliance later
- Mixing data and business rules - rules like "price X only for customer Y from 100 pieces" belong in a rule engine, not in SQL triggers
- Unclear ownership - who may create an item in the shop: BC, PIM or Shopware? Without a decision, conflicts follow
Implementation Roadmap in 5 Phases
- Analysis & scoping - inventory the data model in BC and Shopware, define sync directions, identify critical scenarios (B2B prices, stock, blanket agreements)
- Architecture decision - direct vs. middleware, pick the queue technology (e.g. Azure Service Bus), set up authentication with Entra ID
- MVP integration - master entities (customers, items, stock) bidirectional, OData client with retry/backoff, webhook subscriptions including renewal job
- Expansion of B2B logic - price lists, customer groups, blanket agreements, approval workflows, customer-specific assortments via rule builder and custom plugins
- Operate & reconcile - monitoring, alerting, nightly
$batchreconciliation, performance tuning, continuous adaptation to new BC and Shopware releases
For customers coming from an older Microsoft ERP generation, also check our take on Dynamics NAV - many NAV installations are on their way to BC, and a future-proof shop integration should account for that from the start. Our integrations services give an overview of all supported system landscapes.
This article is based on data from: Microsoft Learn (per-user OData v4 limits, webhook subscriptions, $batch, behaviour on HTTP 429), 6sense (recorded BC user base by country and size band) and Shopware Docs (Admin API patterns). Figures may vary by reporting period.
BC Integration as a Strategic Investment
A Business Central Shopware integration is not a plugin purchase but a strategic architecture decision. Those who bet on OData v4, webhooks and a decoupled middleware get an integration that grows with the business - in B2B as much as in multichannel retail. It only carries, though, if the data model, error handling and reconciliation are taken seriously from the start. We support you from architecture through implementation to ongoing operations - based on Shopware 6 CE, clean programming and established B2B patterns.
Based on experience, 8-16 weeks for a production-ready integration is realistic - depending on the scope of B2B logic, the number of entities and the desired middleware approach. An MVP with customers, items, stock and orders can usually go live in 6-8 weeks. We are happy to provide an individual estimate for your project.
Not strictly. Azure Service Bus is a well-integrated option within the Microsoft ecosystem; typically, generic queues such as RabbitMQ, Kafka or lightweight SaaS brokers are equally suitable. What matters is the decoupling between BC and Shopware - the specific technology is chosen based on your existing infrastructure.
According to Microsoft Learn, the limit is 6,000 requests per user in a sliding 5-minute window, i.e. about 20 requests per second, with a maximum of 5 processed concurrently. As a rule, a combination of the $batch endpoint for bulk operations, caching of master data in the middleware, webhook-based real-time sync instead of polling and clean retry handling for HTTP 429 with a cool-off period helps.
Typically yes. Shopware 6 CE provides enough building blocks with customer groups, the rule builder and the Admin API to model tiered and customer-specific prices from BC. We usually develop a custom plugin that translates BC price lists cleanly into Shopware rules - as part of our B2B e-commerce work.
In a middleware architecture with a queue, the message is buffered and, experience shows, automatically delivered once the connection returns - dead-letter queues catch permanently failing messages. Orders from Shopware are therefore usually not lost. Direct integrations without a queue are more fragile in such scenarios and require additional retry logic in the shop.
Authentication typically runs via Entra ID (formerly Azure AD) with OAuth 2.0 and a dedicated service principal, data is transmitted encrypted and access is traceable in BC audit logs. For GDPR requirements we provide a documented data flow architecture, clear role separation and logging - covered in more depth in our blog on ERP integration.