A Shopify ERP integration keeps your store and your back office in agreement: the ERP knows about every order, and the store shows the stock and prices the ERP holds. This guide explains what has to sync, who should own each record, the three ways to connect the two systems, where integrations usually break, and what to check before go-live. It applies to any ERP. We have separate guides for NetSuite and Microsoft Dynamics 365 Business Central.
The short answer
- If your ERP vendor ships a Shopify connector and your process is standard, start with the connector.
- If you need several systems connected, or mappings the connector doesn't offer, use an integration platform (middleware).
- If your order flow, pricing or fulfilment is unusual, or volumes are high, build a custom integration on Shopify's GraphQL Admin API and webhooks.
Whichever route you take, the project succeeds or fails on one decision made before any tool is chosen: which system owns each piece of data.
What a Shopify ERP integration syncs
Six flows cover almost every project.
| Flow | Usual direction | Typical trigger |
|---|---|---|
| Products and variants | ERP → Shopify | Scheduled, or when an item changes |
| Inventory by location | ERP → Shopify | Near real time for fast sellers; scheduled for the rest |
| Prices and B2B price lists | ERP → Shopify | Scheduled, or on price change |
| Orders and customers | Shopify → ERP | Webhook when an order is created or paid |
| Fulfilments and tracking | ERP or warehouse → Shopify | When a shipment is confirmed |
| Refunds, returns and payouts | Shopify → ERP | Webhook for refunds; scheduled for payouts |
Not every store needs all six on day one. Orders into the ERP and inventory back to the store are the two that remove the most manual work.
Decide who owns the data first
Most integration bugs come from two systems both editing the same field. Agree the owner of each record with finance and operations, and write it down.
| Data | System of record | Watch for |
|---|---|---|
| SKU, cost, tax class, weight | ERP | Blank or duplicate SKUs in Shopify |
| Titles, descriptions, images, SEO fields | Shopify | The ERP sync overwriting storefront content |
| Stock levels | ERP or warehouse system | Location mapping, and stock reserved for other channels |
| Prices | ERP | Compare-at prices, market prices and B2B catalogs |
| Orders | Shopify | Discounts, taxes and shipping lines mapped to the right accounts |
| Fulfilment status | Whoever ships | Split and partial shipments |
| Refunds | One origin per case | Refund loops between the two systems |
The SKU is usually the key that links a Shopify variant to an ERP item. Audit SKUs before you start: blanks, duplicates, trailing spaces and case differences cause most failed order imports.
Three ways to connect Shopify to an ERP
| Vendor connector | Integration platform | Custom integration | |
|---|---|---|---|
| What it is | An app built by the ERP vendor or a partner | A hosted tool with prebuilt Shopify and ERP steps you configure | Your own service using Shopify's APIs and the ERP's API |
| Best for | Standard order-to-cash on one store | Several systems, or mappings a connector lacks | Unusual processes, high volume, strict control |
| Setup effort | Lowest | Medium | Highest |
| Flexibility | Limited to the connector's settings | Good, within the platform's building blocks | Full |
| Who maintains it | The vendor | You or a partner, on the platform | You or a partner |
| Main risk | You outgrow it | Subscription cost grows with volume and flows | It needs monitoring and an owner |
Examples of vendor connectors are Microsoft's Shopify Connector for Business Central and Oracle's NetSuite Connector. For other ERPs, check whether the vendor or a certified partner publishes one, and read what it does not sync before you commit.
When a connector is enough
One store, one currency or a simple Markets setup, standard products, and an order flow that matches what the connector expects. Test it with your real edge cases: bundles, gift cards, partial refunds, B2B orders and pre-orders.
When middleware fits
You also need to connect a warehouse system, a marketplace or a CRM, or you need rules such as "route orders from this market to that subsidiary". The platform handles retries and logging, and your team can change mappings without a developer.
When custom makes sense
- The order flow has steps no connector models, such as made-to-order items, deposits or split fulfilment across suppliers.
- You sell B2B on Shopify with company-specific price lists and payment terms that live in the ERP.
- Volume is high enough that scheduled batch syncs oversell stock.
- You run several stores against one ERP and need one place that decides what goes where.
- You want the integration in your own repository, with your own tests and monitoring.
How a custom integration works
A reliable custom integration follows the same pattern regardless of the ERP.
- Receive. Shopify sends a webhook when an order is created. The receiver verifies the signature, stores the event and answers quickly.
- Queue. A background worker picks up the stored event. Work never happens inside the webhook request.
- Map. The worker turns the Shopify order into the ERP's sales order format: items by SKU, taxes, discounts, shipping, customer and payment.
- Send once. The worker creates the order in the ERP with an external ID, so a retry can't create a duplicate.
- Reconcile. A scheduled job asks Shopify for recent orders and compares them with what the ERP holds, because webhook delivery isn't guaranteed.
- Write back. Stock, prices, fulfilments and tracking flow from the ERP to Shopify through the GraphQL Admin API.
Step 4 is where duplicates are prevented. This is the shape of it in Node.js, with db and erp standing in for your own database and ERP client:
```js
// Push one Shopify order to the ERP, safely repeatable.
export async function syncOrder(order, { db, erp }) {
const key = shopify-order-${order.id};
const log = await db.syncLog.find(key);
if (log?.status === "done") return log.erpId; // already synced
// The ERP stores the key, so a second attempt returns the same record.
const erpId = log?.erpId ?? (await erp.createSalesOrder(mapOrder(order), { externalId: key }));
await db.syncLog.upsert(key, { status: "done", erpId, syncedAt: new Date() });
return erpId;
}
function mapOrder(order) {
return {
customerEmail: order.email,
currency: order.currency,
lines: order.line_items.map((line) => ({
sku: line.sku,
quantity: line.quantity,
unitPrice: line.price,
})),
};
}
```
Three Shopify facts shape the design:
- Webhooks need a safety net. Shopify's documentation says delivery and ordering aren't guaranteed and duplicates can happen. Our guide to reliable Shopify webhooks has the full handler.
- Use GraphQL. The REST Admin API is legacy, and new work belongs on the GraphQL Admin API. If you have an older integration, see our REST to GraphQL migration guide.
- Plan for limits. The GraphQL Admin API limits requests by calculated query cost. Use bulk operations for large exports such as a full catalogue or a stock reconciliation.
Where Shopify ERP integrations break
- SKU mismatches. Orders fail to import or post against the wrong item.
- Overselling. Stock syncs on a schedule while orders arrive continuously. Shorten the interval for fast sellers, or reserve stock in the ERP when the order arrives.
- Tax and discount mapping. Order totals differ by small amounts between systems. Agree how discounts, shipping and tax-inclusive prices are split per line.
- Refunds and exchanges. Each system starts a refund and both record it. Pick one origin per case.
- Bundles and kits. A bundle sold as one line in Shopify needs to become its components in the ERP.
- Multi-location and multi-currency. Shopify locations and markets need an explicit mapping to ERP warehouses, subsidiaries and currencies.
- Silent failures. A failed sync nobody sees is worse than a visible error. Every failure needs to reach a person.
Go-live checklist
- The data ownership table is signed off by finance and operations.
- SKUs are audited: none blank, none duplicated.
- Every order type has been tested end to end: standard, discounted, gift card, partial refund, exchange, B2B and pre-order.
- Stock is correct per location after a full sync, and after an order and a return.
- A repeated webhook or a retried job does not create a second ERP order.
- A reconciliation job runs on a schedule and reports differences.
- Failed syncs raise an alert with the order number and the reason.
- API credentials are scoped to what the integration needs, and stored outside the code.
- There is a way to re-send one order by hand.
- Historical orders are either imported or deliberately left out, and finance knows which.
- Someone owns the integration after launch.
When you don't need a custom build
If a vendor connector covers your order flow and you sell from one store, use it. A custom integration is worth its upkeep only when the connector's limits cost you real time or real stock errors.
Want help with a Shopify ERP integration?
We build and repair Shopify integrations with ERP, warehouse and accounting systems, and we configure vendor connectors when they are the better fit. Send us your ERP, your order volume and the flows you need on our Shopify API integrations page. If the integration is part of a replatforming, see Shopify migration.
Sources
- Shopify: GraphQL Admin API reference
- Shopify: REST Admin API (legacy status)
- Shopify: About webhooks
- Shopify: API limits
- Shopify: Bulk query operations
- Shopify: API versioning
- Shopify Help Center: B2B on Shopify
- Microsoft Learn: Get started with the Shopify Connector
- Shopify App Store: NetSuite ERP Connector by Oracle NetSuite



