ml-connector
AcumaticaWooCommerce

Acumatica and WooCommerce integration

Acumatica Cloud ERP runs finance, distribution, and inventory. WooCommerce runs the online store on the merchant's own WordPress site, where orders are placed. Connecting the two keeps the webstore and the back office in agreement without re-keying. Paid WooCommerce orders, refunds, and shoppers land in Acumatica as AR sales invoices and customers, while Acumatica product price and stock changes flow out to the WooCommerce catalog. ml-connector handles the very different APIs on each side and moves records on the cadence you set.

How Acumatica works

Acumatica Cloud ERP exposes Customer, SalesInvoice, Payment, JournalTransaction, StockItem, and NonStockItem records through its Contract-Based REST API. The base URL is tenant-specific and version-locked: the endpoint version in the path, such as 24.200.001, must exactly match the customer's ERP release or the call returns 404. Auth is OAuth 2.0 against the instance identity server, with legacy cookie sessions also supported. Acumatica can push change events through its Push Notifications system, but those use a shared-secret header rather than a signed payload and are not guaranteed, so polling on LastModifiedDateTime with $top and $skip offset paging is the common pattern.

How WooCommerce works

WooCommerce is an open-source WordPress plugin with no hosted instance, so the API base URL is the merchant's own domain at /wp-json/wc/v3/. It exposes orders, refunds, customers, products, taxes, and coupons over REST, plus read-only sales reports. Auth is a per-user Consumer Key and Consumer Secret pair, sent as HTTP Basic credentials over HTTPS. WooCommerce pushes webhooks for order, customer, and product events, each signed with a base64 HMAC-SHA256 value in the X-WC-Webhook-Signature header, and a webhook is auto-disabled after five consecutive delivery failures. WooCommerce has no vendor, purchase order, or GL account resource, so the accounting structure stays on the Acumatica side.

What moves between them

The primary flow runs from WooCommerce into Acumatica. As orders are placed and paid, ml-connector reads the order, its line items, and any refunds and creates the matching AR sales invoice in Acumatica, creating or updating the customer first so each document links to a valid account. The reverse flow runs from Acumatica to WooCommerce: stock item price and inventory level changes update the corresponding WooCommerce catalog products by SKU. Order capture is event-driven on WooCommerce webhooks with a scheduled poll as a catch-up, and catalog pushes run on the schedule you set. Because WooCommerce has no GL resource, ml-connector never writes ledger entries back to the store.

How ml-connector handles it

ml-connector stores both credential sets encrypted, sends the WooCommerce Consumer Key and Secret as HTTP Basic credentials on every store call, and runs the Acumatica OAuth flow against the customer's instance, refreshing the bearer token when a call returns 401. It pins the exact Acumatica endpoint version per customer so the version-locked URL resolves, and wraps every field value as {"value": ...} the way the Contract-Based REST API requires. WooCommerce order webhooks are verified against the X-WC-Webhook-Signature HMAC before processing, and SKUs are matched to Acumatica InventoryID so catalog and order lines land on the right items. Neither API has a native idempotency key, so ml-connector dedupes on the WooCommerce order id and a BullMQ jobId before posting, which avoids double-booking a re-read order. WooCommerce disables a webhook after five consecutive failures, so a health check re-registers it, and a scheduled poll on LastModifiedDateTime backfills anything a missed push dropped. Acumatica returns HTTP 429 once the per-minute request count crosses its licensed threshold, so ml-connector backs off with jitter, and on shared hosts that strip the Authorization header it falls back to the query-string credential form. Every record carries a full audit trail and can be replayed if a downstream call fails.

A real-world example

A mid-sized consumer goods seller with roughly 60 staff runs an online store on WooCommerce and uses Acumatica Cloud ERP for inventory, AR, and finance. Before the integration, a clerk exported each day's web orders from WooCommerce and re-typed them into Acumatica as invoices, mistyped SKUs and customer details caused billing and picking errors, and the storefront showed stock the warehouse had already sold. With Acumatica and WooCommerce connected, paid orders post into Acumatica within minutes as AR sales invoices against matched customers, refunds post as credit notes, and Acumatica inventory levels push back to the catalog so the store stops overselling. The manual entry step is gone and the two systems stay reconciled through the day.

What you can do

  • Create Acumatica AR sales invoices from paid WooCommerce orders, with the customer matched or created first.
  • Post WooCommerce refunds against the right Acumatica documents as credit notes.
  • Push Acumatica stock item price and inventory updates to WooCommerce catalog products by SKU.
  • Bridge the WooCommerce Consumer Key and Acumatica OAuth, pinning the exact version-locked endpoint URL.
  • Capture orders on WooCommerce HMAC-signed webhooks with a scheduled LastModifiedDateTime poll as catch-up, plus retries and a full audit trail.

Questions

Which direction does data move between Acumatica and WooCommerce?
Orders, refunds, and shoppers move from WooCommerce into Acumatica as AR sales invoices and customers. Product price and inventory move the other way, from Acumatica out to the WooCommerce catalog. WooCommerce has no GL account resource, so the general ledger stays in Acumatica and ml-connector never writes ledger entries back to the store.
How does the integration deal with Acumatica's version-locked endpoint and field wrapping?
ml-connector accepts the customer's instance URL and exact endpoint version, such as 24.200.001, and pins it on every call so the version-locked path resolves instead of returning 404. It also wraps each field value as a {"value": ...} object, which the Contract-Based REST API requires; flat key-value pairs would be rejected with a 400. Both are handled automatically from the stored configuration.
Does the integration rely on WooCommerce webhooks, and what if one is missed?
Yes. WooCommerce pushes HMAC-SHA256 signed webhooks for order, customer, and product events, which ml-connector verifies against the X-WC-Webhook-Signature header before acting on them. Because WooCommerce disables a webhook after five consecutive delivery failures, a health check re-registers it and a scheduled poll on LastModifiedDateTime backfills anything a missed push dropped, so no paid order is lost.

Related integrations

Connect Acumatica and WooCommerce

Free to use. Add your credentials, ping your real systems, and see if we fit.

Get started