How to connect ERP, ecommerce, and payments with REST APIs that hold up

How to connect ERP, ecommerce, and payments with REST APIs that hold up

Updated: 13 min read
  • api
  • rest
  • integrations
  • erp
  • webhooks
  • laravel

When the online store, the ERP, and the payment gateway speak different languages, the business feels it: duplicate orders, stale stock, or charges nobody can explain. The problem is not “missing an endpoint”; it is missing a clear contract between systems.

This article explains how to design REST APIs for server-to-server integrations — with plain-language analogies, concrete steps, and the technical detail a team needs to build without accumulating debt. It applies to ERPs, ecommerce, and gateways such as Yappy, BAC, or Paguelo Fácil.

Why it matters for the business

A fragile integration behaves like a phone with a bad signal: sometimes the message arrives, sometimes it duplicates, sometimes it vanishes. Every failure costs support time, manual accounting, and customer trust.

  • Orders: the customer paid, but the ERP does not see it → shipping delays.
  • Inventory: you sell what is gone → cancellations and reputation damage.
  • Payments: two charges for one attempt → complaints and chargebacks.
  • Support: without a shared ID across systems, nobody knows what failed.

Key concepts (plain and technical)

Think of the API as a bank teller window: there is a form (request), a signed reply (response), and rules so the same document is never charged twice (idempotency).

  • Contract: what is sent, what is received, and which errors exist. Technically: OpenAPI with examples.
  • Idempotency: retrying does not duplicate. Technically: Idempotency-Key header on creation POSTs.
  • Versioning: major changes do not break old clients. Technically: /v1/ vs /v2/.
  • Least-privilege auth: each system can only do what it needs. Technically: API keys with scopes.
  • Correlation ID: a tracking number that travels across systems. Makes support and logs usable.

Recommended resource structure

Common pattern for ecommerce + ERP + payments:

ResourceMethodsPurpose
/v1/ordersPOST, GETCreate and query orders
/v1/orders/{id}/statusPATCHUpdate status with business rules
/v1/products/syncPOSTSync catalog from the ERP
/v1/webhooks/paymentPOSTReceive gateway confirmation
/v1/inventory/{sku}GETQuery real-time stock

Practical guide: from zero to a stable integration

1. Server-to-server authentication

  • API keys with minimal scopes (stock read-only, orders write-only).
  • HMAC on webhooks: the receiver validates the signature with a shared secret.
  • OAuth2 client credentials when the provider requires it (SAP, some cloud ERPs).
  • Documented rotation; never keys in repos, query strings, or Docker images.

2. Webhooks vs polling

A webhook is a notice: “payment confirmed”. The sender calls; the receiver validates the signature, stores the event, and responds 200. Prefer this for business events.

Polling means asking on a schedule: “any news yet?”. Use it only as a fallback or when the external system does not support callbacks. Always with exponential backoff and a retry limit.

3. Predictable errors

A consistent response lets the other system decide: retry, alert, or abort?


            {
  "error": {
    "code": "ORDER_NOT_FOUND",
    "message": "Order 12345 does not exist",
    "correlation_id": "abc-123"
  }
}
          
  • Clear HTTP codes: 400 (invalid input), 401 (auth), 404 (not found), 409 (conflict/idempotency), 429 (rate limit), 500 (internal error).
  • Never expose stack traces or SQL in production.
  • Include correlation_id in header and body for cross-system support.

4. When the ERP is down

  1. Ecommerce creates the order locally with pending_sync status.
  2. A queued job tries to sync with retries and backoff.
  3. If it fails after N attempts, it goes to a dead-letter queue and alerts the team.
  4. The customer already saw confirmation; synchronization is reconciled later.

Common mistakes

  • Designing “one endpoint per screen” without a stable resource model.
  • Marking orders as paid only because the user hit a success URL.
  • Retrying POST without idempotency and duplicating charges or orders.
  • Changing the /v1/ contract without notice (silent breaking change).
  • Logs without a correlation ID: blind support across systems.
  • Shared “do everything” credentials instead of minimal scopes.

Integration checklist

  1. OpenAPI contract with request/response and error examples.
  2. Authentication with minimal scopes and key rotation.
  3. Idempotency on creation POSTs (Idempotency-Key).
  4. Webhooks with HMAC validation and sender retries.
  5. Queues for async sync with dead-letter.
  6. Logs with correlation ID, no PII or secrets.
  7. Rate limiting on public endpoints.
  8. Separate sandbox and production, with distinct credentials.
  9. Deprecation policy (e.g. 90 days) before removing an endpoint.
  10. Contract tests between consumer and provider when multiple teams are involved.

Connect with integrations, payments in Panama, and API protection .

Frequently asked questions

REST or GraphQL for ERP integrations?

For B2B integrations and payment gateways, REST is usually more predictable and easier to operate. GraphQL fits better when the consumer is your own frontend with highly variable queries.

How do you version without breaking anyone?

Use a version in the URL or header (`/v1/`), publish OpenAPI, and give dated notice before removing anything. Breaking changes go to `/v2/`; they are not “fixed” silently.

When webhooks and when polling?

Webhooks for business events (payment confirmed, stock updated). Polling only as a fallback or if the external system does not support callbacks. Both need retries and idempotency.

How do you authenticate system to system?

API keys with minimal scopes, HMAC on webhooks, and OAuth2 client credentials when the provider requires it. Never credentials in query strings or the repository.

What if the ERP does not respond?

Do not block the purchase: save the order, enqueue sync, use a dead-letter queue, and alert. The customer gets confirmation; backoffice reconciles later.