Home/Insights/Integration
Integration

API-First ERP Integration: Patterns for Connecting Custom Applications to Your ERP

By EnterTech · September 29, 2026 · 7 min read

Almost every custom business application eventually needs to talk to the ERP. Orders created in a customer portal need to become sales orders. Stock levels need to flow back to the storefront. Invoices, customers, products and prices move in both directions. Done well, this integration is invisible. Done badly, it becomes the most fragile part of the estate: nightly jobs that fail silently, duplicate orders after a retry, and custom code so entangled with the ERP's data model that every ERP upgrade becomes a project.

This guide sets out an API-first approach to ERP integration for custom applications: define your own contract, isolate the ERP behind an adapter, publish changes reliably, process them idempotently, and respect the ERP's limits. The patterns are vendor-neutral; where we cite specifics, we use Microsoft's public architecture and platform documentation as a worked example.

Why ERP integration is different

An ERP is usually the system of record for finance, inventory and fulfilment. That brings constraints that ordinary service-to-service integration does not have:

  • Strict validation. ERPs enforce accounting rules, master data and posting periods; a record that is valid in your application may be rejected.
  • Customisation. Most ERP instances are configured and extended, so the data model is specific to your organisation.
  • Throughput limits. Cloud ERPs and business platforms protect themselves with rate and concurrency limits.
  • Upgrade cycles. Vendor upgrades can change APIs, fields and behaviour on a schedule you do not control.
  • High cost of duplicates. A duplicated sales order or payment is not a cosmetic bug; it has financial and customer consequences.

Principle 1: Your applications talk to your API, not the ERP's

"API-first" in this context means that you define the integration contract your applications depend on — resources such as Order, Customer and StockLevel, in your own business language — before writing any ERP-specific code. Describe it in a machine-readable specification such as OpenAPI for synchronous endpoints, and document event schemas for asynchronous messages.

Your portal, mobile app and internal tools then depend only on that contract. The ERP becomes an implementation detail behind it. This has three practical benefits: application teams can build against a stable interface (and a mock) without ERP access; ERP-specific complexity is concentrated in one place; and replacing or upgrading the ERP does not ripple through every application.

Principle 2: Put an anti-corruption layer in front of the ERP

The component that implements your contract against the ERP is an anti-corruption layer. Microsoft's Anti-Corruption Layer pattern describes it as a facade or adapter between subsystems that don't share the same semantics, translating requests so that dependencies on outside systems don't limit an application's design. The pattern was first described by Eric Evans in Domain-Driven Design.

In ERP terms, the layer maps your Order to the ERP's sales-order structure, translates codes and units, applies defaults the ERP requires, and turns ERP-specific errors into meaningful responses. Microsoft's guidance also lists the trade-offs, which are worth planning for up front:

  • It adds latency and is another service to manage, scale and monitor.
  • Transaction and data consistency need to be maintained and monitored across the boundary.
  • Because it sits between systems with different trust levels, it is the right place to enforce input validation.
  • Observability — correlation IDs and structured logging — is needed to diagnose translation failures.
  • It should focus on translation; avoid putting business rules or orchestration in it.

The same pattern is useful when you are gradually replacing a legacy system and old and new must coexist for a time; see our guide to choosing a cloud migration strategy for custom applications.

Principle 3: Choose synchronous or asynchronous per interaction

Not every exchange with the ERP should work the same way. A useful rule of thumb:

  • Synchronous reads for information a user needs immediately, such as price or availability, ideally served from a cache or replica maintained by the integration layer rather than hitting the ERP on every page view.
  • Asynchronous writes for business transactions such as orders, returns and customer updates. The application records the transaction, acknowledges the user, and the integration layer delivers it to the ERP, retrying if the ERP is busy or unavailable.
  • Events out of the ERP (or change polling where events are not available) for updates such as shipment confirmations and stock changes.

Asynchronous writes decouple your application's availability from the ERP's. If the ERP is down for maintenance, the portal can keep taking orders.

Principle 4: Publish changes reliably with a transactional outbox

A common failure mode: the application saves an order to its database, then tries to publish an "order created" message, and the publish fails. Now the order exists locally but the ERP will never hear about it. Microsoft's guide to the Transactional Outbox pattern describes this exact problem and the fix: save the business object and its event in the same database transaction, in an outbox table, and have a separate worker publish outbox entries to the message broker and mark them as processed.

The guidance notes that preserving event order matters (an "order created" event must be published before "order updated"), and that because a relay may resend after a failure, downstream consumers need to handle duplicates. Which brings us to the next principle.

Principle 5: Make the ERP-facing consumer idempotent

Most message brokers deliver at least once, so the integration layer will occasionally receive the same message twice. Microsoft's Idempotent Consumer pattern recommends deduplicating on a stable key and recording that key atomically with the business change. For ERP integration, this translates into a few concrete rules:

  • Carry a business key end to end — for example, the portal's order number — and store it on the ERP document in a reference field.
  • Check before create, and where the ERP supports it, use an upsert or alternate-key lookup so a repeated message updates rather than duplicates.
  • Record in-progress and completed states in the integration layer for calls that cannot be part of a local transaction, so a redelivered message after a crash triggers reconciliation instead of a blind resend.
  • Send mismatches to a dead-letter queue with an alert when a key repeats with different content, rather than silently discarding or overwriting.

Principle 6: Respect the ERP's limits

Cloud business platforms protect shared capacity with service protection limits, and integrations are the clients most likely to hit them. Microsoft Dataverse is a well-documented example. Its service protection API limits documentation explains that when limits are exceeded, the Web API returns 429 Too Many Requests with a Retry-After header indicating how long to wait. Limits are evaluated per user across three dimensions — number of requests, combined execution time and concurrent requests — with default values per web server of 6,000 requests and 20 minutes of combined execution time within a five-minute sliding window, and 52 or more concurrent requests. Microsoft notes these values can change and vary between environments.

The same documentation offers guidance that generalises well to any ERP API:

  • Let the server tell you how much it can handle. Increase request rate gradually and use the Retry-After value, rather than hard-coding a rate.
  • Be careful with large batches. Batching reduces request count but increases execution time per request, so it can trade one limit for another.
  • Move toward real-time integration. Large nightly or monthly jobs that push big volumes in a short window are the most likely to be throttled; spreading work out reduces the impact of limits.

Throttling behaviour also affects cost and capacity planning on your side of the integration; our FinOps basics guide covers how to make that visible.

Principle 7: Decide who owns each piece of data

Many integration problems are really ownership problems. For each entity and, where necessary, each field, decide which system is the system of record:

  • Customer legal and credit data may belong to the ERP; marketing preferences may belong to the CRM or portal.
  • Prices and stock are typically mastered in the ERP and replicated outward.
  • Orders originate in the channel application and become ERP documents once accepted.

Avoid two-way synchronisation of the same field between systems. It invites update loops and conflicting edits. If a field must be editable in two places, route edits through the owning system's API.

Principle 8: Plan for errors, reconciliation and change

  • Dead-letter and alert. Messages that fail validation go to a dead-letter queue with enough context for a business user to fix the data.
  • Reconcile regularly. A scheduled report comparing orders in the portal with sales orders in the ERP catches anything that slipped through.
  • Trace end to end. Use correlation IDs from the originating request through the outbox, broker, integration layer and ERP reference fields.
  • Version your contract. Changes to your own API follow a versioning policy; ERP upgrades are absorbed inside the anti-corruption layer and regression-tested against recorded payloads.

Summary

  • Define your own integration contract first; keep the ERP behind it.
  • Implement the contract in an anti-corruption layer focused on translation.
  • Use asynchronous writes and a transactional outbox so no business event is lost.
  • Make the ERP-facing consumer idempotent using business keys.
  • Design for the ERP's rate and concurrency limits; honour Retry-After.
  • Assign a system of record for every entity and avoid two-way field sync.

If you are connecting custom applications to an ERP or rebuilding an integration that has become fragile, our API and integration services team can help. Contact us to talk through your landscape.

Frequently asked questions

Should we use the ERP vendor's integration platform or build our own layer?

Either can host the anti-corruption layer. What matters is that your applications depend on your contract, not on ERP-specific structures, and that translation logic lives in one place with proper monitoring.

Is a nightly batch integration always wrong?

No, but large batch windows are more exposed to throttling and delay feedback on errors until the next morning. Microsoft's Dataverse guidance recommends moving toward real-time integration where large periodic jobs cause limit problems.

How do we stop duplicate orders in the ERP?

Carry a stable business key from the originating application, store it on the ERP document, deduplicate on it in the integration layer, and use upserts or alternate-key lookups where the ERP supports them.

Planning a Migration or Integration?

Tell us what you're trying to solve. We'll help you choose the right approach for your applications.

Contact Us →