Microsoft Dynamics 365 Business Central is the ERP of choice for many mid-market companies, especially those already invested in the Microsoft ecosystem. Integrating it with WooCommerce requires understanding D365’s API landscape and choosing the right integration pattern for your scale and complexity.
D365 Business Central API Options
OData/REST APIs (Standard)
Business Central exposes standard entities via OData v4 endpoints:
GET https://{tenant}.api.businesscentral.dynamics.com/v2.0/{environment}/api/v2.0/items
GET https://{tenant}.api.businesscentral.dynamics.com/v2.0/{environment}/api/v2.0/salesOrders
GET https://{tenant}.api.businesscentral.dynamics.com/v2.0/{environment}/api/v2.0/customers
Authentication: OAuth 2.0 via Azure AD. Register an app in Azure Portal, grant Financials.ReadWrite.All permissions.
Custom APIs (AL Extensions)
For complex integrations, build custom API endpoints in Business Central using AL language:
page 50100 "WooCommerce Items API"
{
PageType = API;
APIPublisher = 'wpclan';
APIGroup = 'woocommerce';
APIVersion = 'v1.0';
EntityName = 'item';
EntitySetName = 'items';
SourceTable = Item;
// ... field definitions
}
Dataverse (Advanced)
For bi-directional sync with change tracking, Business Central can sync data to Dataverse (formerly Common Data Service). This provides webhook-like change notifications.
Integration Patterns
Pattern 1: Power Automate (Low-Code)
Best for: Simple integrations, < 100 orders/day
Microsoft Power Automate can connect D365 to WooCommerce via HTTP connectors:
Trigger: When a WooCommerce order is created (HTTP webhook)
→ Parse JSON (order data)
→ D365: Find or create customer
→ D365: Create sales order
→ D365: Add line items
→ WooCommerce: Update order meta with D365 reference
Pros: No code, visual workflow, built-in error handling
Cons: API call limits (Performance plan needed), slower execution, limited transformation logic
Pattern 2: Azure Functions + Service Bus (Cloud-Native)
Best for: Medium-high volume, Microsoft-stack teams
WooCommerce Webhook → Azure Function → Service Bus Queue → Azure Function → D365 API
D365 Change Feed → Azure Function → Service Bus Queue → Azure Function → WooCommerce API
Azure Functions handle the API calls and data transformation. Service Bus provides reliable message queuing with dead-letter support.
Pattern 3: Custom Node.js Middleware (Full Control)
Best for: Complex requirements, custom business logic
// D365 Business Central client
class D365Client {
constructor(tenantId, clientId, clientSecret, environment) {
this.baseUrl = https://api.businesscentral.dynamics.com/v2.0/${environment}/api/v2.0;
this.tokenUrl = https://login.microsoftonline.com/${tenantId}/oauth2/v2.0/token;
this.clientId = clientId;
this.clientSecret = clientSecret;
}
async getToken() {
const response = await fetch(this.tokenUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams({
grant_type: 'client_credentials',
client_id: this.clientId,
client_secret: this.clientSecret,
scope: 'https://api.businesscentral.dynamics.com/.default'
})
});
const data = await response.json();
return data.access_token;
}
async getItems() {
const token = await this.getToken();
const response = await fetch(${this.baseUrl}/items, {
headers: { 'Authorization': Bearer ${token} }
});
return response.json();
}
async createSalesOrder(orderData) {
const token = await this.getToken();
return fetch(${this.baseUrl}/salesOrders, {
method: 'POST',
headers: {
'Authorization': Bearer ${token},
'Content-Type': 'application/json'
},
body: JSON.stringify(orderData)
});
}
}
Data Mapping: D365 → WooCommerce
Items to Products
| D365 Field | WooCommerce | Notes |
|---|---|---|
| number | sku | Primary key for mapping |
| displayName | name | |
| unitPrice | regular_price | From price list |
| inventory | stock_quantity | Real-time critical |
| itemCategoryCode | categories | Map codes to WC category IDs |
| blocked | status | blocked=true → draft |
| gtin | meta: _gtin | For schema markup |
Sales Orders
| WooCommerce | D365 Sales Order | Notes |
|---|---|---|
| order.id | externalDocumentNumber | Cross-reference |
| billing.email | customerNumber | Match by email |
| line_items[].sku | salesOrderLines[].itemId | Match by item number |
| line_items[].quantity | salesOrderLines[].quantity | |
| line_items[].total | salesOrderLines[].unitPrice | Recalculate for discounts |
| shipping_total | — | Add as separate line or freight charge |
Handling D365’s Pagination
Business Central APIs return max 20,000 records and use @odata.nextLink for pagination:
async function getAllItems(client) {
let items = [];
let url = ${client.baseUrl}/items?$top=1000;
while (url) {
const response = await client.authenticatedFetch(url);
const data = await response.json();
items = items.concat(data.value);
url = data['@odata.nextLink'] || null;
}
return items;
}
Inventory Sync Strategy
D365 Business Central tracks inventory at the location (warehouse) level. Your sync must decide:
- Sum all locations for a single WooCommerce stock count?
- Sync specific locations (e.g., only the ecommerce warehouse)?
- Reserve buffer stock (show 90% of actual stock to avoid overselling)?
async function syncInventory() {
const d365Items = await d365.getItems();
const updates = d365Items.value
.filter(item => !item.blocked)
.map(item => ({
sku: item.number,
stock_quantity: Math.floor(item.inventory * 0.95), // 5% buffer
stock_status: item.inventory > 0 ? 'instock' : 'outofstock'
}));
// Batch update WooCommerce
for (let i = 0; i < updates.length; i += 100) {
await wooApi.post('products/batch', {
update: updates.slice(i, i + 100).map(u => ({
sku: u.sku, // requires SKU lookup to get product ID
stock_quantity: u.stock_quantity,
stock_status: u.stock_status
}))
});
}
}
Common D365 Integration Pitfalls
- OAuth token expiration: Tokens expire after 1 hour. Always refresh before API calls.
- Rate limiting: Business Central has a 600 calls/minute limit per tenant. Batch your requests.
- Number sequences: D365 auto-generates document numbers. Don’t try to set them manually.
- Dimensions: D365’s financial dimensions (cost center, department) have no WooCommerce equivalent. Plan how to handle them.
- Multi-currency: D365 handles multi-currency natively. WooCommerce needs a plugin for multi-currency. Map exchange rates carefully.
Conclusion
D365 Business Central + WooCommerce is a strong combination. Power Automate works for simple, low-volume integrations. Azure Functions suit Microsoft-stack teams needing reliability. Custom middleware gives you full control for complex scenarios. Regardless of the pattern, the fundamentals are the same: map your data carefully, handle inventory as the highest-priority sync, and build robust error handling from day one.
Last modified: April 3, 2026
United States / English
Slovensko / Slovenčina
Canada / Français
Türkiye / Türkçe