ml-connector
AcumaticaShopify

Acumatica and Shopify integration

Acumatica Cloud ERP runs financials, distribution, and inventory. Shopify runs the online storefront and its order, payment, and customer flow. Connecting the two means each web order, the payment captured against it, and refunds post into Acumatica as AR sales invoices and payments without re-keying, while the customer and item masters stay in agreement. ml-connector handles the very different APIs on each side and moves the data on a schedule you control. Because Shopify has no GL chart of accounts, the general ledger stays in Acumatica where it belongs.

How Acumatica works

Acumatica Cloud ERP exposes customers, sales invoices, payments, stock and non-stock items, GL accounts, and journal transactions through its contract-based REST API. Every URL is version-locked to the customer's ERP release, for example 24.200.001, and a mismatched version returns HTTP 404. It authenticates with OAuth 2.0 through the built-in identity server, or with legacy cookie sessions that expire after about 20 minutes of inactivity. All field values in request and response bodies are wrapped in value objects. Acumatica can push changes via Push Notifications using a shared-secret header rather than a signed payload, but the common and reliable pattern is polling on LastModifiedDateTime.

How Shopify works

Shopify exposes orders, customers, transactions, Shopify Payments payouts, products, inventory, draft orders, and refunds through its GraphQL Admin API at a date-based version such as 2026-04. It authenticates with OAuth 2.0 authorization code grant, issuing an offline access token that begins with shpat_ and does not expire for server-side use. Reads page with cursor-based connections capped at 250 records per request, with bulk operations for large historical exports. Shopify pushes events such as orders/create, orders/paid, and refunds by webhook, signed with HMAC-SHA256. Shopify is not an ERP: it has no GL chart of accounts, no AP or AR ledger, and no native vendor or purchase order object.

What moves between them

The main flow runs from Shopify into Acumatica. ml-connector reads Shopify orders, the payment transactions captured against them, and refunds, and posts them into Acumatica as AR sales invoices and payments, each mapped to the matching Acumatica customer, item, and GL account. Customer records flow the same direction so the Acumatica customer master reflects storefront buyers. Product and SKU references are aligned so each order line resolves to a real Acumatica inventory ID. GL postings stay in Acumatica, since Shopify has no GL resource, so ml-connector never writes ledger entries back to the store. Cadence is webhook-triggered for new and paid orders, with a scheduled poll as catch-up.

How ml-connector handles it

ml-connector stores both credential sets encrypted. On the Shopify side it sends the offline access token in the X-Shopify-Access-Token header on every GraphQL call and scopes each request to the one myshopify store. On the Acumatica side it requests and refreshes an OAuth 2.0 bearer token, or maintains a cookie session and calls logout so orphaned sessions do not consume the concurrent-user license, and it pins the version-locked endpoint URL per customer so a release upgrade does not silently 404. Shopify orders/create, orders/paid, and refunds webhooks are verified by HMAC-SHA256 and used as triggers, while a scheduled poll on LastModifiedDateTime backfills anything a webhook missed, since Acumatica push notifications are not guaranteed. Items and customers are mapped first so every invoice line references an existing Acumatica inventory ID and customer. Shopify has no idempotency key and Acumatica has none either, so ml-connector dedupes on the Shopify order GID plus a BullMQ jobId before it posts, and wraps every Acumatica field value in the required value object to avoid HTTP 400. Acumatica rate limits return HTTP 429 once the per-minute count crosses the license threshold, so ml-connector backs off with jitter, and every record carries a full audit trail and can be replayed if a downstream post fails.

A real-world example

A mid-sized consumer goods maker with about 120 staff runs Acumatica Cloud ERP for inventory, distribution, and finance, and sells direct to shoppers through a Shopify store. Before the integration, a clerk exported the day's Shopify orders to a spreadsheet and keyed each one into Acumatica as a sales invoice, which meant orders lagged by hours, SKUs were sometimes mistyped, and the receivables in the ledger never matched the storefront totals at month-end. With Acumatica and Shopify connected, each order and its captured payment post into Acumatica within the webhook and polling window, allocated to the correct customer and inventory ID, and refunds post as credit adjustments. Orders are recognized sooner, the keying errors are gone, and the AR accounts reconcile without a month-end scramble.

What you can do

  • Post Shopify orders and captured payments into Acumatica as AR sales invoices and payments.
  • Map Shopify SKUs to Acumatica inventory IDs so every invoice line lands on a real item.
  • Keep the Acumatica customer master aligned with Shopify storefront buyers.
  • Authenticate Shopify with an OAuth offline token and Acumatica with OAuth 2.0 or a cookie session against its version-locked URL.
  • Trigger on Shopify HMAC-verified webhooks with order GID and jobId dedup, retries, and a full audit trail on every record.

Questions

Which direction does data move between Acumatica and Shopify?
The main flow is Shopify into Acumatica. Orders, captured payments, refunds, and customer records move from Shopify into Acumatica as AR sales invoices, payments, and customer master records, while item and SKU references are aligned so order lines resolve to real inventory IDs. Shopify has no GL chart of accounts, so the general ledger stays in Acumatica and ml-connector never writes ledger entries back to the store.
Does the integration use Shopify webhooks or polling for Acumatica?
Both. Shopify orders/create, orders/paid, and refunds webhooks are verified by HMAC-SHA256 and used as triggers so new activity posts quickly. A scheduled poll on Acumatica's LastModifiedDateTime runs as a catch-up, because Acumatica push notifications retry but are not guaranteed, so polling backfills any missed event.
How does the integration handle Acumatica's version-locked URL and field wrapping?
ml-connector pins the version-locked endpoint URL per customer, for example 24.200.001, because a mismatched version returns HTTP 404 against the running instance. It also wraps every field value in the required value object that Acumatica expects, since sending flat key-value pairs returns HTTP 400, and it dedupes on the Shopify order GID and a jobId before posting to avoid double-booking a re-read order.

Related integrations

Connect Acumatica and Shopify

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

Get started