Integrate ERP

Ask about this Page
Copy for AI
View as Markdown

Replicate master data, financial records, and back-office processes between an enterprise resource planning system and commercetools.

An enterprise resource planning (ERP) system is the system of record for the master data a business runs on: materials, classifications, list prices, stock, accounts, and financial documents. Integrating it with commercetools means replicating the subset of that data your storefront needs, and sending back the transactions the ERP must record.

This guide covers the decisions that shape an ERP integration: which domains the ERP owns, whether to configure a Connector or run the flows through middleware, how to load master data in bulk and keep it current, and how to keep financial data reconcilable between the two systems.

It does not cover the post-order lifecycle. Order status, fulfillment, shipments, and returns belong to Integrate an order management system, which applies whether that system is a dedicated order management system (OMS) or your ERP. It also does not cover the product model itself, which is Integrate product data, or tax calculation, which is Integrate tax.
Before you start, you need a commercetools Project, an ERP with an API or an extract mechanism you can schedule, and an agreed owner for each data domain described in the next section. For the wider planning framework, see Integration planning and patterns.

Assign ERP ownership before you design anything

An ERP integration is not one integration. It is a set of one-way flows that differ in direction, volume, and urgency, and that fail independently. The first task is deciding which flows exist at all.

Decide the system of record per data domain

Treat each ERP domain as a one-way contract. Designate one writer and make the replica read-only. Reject or reconcile changes that originate on the read-only side.

Data domainTypical owner when an ERP is presentDirectionWhere the design lives
Core product data and classificationERPERP to commercetoolsIntegrate product data
Product content and enrichmentPIM, or the ERP when no PIM existsERP to commercetoolsIntegrate product data
List and base PricesERPERP to commercetoolsIntegrate product data
Contract and customer-specific PricesERPERP to commercetoolsThis guide
Inventory quantitiesThe system that owns OrdersUsually ERP to commercetoolsIntegrate an order management system
Customer profilecommercetools, or a CRM or customer data platformVariesIntegrate a CRM
B2B accounts, credit limits, and payment termsERPERP to commercetoolsThis guide
Order capture and contentscommercetoolscommercetools to ERPIntegrate an order management system
Order fulfillment lifecycleOMS, or the ERP when it owns the Order lifecycleERP to commercetoolsIntegrate an order management system
Invoices and financial documentsERPERP to commercetoolsThis guide
Tax rates and calculationTax engine, or the ERPVariesIntegrate tax
Reporting copies of commerce datacommercetools remains the sourcecommercetools to a warehouse or analytics toolIntegrate an analytics destination

The rows this guide owns are the ones no other integration claims: the master data that arrives in bulk, and the financial and account data that has to reconcile. Confirm the remaining rows against the linked guides before you rely on the defaults above.

Answer the questions that change the design

Record the following before choosing a runtime, because each answer moves the architecture:

  • Which domains are actually in scope? An ERP holds far more than a storefront needs. Replicate only what search, display, pricing, checkout, and fulfillment use, and leave the rest in the ERP.
  • What volume, and how often does it change? Core product data changes infrequently, prices change on a schedule, and stock changes constantly. These are different integrations with different cadences, even when they leave the same system.
  • How does the ERP publish changes? A push to an endpoint, a queue, a scheduled extract, or a full file drop. A push maps to a service application. A schedule maps to a job, provided the job orchestrates the work rather than performing bulk file processing inside it.
  • Does the ERP track changes? If it can emit deltas, incremental synchronization is straightforward. If it can only produce full extracts, the integration needs its own change detection or must accept full loads.
  • Which markets, currencies, and locales are in scope? This determines the Price and localization mapping, and whether one extract serves every Store.
  • How much staleness is tolerable per domain? Stock tolerance is usually minutes, price tolerance hours, and material description tolerance a day. These set the schedules and the alerting thresholds.
  • What is the initial load, and when does it run? A first full catalog and account load is a separate project from steady-state synchronization, with different tooling and a different risk profile.
  • What happens when the ERP is unavailable? Decide per flow whether the integration retries, queues, or skips a cycle, and who is told.

Record special requirements

Add ERP-specific constraints that could require custom extraction, transformation, or hosting:

  • B2B account hierarchies modeled as Business Units with approval workflows.
  • Multi-Store or multi-market catalogs that need Product Selections or Product Tailoring.
  • Contract pricing that varies by account, volume tier, or negotiated agreement.
  • Data residency, retention, or audit constraints that restrict where the integration runs.
  • An existing middleware platform or ERP support contract that constrains the runtime.
  • Non-commerce data that the business wants replicated for reporting rather than for the storefront. Exporting commerce data itself for reporting is covered by Integrate an analytics destination.

Choose an integration path

Start with the option that requires your team to build and maintain the least custom ERP integration logic. Move to a custom runtime only when the earlier options cannot meet a recorded requirement.

Check for an existing ERP Connector

Search the current Connector inventory with an API Client that has the view_connectors scope. Filter the Search Connectors endpoint by integration type:
Search for ERP Connectorshttp
GET https://connect.{region}.commercetools.com/connectors/search?integrationTypes=erp&integrationTypes=pim
Query both erp and pim, because a Connector that replicates core product data and price data can be published under either type. For the full list of values, see IntegrationType. For the host to use in each Region, see Hosts and authorization. You can also browse the available Public Connectors in Connect in the Merchant Center.
Treat the technology partner directory and the Public Connector catalog as separate discovery sources. Before planning a Connect deployment, confirm whether a candidate is an installable Connector or a vendor-operated integration. Follow the candidate documentation for its setup and supported flows.

Evaluate the candidate against the recorded data domains, directions, mappings, Regions, locales, and peak volume.

Compare middleware and runtime options

Most ERP integrations need logic beyond the commercetools APIs. This logic extracts data from the ERP, transforms it into commercetools resources, and sends it to commercetools. Choose where to run it based on technology your organization already knows how to deploy, secure, monitor, and support.

OptionChoose it whenWhat you own
ERP-vendor middlewareThe organization already runs the ERP vendor's integration platform and extraction toolingIntegration flows, mapping, and the calls into commercetools
Integration platformSeveral systems need connecting, and available adapters reduce custom connection workIntegration flows, mapping, and connection management
Cloud servicesThe team prefers to use functions, queues, and storage in its existing cloud accountExtraction, transformation, scheduling, retries, and hosting
ConnectThe commercetools-facing logic can run close to the platform, and you want Connect to host and scale itApplication code only; Connect provides hosting, scheduling, and the message broker
Import API called directlyAn existing job already produces well-formed extracts and needs no separate runtimeThe calling job
Merchant Center CSV importVolumes are low, changes are occasional, and business users own the processNothing; there is no integration to run
These options can be combined. For example, ERP-vendor middleware can extract and transform records while a Connect application performs the commercetools writes and schedules reconciliation. For a comparison of the import mechanisms, see Import and export.
Use Connect for the platform-facing part only when the work fits its execution limits. A service request times out after five minutes and has a maximum of 1 CPU and 512 MB. A job request times out after 30 minutes and has a maximum of 2 CPUs and 4 GB. Keep stateful work, bulk file processing, and long-running transformations outside Connect. Review the Connect deployment behavior and when to use an alternative to Connect before choosing it.

When comparing runtimes, check whether each option can process the largest ERP data export you expect within the required synchronization window. Also consider how it protects data while moving between systems, whether your team has the skills to operate it, and its ongoing operating cost in addition to its implementation cost.

Prove that a gap is not configuration

Test the candidate controls for field mapping, locales, currencies, enabled domains, and category mapping before treating an apparent limitation as a code gap.

Fork or build

When a source-available Connector covers the core flow, extend only the ERP behavior that its configuration cannot provide. Deploy the result as an Organization Connector.

If no Connector matches, build one. Use a service application to receive pushed changes, a job application to trigger scheduled loads and reconciliation, and an event application when commercetools changes must flow back. Event applications receive messages at least once without ordering guarantees, and unacknowledged messages are retained for seven days. Make consumers idempotent, tolerate out-of-order delivery, acknowledge only after durable processing, and reconcile records that exceed the retry window.
Keep heavy extraction and transformation outside a job. A job request times out after 30 minutes, and the application type is intended for lightweight recurring tasks. Scaffold each application with the Connect CLI:
Scaffold a Connector and add an applicationbash
commercetools connect init my-erp-connector
commercetools connect application add
Before selecting a CLI template, inspect its generated applications, data direction, and credential model. The Application templates overview describes the documented templates and their intended use cases.

Design the master-data flows

Choose the ingestion API per domain

Use the Import API for the initial load and scheduled refreshes. Use the HTTP API for changes that cannot tolerate asynchronous processing. Integrate product data covers full and incremental uploads, event-driven and bulk flows, the Import API behaviors that shape monitoring and retry, and worked examples for both APIs. Do not repeat that design here; apply it and add the two properties below.
Confirm the current availability of every required Import API surface in the Import API overview.

An ERP load is larger and runs to a schedule, so two further properties shape its design:

  • Import summaries are eventually consistent. Use ImportSummary to confirm a completed run, not for real-time monitoring. For live status, subscribe to Import API Events.
  • Batch by resource count and bytes. An Import Request carries up to 20 resources, its request body cannot exceed 14 megabytes, and each resulting document cannot exceed 16 megabytes. The Import API recommends no more than 300 calls per second per Project. A Project can hold up to 1 000 Import Containers. Keep fewer than 200 000 Import Operations in a container so monitoring stays efficient. See Import API best practices.

Separate the initial load from ongoing synchronization

The first load and steady-state replication are different problems. The initial load is large, ordered, and run once under supervision. Steady-state replication is small, continuous, and unattended. Build them as separate processes even when they share mapping code.

Every terminal Import Operation state other than imported requires explicit handling. Resubmit a rejected resource after the platform retry limit is reached. Correct the source before resubmitting a validationFailed resource. For canceled and partiallyImported, inspect the errors and submit only the work still required.
The Import API retries non-terminal operations. Middleware that resubmits those operations can cause concurrent modification errors, and the processing order of duplicate requests is unspecified. Do not send duplicate import requests concurrently. Follow the documented retry handling.
Monitoring has to finish inside the lifetime of the operations it inspects. Import Operations are deleted 48 hours after creation. An Import Container without a retentionPolicy is removed after 72 hours. Set a TimeToLiveRetentionPolicy when a load needs longer.

Run the initial load against a test Project first, bounded to a small representative sample. Count the resources the run will process before it starts, and treat any full-catalog run as a deliberate decision rather than a default.

Give every resource a key the ERP already owns

Derive the import identity from a stable ERP identifier, such as a material or account number. Never derive it from a name, description, or file position. The Import API upserts most resources by key and Orders by orderNumber; review how resources are created or updated before defining the mapping. Fields such as externalId, sku, and SyncInfo can correlate records but do not replace the import identity.
Orders and Product Variants use different requests for creation and patching. Follow the request matrix in Import API resource creation and updates. For Order correlation, follow Store the OMS identifier on the Order, including its Channel prerequisite.
Set the key when the resource is first created. The Import API cannot set or change the key of a resource that already exists, so a material that was created in commercetools without a key cannot be adopted by a later import: the import creates a second resource instead. To adopt existing data, set the keys first with the relevant Set Key update action in the HTTP API, or with the approach described in Add keys to existing resources and objects.

Sequence the resources the Import API cannot create

Create referenced prerequisites that are outside the supported Import API resources through the HTTP API before the bulk run. Otherwise, the dependent Import Operations remain unresolved until the prerequisite exists or the operation expires.

Two further constraints change how a multi-source integration must be written:

  • Preserve fields owned by other systems. Product imports remove omitted values during an update. Follow the Product import guidance and include every value that must remain on the Product or Product Variant.
  • Define the removal policy outside the Import API. The Import API cannot delete resources. Decide whether an ERP discontinuation unpublishes or deactivates the corresponding commerce resource.

When several systems write to the same Product, one process creates it and each source updates only the fields it owns. Never let a source perform a blind full overwrite.

Schedule batch runs so they do not collide

Distribute recurring ERP loads using the scheduled sync recommendations. Assign each Project or job a stable offset and apply the recommended jitter.

Use scheduled reconciliation extracts to expose master-data drift that delta feeds cannot reveal.

Synchronize financial and back-office data

Align rounding modes before go-live

Agree the Project price and tax rounding configuration with the finance team before go-live. New Carts use the Project defaults, and the default price RoundingMode is HalfEven. A mismatch can create minor-unit differences that prevent financial reconciliation. Test representative ERP totals against the selected modes before the first production Order.

Replicate invoices and financial documents

Keep invoices, credit notes, and overdue-payment collection records in the ERP as the system of record. In this design, commercetools stores only the references and summary fields needed by the storefront or Merchant Center.

Store the invoice number, date, status, and amount in Custom Fields on the corresponding Order. Render the document itself in the ERP or the document system, store it in a location the storefront can reach, and hold that URL in a Custom Field. Do not treat commercetools as the archive, because the ERP retains the record for audit and filing.

Apply the same boundary to an external ledger. Store a reference and display value in commercetools while the ERP retains the balance and liability. If the balance is not replicated, validate any spend limit against the ERP when the value is applied.

Model B2B accounts, credit, and payment terms

When the ERP is the system of record for accounts, replicate the account structure to Business Units and link each one by its key. Map account availability to BusinessUnitStatus instead of a Custom Field. Store ERP-specific credit limits and payment terms in Custom Fields on the Business Unit.
Standalone Prices selected by Customer Group or Channel can represent contract price lists without changing Product data. A Product Variant has a soft limit of 50 000 Standalone Prices, so size the account, Channel, validity, and tier combinations before choosing this model. Confirm the selection model against Integrate product data before building the extract.

When the ERP owns the Order lifecycle

Many organizations run order management inside the ERP rather than in a separate system. The integration is then the same one described in Integrate an order management system: commercetools captures the Order and exports it, and the ERP returns status, fulfillment, shipment, cancellation, return, and Inventory updates.

Apply that guide to the post-order lifecycle and this one to master data. They are separate flows with separate failure modes, and combining them into a single job means a slow nightly catalog run can delay an order status update.

Historical or back-office Orders that never passed through a commercetools Cart can use the Order Import endpoint. It emits an Order Imported Message instead of the Order Created Message emitted by checkout. Cover every enabled creation path in the export Subscription, including OrderCreatedFromRecurringOrderMessage when the Project uses Recurring Orders.
Order Import requires an explicit Order total and accepts negative Prices and quantities. Validate those values against the ERP record before sending the payload. Make the Subscription consumer idempotent and tolerant of duplicate or out-of-order messages. Acknowledge a message only after durable processing, monitor retry exhaustion, and reconcile Orders against the ERP. Review the Subscription delivery guarantees and the retry policy for the selected destination.
If the ERP is also the Inventory owner, decide whether commercetools deducts stock at all before you connect the two, because both systems decrementing the same Order produces drift that reconciliation reports forever. The InventoryMode of the Cart controls the platform-side deduction; see Synchronize Inventory for the full decision.

Secure and operate the integration

Manage credentials and scopes across the middleware boundary

Declare the least-privilege scope set through inheritAs.apiClient.scopes so Connect generates the API Client during installation.
The Import API needs manage_import_containers and the resource scopes that correspond to each Import Container resourceType. Avoid broad legacy scopes such as manage_products when narrower scopes cover the enabled flow. Determine the final set from Import API authorization and API scopes. Classify ERP credentials according to the connect.yaml configuration rules so secrets never appear in standard configuration or logs.

Treat every ERP-facing write route as a privileged public interface. Authenticate processing routes and expose only health checks without authentication. Implement the calling system's documented authentication scheme. If the caller signs the request body, validate the documented header and algorithm instead of assuming a token format.

API Extensions support only specific resources and run synchronously within the commercetools request time budget. These constraints make them unsuitable for ERP master-data round trips. Review the supported resources and time limits before considering an Extension for another flow.

Validate the ERP connection at deploy time

Have the Connector's postDeploy script make a test call to the ERP so invalid credentials surface at deployment instead of during the first load. Decide whether that failure fails the deployment or only warns, and record the decision.
Register the Custom Types, Channels, and any Subscription the integration relies on in the same postDeploy script, and remove them in preUndeploy. Declare both in the scripts block of connect.yaml, because a script file that is not declared never runs. Create each resource when it is absent and update it in place rather than deleting and recreating it, then confirm the resources exist rather than inferring success from the Deployment status. See Connect development and Deployment logs.

Govern who can edit ERP-owned data

Use Attribute Groups as the Merchant Center permission boundary for ERP-owned Attributes. Grant editing access only to the responsible teams. Merchant Center permissions do not restrict API Clients, so keep Product write scopes narrow as well.

Monitor and reconcile

Correlate logs with the ERP record key. Record identifiers and processing decisions without logging customer or account payloads.

Track run freshness, every non-imported terminal state, source and platform count differences, reconciliation lag, and replay outcomes. Document how an operator corrects and replays a failed extract.

Verify the integration

Before the first production run, test the mapping in isolation. A mapping is a pure transformation from an ERP record to a commercetools draft, so it can be tested with fixtures and no credentials. Verify the integration in the product data guide lists the cases that silently corrupt data and the guardrails for a first live run against a test Project. Apply them, and then prove the outcomes that only an ERP integration produces:
  • Every Import Operation for a bounded sample reaches imported rather than rejected, validationFailed, canceled, or partiallyImported.
  • A material discontinued in the ERP produces the agreed outcome rather than remaining sellable.
  • An account blocked in the ERP is rejected through BusinessUnitStatus rather than only being flagged in a Custom Field.
  • An invoice reference written to an Order Custom Field resolves to a retrievable document in the ERP or the document system.
  • An Order placed in commercetools totals the same as the ERP calculates it, including rounding. Orders created through Order Import carry the total the ERP supplied, so check those against the source data instead.
Some expected behavior looks like failure while testing. An Import Operation with resolved references can still enter validationFailed when the data violates a constraint. ImportSummary can lag behind the operation states because it is eventually consistent. An unresolved operation is not an error while its referenced resource is still expected to arrive. Confirm the terminal state before treating these conditions as defects, and clean up test data afterward so a shared Project does not accumulate partial loads.

Apply the design to SAP ERP

This section applies the guidance above to an SAP ERP integration. Verify the interfaces and data formats available in your SAP implementation before using the example mapping.

Map SAP domains to commercetools resources

Start with the commerce outcome each SAP domain must support. Then map the source interface configured for that domain to the corresponding commercetools resource:

SAP domaincommercetools resource
MaterialsProduct and ProductVariant
ClassificationProductType, Attributes, and Product Variant
Prices and conditionsEmbedded Prices or Standalone Prices
Stock levelsInventoryEntry
InvoicesCustom Fields on the Order

Integrate through SAP Cloud Integration

If your organization uses SAP Cloud Integration, configure one integration flow per data domain. Separate flows let you schedule, monitor, and retry each domain independently.
Use the Import API for bulk material and classification flows that tolerate asynchronous processing. Use the HTTP API for time-sensitive stock updates. Send Orders outbound with Subscriptions and apply the idempotency, ordering, retry, and reconciliation controls described earlier.

Use cloud services with SAP Gateway

  1. Expose the approved data. Configure the SAP interface for the domains in scope.
  2. Protect the endpoints. Route the endpoints through an API gateway that applies authentication, authorization, and network controls.
  3. Transform and load the records. Convert the source payloads to JSON in a function or container. Use the Import API for bulk domains and the HTTP API for time-sensitive domains. Handle retries, timeouts, and errors in this layer.

Troubleshoot observable symptoms

Match the symptom you observe to its likely cause and resolution. Symptoms that apply to any catalog import, such as a duplicate created by a missing key or fields blanked by an import that omitted them, are in Troubleshoot observable symptoms in the product data guide.
SymptomLikely causesChecks and resolution
Import operations stay unresolved and eventually expireThe referenced Tax Category, Channel, State, or Shipping Method does not exist, and the Import API cannot import itCreate the prerequisite through the HTTP API, then resubmit
Monitoring shows operations still processing after the run finishedImport summaries are eventually consistentConfirm the individual Import Operation states, or subscribe to Import API Events instead of polling
Some resources never arrive, and no retry ever fixes themThe operations are in validationFailed, which the Import API does not retry and resubmitting the same data cannot resolveRead the errors field, correct the source record, and send it as a new import
Concurrent modification errors occur during a loadMiddleware resubmitted operations that the Import API was already retrying, or sent duplicate requests whose processing order was unspecifiedResubmit only rejected operations and never send duplicate import requests concurrently
The nightly load is slow only at exactly midnightScheduled jobs across many Projects start at the same timeApply the scheduled sync offset and jitter recommendations
Order totals differ from the ERP by minor unitsThe price or tax rounding mode does not match the ERPAlign both rounding modes with the ERP and repeat the reconciliation test
An account blocked in the ERP can still place OrdersThe ERP status was replicated to a Custom Field instead of BusinessUnitStatusMap account availability to BusinessUnitStatus and confirm the native status behavior
An ERP webhook is rejected as unauthenticatedThe endpoint expects a different authentication scheme from the one the caller usesImplement the authentication scheme documented by the calling system
Replicated values keep drifting back to older dataA Merchant Center user is editing ERP-owned AttributesGroup them in an Attribute Group and restrict editing permission to the appropriate teams
Stock is deducted twice for the same OrderBoth the ERP and commercetools decrement it, because the Cart InventoryMode is not NoneSet the mode to None, or subtract the platform-side deduction in the mapping