Integrations

Integrating your ERP with your CRM without losing your mind

By Alternetica Team··7 min read

There is a scene that repeats itself in almost every mid-sized Latin American company we have visited: the sales team has its CRM with customer data, the accounting team has its ERP with invoices and payments, and someone is manually copying data between the two systems every Monday. This inefficiency is not inevitable. It is the result of not having designed the integration correctly from the start.

The three enterprise integration patterns

Before talking about tools, we need to understand the fundamental patterns.

Point-to-Point

Each system connects directly with every other. This works for 2–3 systems but becomes an unmaintainable mess with more.

CRM ──────────── ERP
 │               │
 └──── Invoice ──┘

This is what most companies implement first because it seems simplest. The problem appears when you have 5 systems and need 10 direct connections (n*(n-1)/2).

Hub-and-Spoke

A central system (hub) coordinates all integrations. Each system only needs to connect to the hub, not to all the others.

CRM ──┐
      │
ERP ──┼── HUB ── Warehouse
      │
Shop ─┘

This is the right pattern for most mid-sized companies. It reduces complexity from O(n²) to O(n).

ESB (Enterprise Service Bus)

The enterprise version of hub-and-spoke, with additional message transformation, orchestration, and governance capabilities. Appropriate for large corporations with dozens of systems. For mid-sized companies, it is over-engineering.

REST vs Webhooks vs Message Queues

The choice of communication mechanism directly impacts reliability and performance.

REST APIs

The most familiar mechanism. System A calls system B's API and waits for the response. Simple and direct, but it has a fundamental problem: if system B is down when A tries to communicate, the operation fails.

Use it for: data queries where an immediate response is necessary, and when both systems will always be available simultaneously (which is rare in production).

Webhooks

System B calls system A when an event occurs (push notification vs. polling). More efficient than constant polling, but requires the receiving system to always be accessible.

// Webhook receiver endpoint in Node.js
app.post('/webhook/new-customer', async (req, res) => {
  // Respond immediately to avoid timeout from the sender
  res.status(200).json({ received: true })

  // Process asynchronously
  const { customer_id, name, email } = req.body

  try {
    await syncCustomerInERP(customer_id, name, email)
    await logger.info(`Customer ${customer_id} synced`)
  } catch (error) {
    await logger.error(`Error syncing ${customer_id}`, error)
    await queueForRetry(req.body)
  }
})

Message Queues

The most robust solution for critical integrations. Messages are published to a queue (RabbitMQ, SQS, Redis Streams) and processed asynchronously. If the consumer fails, the message remains in the queue for reprocessing.

For critical integrations where losing a single event has financial consequences (payments, invoices, orders), message queues are the standard.

Error handling and idempotency

This is the topic most often ignored and the one that causes the most headaches in production.

The idempotency problem

If your integration system fails halfway through processing a payment, can it process the same payment again without creating a duplicate? If the answer is "I don't know" or "no," you have an idempotency problem.

An operation is idempotent if executing it multiple times produces the same result as executing it once.

// BAD: creates duplicates if called twice
async function createInvoiceInERP(data: InvoiceData) {
  return await erp.invoices.create(data)
}

// GOOD: uses external ID as idempotency key
async function createInvoiceInERP(data: InvoiceData) {
  const existing = await erp.invoices.findByExternalId(data.crm_id)
  if (existing) return existing

  return await erp.invoices.create({
    ...data,
    external_id: data.crm_id  // reference to the source system
  })
}

Retry policy

Not all errors should be retried the same way. 4xx errors (Bad Request, Not Found) generally should not be retried. 5xx errors (Server Error) and network errors should be retried with exponential backoff.

Common ERPs in LATAM and their APIs

Each ERP has its own integration particularities worth knowing:

SAP Business One

It has Service Layer, a well-documented RESTful API. This is the modern way to integrate. Avoid the old DI API approach that requires local installation. Authentication via session token with expiration.

Odoo

Native XML-RPC and JSON-RPC APIs. Very flexible and well-documented. Large community. Our recommendation for companies looking for an integrable open-source ERP.

Siigo (Colombia)

A relatively recent REST API. It allows creating electronic invoices, querying accounts receivable, customers, and products. Requires application registration on its developer portal. Some rate limiting constraints that need to be handled.

World Office / Helisa / Contpaq (Mexico)

Fewer native APIs. Frequently integrated via direct database access or file export/import. Not ideal, but it is the reality of the market.

Recommended middleware tools

n8n (self-hosted): Our first recommendation for companies with a developer available. It can act as a central hub, has integrated logging, and allows handling complex transformations.

Apache Camel: For high-complexity enterprise integrations. Steep learning curve, but enormous power.

Custom middleware (Node.js/Python): For very specific integrations or when performance is critical. More upfront work but maximum control.

The most costly mistakes

Bidirectional sync without origin control: If a customer is updated in both the CRM and the ERP simultaneously, which version wins? Without a clear "system of record" policy, you will create endless conflicts.

No error handling in production: Any integration that has no alerts when it fails will fail silently for weeks without anyone noticing.

Data transformations without validation: Null fields, different date formats, currencies, special character encoding (accents, special characters). In LATAM these problems are especially frequent.

Integrating directly to the database: Accessing the ERP's DB directly instead of its API is fast to implement and a nightmare to maintain. ERP updates break the integration without warning.

Conclusion: a well-built integration is a strategic asset

A well-designed integration architecture, with the correct pattern, robust error handling, and idempotency, can be an engine of operational efficiency for years. An improvised integration becomes technical debt that slows growth.

If you are considering integrating systems in your company or have existing integrations causing problems, at Alternetica we offer integration architecture diagnostics. Contact us and we will review your current situation at no commitment.

Let's talk with no strings attached

Ready to take the next technology step?

Tell us your challenge. In less than 24 hours you'll hear from one of our senior engineers to analyze how we can help you.

No initial commitmentResponse in less than 24 hoursSenior engineers from day one