WooCommerce and Dynamics
WooCommerce to Microsoft Dynamics: field mapping and sync guide
Which WooCommerce field goes where in Dynamics, when to use webhooks and when to run a scheduled sync, and what happens when the two systems disagree. Field names checked against WooCommerce and Microsoft documentation on 30 October 2026.
By itmarkerz Technologies. Updated 30 October 2026.
What this guide is based on
The WooCommerce side uses the REST API v3. The Dynamics side uses the Business Central API v2.0, because it has one documented resource for each thing a store needs. If you run Dynamics 365 Sales or Finance, the logic holds and the names differ; our product comparison covers those.
We have delivered order and customer sync between WooCommerce and Dynamics on a high-volume Belgian store, and enquiries and customer data from WordPress into Dynamics for a water-treatment supplier. Most of our work is delivered under NDA, so many projects cannot be named. Product and invoice mappings come from the documentation, and we say so here rather than imply otherwise. Treat this as a starting point to check on your own environment, because Dynamics customisation can change which fields exist and which are required.
Decide three things before mapping a single field
- Who owns each record. For each field, one system is the source of truth. If you can’t say which, you will end up with both systems overwriting each other.
- The shared key. SKU for products, order number for orders, and your own lookup table for customers. A store and an ERP have different internal IDs, and neither should have to remember the other’s.
- When an order becomes real. Most stores should send an order when payment is confirmed, not when it is created. Otherwise abandoned payment attempts turn into sales documents someone has to clean up.
Orders
Usually one way, store to Dynamics, with status coming back. See the Woo order properties, salesOrder and salesOrderLine.
| WooCommerce | Business Central | Watch out for |
|---|---|---|
number | externalDocumentNumber | Your duplicate check. Search for it before creating anything. |
date_paid_gmt | orderDate | Decide which date finance wants, and convert from GMT to the company’s time zone. |
customer_id | customerNumber | Through your own lookup table, not by copying the ID. Guests have customer_id 0, so they need a rule. |
billing.* | billToAddressLine1, billToCity, billToPostCode… | Check maximum lengths in your Dynamics configuration, or trim with a logged warning. |
shipping.* | shipToName, shipToAddressLine1, shipToCity… | Sent per order, so a one-off gift address doesn’t overwrite the customer record. |
currency | currencyCode | Your local currency may be blank in Business Central. Test this before go-live. |
line_items[].sku | salesOrderLines[].lineObjectNumber | With lineType set to Item. An empty SKU in Woo should stop the order and raise an alert. |
line_items[].quantity | quantity | Direct. |
line_items[].price | unitPrice | Check prices_include_tax against pricesIncludeTax, which is read-only on the order. See the tax section below. |
shipping_lines[] | salesOrderLines[] with lineType Account or Charge | Needs a decision from finance on where shipping is posted. |
fee_lines[] | salesOrderLines[] with lineType Account or Charge | Same as shipping. Often forgotten until a payment fee plugin is added. |
coupon_lines[] | discountAmount on the line or the order | Line totals in Woo already include discounts, so send one or the other, never both. |
transaction_id, payment_method | Custom field, or a payment journal entry | The standard salesOrder has no field for these. See the note on custom APIs. |
status | Your own rule | Woo statuses and Dynamics statuses don’t correspond one to one. See the table below. |
Status mapping
Woo has seven standard statuses, and a Business Central sales order only reports Draft, In Review or Open, plus a fullyShipped flag. So status isn’t a field-to-field copy. A workable rule looks like this:
| Woo status | What to do in Dynamics |
|---|---|
pending, on-hold, failed | Nothing yet. Waiting for payment or already failed. |
processing | Create the sales order. |
completed | Normally set from Dynamics: when fullyShipped is true, mark the Woo order completed. |
cancelled | If not yet shipped, delete or cancel by agreed process. If shipped, alert a person. |
refunded | Raise a credit memo through whichever route finance agrees. Never edit a posted document. |
Tax and rounding
Don’t expect totals to match by chance. Woo calculates tax by its own settings, and Dynamics recalculates from its own tax setup, so a 0.01 difference on a multi-line order is common. Decide the tolerance with finance, and compare total and total_tax with totalAmountIncludingTax and totalTaxAmount after creation. Anything outside the tolerance should raise an alert rather than quietly post.
Customers
See Woo customers and the customer resource. Many B2C stores send every order to a single “web customer” in Dynamics, with the address on the order, and only create named customers for accounts. That is a legitimate choice and removes a lot of matching logic, but check that finance and your VAT reporting can live with it.
| WooCommerce | Business Central | Watch out for |
|---|---|---|
email | email | The usual match key for people, but not always unique in Dynamics. Decide what happens when it matches two records. |
billing.company, or first_name + last_name | displayName, type | Set type to Company or Person accordingly. |
billing.address_1, address_2, city, state, postcode, country | addressLine1, addressLine2, city, state, postalCode, country | Woo uses ISO country codes. Check they match your Dynamics country table. |
billing.phone | phoneNumber | Direct, after formatting. |
| VAT number (usually order or customer meta) | taxRegistrationNumber, taxLiable | Not a core Woo field. It comes from whichever plugin collects it. |
| None | number, creditLimit, paymentTermsId, blocked | Owned by Dynamics. Read blocked before accepting a B2B order on account. |
date_modified_gmt | lastModifiedDateTime | Used for change detection on each side, and never copied across. |
Products and stock
Usually Dynamics to store. See Woo products and the item resource. Keep descriptions, images and SEO fields in WooCommerce unless you have a reason not to, since an ERP is a poor place to write them.
| WooCommerce | Business Central | Watch out for |
|---|---|---|
sku | number | The join between the systems. Agree this first, and clean duplicates before you start. |
global_unique_id | gtin | Direct, where you hold barcodes. |
name | displayName | Often owned by the shop, since marketing names differ from warehouse names. |
regular_price | unitPrice, priceIncludesTax | Usually owned by Dynamics. Check whether the store displays prices with or without tax. |
stock_quantity, manage_stock | inventory | inventory is read-only and is a total. Per-location stock needs another source. |
variations[] | itemVariants | Each variation needs its own SKU. Decide whether variations are items or item variants in Dynamics. |
status | blocked | A blocked item should stop selling. Decide if that means draft or simply out of stock. |
tax_class | taxGroupCode | A small lookup table, reviewed whenever someone adds a rate. |
Stock is where timing matters most. Dynamics’ figure doesn’t know about orders that haven’t reached it yet, so a naive overwrite can put units back on sale. Either subtract orders in flight or accept and document a small overselling risk.
Invoices
Let Dynamics issue invoices, and let the store only display them. The shipAndInvoice action on a sales order and the post action on a salesInvoice are how documents become final. Microsoft notes that the id on this resource can differ from the record’s systemId once posted, so store the API id and don’t assume they match.
| WooCommerce | Business Central | Watch out for |
|---|---|---|
number | externalDocumentNumber, orderNumber | Lets you find the invoice from the order on either side. |
| Download link in My Account | pdfDocument | Fetch and store a copy, or serve it through your own endpoint with an ownership check. |
date_paid_gmt, status | remainingAmount, status (Open, Paid, Canceled, Corrective) | Payment facts travel in one agreed direction. Don’t let both systems mark a thing paid. |
refunds[] | salesCreditMemos, or makeCorrectiveCreditMemo | A Woo refund isn’t a credit note until accounting says so. Agree who issues it. |
Webhooks or scheduled sync
Use both. Webhooks give you speed, and a scheduled job gives you certainty. Here is what each side actually does.
| WooCommerce webhooks | Business Central webhooks | |
|---|---|---|
| Payload | JSON of the resource, with an HMAC-SHA256 signature header | Which record changed and how. You fetch the record. |
| Timing | Processed in the background | Waits 30 seconds after the first change. More than 1,000 changes become a single collection notification. |
| On failure | Disabled after five consecutive failures, until someone re-enables it | Retries for 36 hours on 408, 429 or 5xx. Any other error code deletes the subscription. |
| Lifetime | Until disabled | Expires after three days unless renewed, with a handshake each time. |
| Source | WooCommerce docs | Microsoft docs |
Three things follow from that table.
- Answer webhooks fast. Accept, store the message, reply with a 2xx, and do the work in a queue. A slow receiver is how a Woo webhook gets disabled, and at that point nothing announces that orders have stopped flowing.
- Return a retryable error. If your receiver is having trouble with Business Central notifications, send a 503 and not a 400. The wrong error code deletes your subscription.
- Renew on a schedule, and monitor it. A forgotten three-day renewal is a silent failure.
Then add a scheduled job as the safety net. Ask each system for what changed since the last run, using modified_after on WooCommerce and a filter on lastModifiedDateTime on Business Central, and process anything the webhooks missed. Because the job can run again safely, it also repairs an outage without anybody having to work out what was lost.
Conflict rules
Avoid “last write wins” unless a field really doesn’t matter. Clocks differ, and a bulk update in Dynamics can overwrite a customer’s address from an hour ago. Here is a starting point to adapt.
| Data | Owner | If they differ |
|---|---|---|
| Order lines and prices after payment | WooCommerce | Dynamics edits are not sent back. Changes go through an agreed process, and a person is told. |
| Fulfilment and shipment status | Dynamics | Dynamics overwrites the store’s status. |
| Credit limit, payment terms, blocked flag | Dynamics | Dynamics overwrites, and the store only reads. |
| Customer login, marketing consent | WooCommerce | Never sent to overwrite anything in Dynamics. |
| Customer address | Agree per field | Order addresses stay on the order. An account address change goes to a review queue if both sides changed since the last sync. |
| Price and stock | Dynamics | Dynamics overwrites, with stock adjusted for orders in flight. |
| Marketing name, description, images | WooCommerce | Not synced from Dynamics. |
| Payment status | One agreed side | Mismatch raises an alert. Never resolved automatically. |
| Tax totals | Dynamics for posting | Within tolerance, accept. Outside it, hold and alert. |
The limits to design around
- Business Central rate limits. Microsoft lists 6,000 OData requests in a five-minute window per user, 5 processed at once, 100 operations in a batch, and an 8-minute timeout. Exceeding the rate limit returns a 429, so retries need a wait.
- Woo batch limit. Batch endpoints such as products take up to 100 objects per request by default.
- Custom fields. Microsoft says standard API pages can’t be extended with extra fields. To send a payment reference, you copy the page’s AL code into a custom API, which is routine but needs someone who can write AL.
- Order storage. Stores can use High-Performance Order Storage, on by default for new installs since WooCommerce 8.2. Integration code that reads order data straight from the posts tables will break there, so use the REST API or the order classes.
For how this holds up under load, read syncing orders at high volume. If you would like us to build it, see the integration service. For the store itself, see WooCommerce development.
Dynamics integrations we have delivered
Three years keeping a high-volume Belgian WooCommerce store up, fast and in sync with Microsoft Dynamics: PHP 7.4 to current, two-hourly backups to S3-compatible storage, monitoring, and every change request handled.
- Sector
- E-commerce & retail
- Region
- Belgium
- Stack
- WordPress, WooCommerce, Microsoft Dynamics
- Engagement
- Maintenance, three years and ongoing
WordPress website plus an integration that sends enquiries and customer data straight into Microsoft Dynamics for a Belgian supplier of water-treatment systems to businesses. Fixed-scope project.
- Sector
- Industrial & B2B
- Region
- Belgium
- Stack
- WordPress, Microsoft Dynamics
- Engagement
- Fixed-scope project
Questions
Does this apply to Dynamics 365 Sales or Finance as well?
The principles do. The field names here are from the Business Central API v2.0, because its documented resources line up closely with a store. Sales uses Dataverse tables such as salesorder and account, and Finance uses data entities through OData. Our guide to the three products covers what changes.
Have you built all four of these flows?
Not all of them. Our delivered Dynamics work covers orders and customers from a WooCommerce store, and enquiries and customer data from a WordPress site. The product and invoice mappings here come from the two products' documented APIs. They are how we would approach that work, and we would confirm them on your environment.
Should a webhook carry the data, or only trigger a fetch?
On the WooCommerce side the payload is the resource itself. On the Business Central side, the notification only tells you which record changed, so you fetch it. In both cases, we prefer treating the message as a signal and reading current data before writing, because messages can arrive late or out of order.
Which system should own the customer?
Usually Dynamics owns account and credit data, and the store owns login and preferences. Address is the one to discuss, because customers edit it at checkout. The conflict table on this page shows a starting point.
More on WooCommerce and Dynamics
- WooCommerce and Microsoft Dynamics: plugin, connector or custom build?A neutral comparison of the three ways to connect them.
- Business Central, Sales or Finance: how each changes a WooCommerce integrationDifferent APIs, limits and change notifications for each product.
- Syncing WooCommerce orders to Dynamics at high volumeQueues, duplicate protection, throttling and daily reconciliation.
- WordPress forms into Dynamics, without a plugin that almost fitsMapping, validation and retry for enquiries that must not go missing.
- Moving a live WooCommerce store from PHP 7.4 to currentThe order of work on a store that has to keep selling.
- What WooCommerce maintenance should include for a store that can’t go downThe questions to ask any provider, with our own plans compared.
- How often should a WooCommerce store back up?Working out a schedule from your own orders, and testing the restore.
Want this mapped for your store?
Tell us which Dynamics product you run and what should travel in each direction.
We reply within one business day (IST).