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-Keyheader 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:
| Resource | Methods | Purpose |
|---|---|---|
/v1/orders | POST, GET | Create and query orders |
/v1/orders/{id}/status | PATCH | Update status with business rules |
/v1/products/sync | POST | Sync catalog from the ERP |
/v1/webhooks/payment | POST | Receive gateway confirmation |
/v1/inventory/{sku} | GET | Query 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_idin header and body for cross-system support.
4. When the ERP is down
- Ecommerce creates the order locally with
pending_syncstatus. - A queued job tries to sync with retries and backoff.
- If it fails after N attempts, it goes to a dead-letter queue and alerts the team.
- 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
- OpenAPI contract with request/response and error examples.
- Authentication with minimal scopes and key rotation.
- Idempotency on creation POSTs (
Idempotency-Key). - Webhooks with HMAC validation and sender retries.
- Queues for async sync with dead-letter.
- Logs with correlation ID, no PII or secrets.
- Rate limiting on public endpoints.
- Separate sandbox and production, with distinct credentials.
- Deprecation policy (e.g. 90 days) before removing an endpoint.
- Contract tests between consumer and provider when multiple teams are involved.
Connect with integrations, payments in Panama, and API protection .