Skip to content

How to Design API and System Integration: A Reliable Order-to-Accounting Flow

Reliable integration across a B2B portal, ERP, WMS, and accounting: API contracts, data ownership, idempotency, outbox, retries, security, observability, and reconciliation.

· TankDev Mühendislik

API integration lets two applications exchange data; system integration ensures that the exchange produces a reliable business outcome. A 200 OK response to an order request does not prove that inventory was reserved, fulfilment was scheduled, or an invoice was recorded. Ownership, sequence, and failure behaviour require explicit design.

This article uses a concrete B2B scenario: a customer submits an order in a portal; an ERP validates pricing and commercial terms; a warehouse management system (WMS) reserves stock; accounting records the invoice; and the CRM reads customer-facing status. The technology can change between REST APIs, messaging, and iPaaS. Data ownership and failure semantics do not.

1. The boundary between API integration and system integration

API integration covers the technical contract: authentication, request and response schemas, status codes, timeouts, and versioning. System integration adds the authoritative data source, workflow states, consistency target, replay policy, manual intervention, and audit trail.

The same API contract can support very different levels of operational reliability.
QuestionAPI integrationSystem integration
What moves?JSON fields and filesBusiness events such as orders, reservations, and invoices
What is success?A valid protocol responseThe correct business result in authoritative systems
Where is failure resolved?Client or endpointQueue, reconciliation, operations, and source system
How is it verified?Contract and integration testsEnd-to-end acceptance, data, and recovery tests

This distinction matters when buying a connector. A prebuilt SaaS connector proves that a connection is possible. You still need to inspect its field coverage, deletion semantics, rate limits, historical migration, error queue, and recovery controls against the real workflow.

2. Assign an owner to every fact

A customer name can appear in CRM, ERP, and the portal. Allowing every system to edit it creates conflicts. Define one write authority for each fact and how every other system consumes it. Replicated data may be unavoidable; ownerless data is not.

Illustrative ownership matrix; actual boundaries depend on the ERP and operating model.
DataAuthoritative systemBehaviour elsewhere
Customer and tax identityERPCRM and portal hold read-only projections
Sales opportunityCRMERP receives the winning opportunity reference
Account-specific priceERP pricing enginePortal displays it; server revalidates totals
Physical inventoryWMSERP holds balance; portal shows available-to-promise
Invoice numberAccountingERP and portal retain a reference
Integration statusIntegration serviceOperations sees attempts and failure history

Ownership may be field-specific. CRM might propose a delivery address while ERP owns tax identity. ‘Who owns the customer?’ is then too broad; document which field changes, from which event, and in which direction.

3. Model a state machine, not a chain of HTTP calls

Define explicit states such as draft → submitted → accepted → fulfilment_pending → invoiced. A single integration_failed state is too coarse: a retryable network error, a business rejection, and an ambiguous write require different actions.

  • submitted: The portal durably accepted the order; ERP has not accepted it yet.
  • accepted: ERP returned its order number, linked to the local record.
  • fulfilment_pending: WMS has not completed reservation.
  • verification_required: A remote write timed out; its outcome is unknown.
  • rejected: Pricing, permission, or data rules will not be fixed by retrying.

Customers do not need to see ‘API returned 504’. They need ‘We received the order and are verifying the ERP record.’ Operations needs the technical code, last attempt, correlation identifiers, and accountable owner.

4. Define more than a sample request

An API contract includes required fields, money and time formats, null semantics, pagination, error bodies, rate limits, idempotency, webhook signatures, supported versions, and retirement dates. The OpenAPI Specification provides a language-independent interface description that people and tools can understand.

http
POST /v1/orders HTTP/1.1
Authorization: Bearer <access-token>
Idempotency-Key: ord-01J7YQ4X8T2M
traceparent: 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01
Content-Type: application/json

{
  "external_order_id": "B2B-2026-004817",
  "account_id": "AC-1042",
  "currency": "TRY",
  "lines": [
    {"sku": "P-8841", "quantity": "12.000", "unit": "EA"}
  ],
  "expected_price_version": 34
}

external_order_id is the business reference; Idempotency-Key identifies a safely repeatable logical write; and traceparent carries distributed tracing context. The expected price version prevents the server from silently accepting an order under terms different from those the user reviewed.

A different error JSON for every endpoint makes consumers brittle. RFC 9457 Problem Details defines a machine-readable model using type, title, status, detail, and instance.

json
HTTP/1.1 409 Conflict
Content-Type: application/problem+json

{
  "type": "https://api.example.com/problems/price-version-conflict",
  "title": "Price version changed",
  "status": 409,
  "detail": "Expected version 34; current version is 35.",
  "instance": "/integration-attempts/ia_98315",
  "current_price_version": 35
}

5. Separate synchronous and asynchronous work by business need

The portal can create a durable local order synchronously when the customer needs an immediate reference. Waiting for ERP, WMS, and accounting in one HTTP request transfers the slowest dependency's latency and outage to the user. Separating local acceptance from chain completion is usually more resilient.

  • Synchronous: identity, authorization, mandatory validation, and local order creation.
  • Asynchronous: ERP transfer, stock reservation, invoicing, and external notification.
  • Customer result: business identifier, current state, and status URL.
  • Operations result: attempt count, failure class, and a safe intervention action for every stage.

6. Idempotency is more than ignoring duplicates

HTTP Semantics RFC 9110 defines methods such as PUT and DELETE as idempotent in intended effect; POST is not inherently idempotent. Order creation therefore needs an application-level key.

Store the idempotency key with tenant, operation type, and a canonical request hash. Return the previous result for the same key and payload. Reject the same key with different content using 409 Conflict. Concurrent requests require a transaction or unique constraint; query-then-insert without atomic protection leaves a race.

text
UNIQUE (tenant_id, operation_type, idempotency_key)

request_hash = SHA256(canonical_json(request_body))

if key exists and request_hash differs:
    return 409 KEY_REUSED_WITH_DIFFERENT_PAYLOAD
if key exists:
    return stored_business_result
else:
    atomically create order + idempotency record + outbox event

Retention must cover the realistic retry horizon. Orders, payments, and document jobs can require different windows. After expiry, stable business identifiers may still be needed to distinguish a late repeat from a new operation.

7. Transactional outbox closes the database–message gap

Saving an order and then publishing a message are two operations. If the database commits but publishing fails, the order remains without an ERP transfer. If publishing happens first and commit fails, an event exists for an order that does not.

With a transactional outbox, the order and outgoing event commit in one local transaction. A publisher sends the outbox row and marks progress. The publisher can crash around acknowledgement, so duplicate delivery remains possible; consumers need an inbox or equivalent deduplication record.

sql
BEGIN;
INSERT INTO orders (id, status, ...) VALUES ('ord_4817', 'submitted', ...);
INSERT INTO outbox (event_id, aggregate_id, event_type, payload)
VALUES ('evt_9001', 'ord_4817', 'order.submitted.v1', '{...}');
COMMIT;

An ‘exactly once’ label does not guarantee an exactly-once business effect. A consumer can commit its database change and crash before acknowledging the message. Design for redelivery, deduplicate every external side effect by business identity, and preserve records that support reconciliation.

8. Classify failures by retryability and ambiguity

Failure class determines retry policy and the user-facing business state.
ConditionAutomatic behaviourOperational outcome
Connection not establishedBounded backoff with jitterQueue and alert after retry budget
429 / 503 + Retry-AfterRespect server delayTrack partner capacity
400 schema failureDo not retryMapping or data correction task
401 / 403Do not blindly retryInspect credentials, scope, or clock skew
Timeout after POSTIdempotent replay or status query firstverification_required if still unknown
Invalid webhook signatureDo not processSecurity record and appropriate alert

Retries must not multiply across layers. Three attempts at the gateway, three in the application, and three in the worker can turn one business event into 27 remote calls. Assign one retry owner and define total duration and maximum attempts. A circuit breaker does not repair the dependency; it temporarily limits new pressure on a failing system.

9. Security: grant the integration account only what it needs

A shared long-lived API key in source code is convenient but difficult to rotate and investigate. Prefer a distinct client identity, short-lived access token, audience restriction, and narrow scopes where the ecosystem supports them. OAuth 2.0 Security Best Current Practice (RFC 9700) recommends restricting token privileges to the minimum resources and actions required.

  • Validate TLS certificates; never carry a temporary disabled-verification setting into production.
  • Keep secrets out of logs, error bodies, query strings, and browser code.
  • Validate webhook signature, timestamp, and replay window against the raw request body.
  • Do not trust tenant identity from payload alone; bind it to authenticated context.
  • Audit service-account use and permission changes.

10. Mapping and versioning are quiet sources of data loss

If ERP accepts 12 characters for customer_code while CRM accepts 40, truncation is a business decision. Decimal precision, currency, timezone, unit, enum values, null versus empty string, and deletion semantics belong in a field catalogue.

Adding an optional field is often backward-compatible; changing its meaning is not. Version event names or schemas and plan producer-consumer overlap. Consumers can ignore unknown optional fields, but silently mapping an unknown enum to a default can create the wrong business outcome.

Separate historical backfill from live change processing. When new orders arrive during migration, define a cutover timestamp, high-water mark, or change-data-capture boundary. Otherwise the gap can lose or duplicate records.

11. Observability must connect technical signals to business outcomes

order_id, external_order_id, integration_attempt_id, event_id, and distributed trace ID answer different questions. Preserve their relationships instead of forcing all of them into one correlation field. W3C Trace Context standardizes traceparent and tracestate for propagating tracing context between services.

  • Technical: request latency, timeout rate, 429/5xx rate, queue age, retry count.
  • Business: submitted, ERP-accepted, stock-reserved, and invoiced orders.
  • Consistency: records missing, extra, or materially different between source and target.
  • Operations: age of manual intervention, unresolved records, and recurring failure rate.

Do not use high-cardinality order IDs as metric labels; retain them in logs or traces. OpenTelemetry HTTP semantic conventions define common HTTP attributes and low-cardinality route templates.

12. Reconciliation is the final line of defence

Not every failure appears immediately. A webhook can be lost, an operator can edit ERP directly, or an old consumer can skip a new enum value. A scheduled reconciliation job must compare expected records across systems.

sql
-- Orders accepted locally but not linked to ERP within 15 minutes
SELECT o.id, o.external_order_id, o.accepted_at
FROM orders o
LEFT JOIN erp_order_links e ON e.order_id = o.id
WHERE o.status IN ('accepted', 'fulfilment_pending')
  AND e.erp_order_id IS NULL
  AND o.accepted_at < now() - interval '15 minutes';

Comparison is more than row count. Use business keys and checks over total amount, currency, line count, and state. Decide whether a mismatch is safe to repair automatically; a financial record may require a review task rather than a silent overwrite.

13. Scenarios to prove before release

  • How many ERP records appear when the same order arrives concurrently twice?
  • What does the portal show when ERP saves an order but no response returns?
  • Can an outbox event publish after the publisher crashes following commit?
  • Does duplicate delivery reserve stock or create an invoice twice?
  • Do Retry-After and the total retry budget hold during partner throttling?
  • How does an older consumer handle a new field and enum value?
  • Can credentials rotate without downtime?
  • Does restore replay already-completed external operations?
  • Does reconciliation find deliberately missing and extra records?

A successful happy-path demo is insufficient. Inject latency, disconnection, malformed responses, partial data, out-of-order delivery, and restarts. Acceptance criteria must prove that data moved, that invalid data did not move, and that ambiguous outcomes remain visible.

14. iPaaS, a custom integration service, or direct calls

An iPaaS can shorten delivery with standard connectors, visual mapping, and an operations console. A custom integration service may suit complex rules, high volume, or detailed failure control. Direct calls can be enough for a few simple flows; as the graph grows, ownership and observability scatter.

Choose through failure behaviour, volume, and ownership before connector count.
OptionStrong fitCost to examine
Direct APIFew simple synchronous flowsPoint-to-point coupling and scattered retries
iPaaSStandard connectors and moderate complexityLicensing, platform limits, data location, exit plan
Custom integration layerBespoke rules, volume, detailed controlEngineering, operations, and on-call ownership

15. Production rollout

Begin with one transaction type, such as order creation, in shadow mode. The new integration computes an outcome without writing to the authoritative target; compare it with the current path. Enable controlled writes for a customer or product cohort, then expand while error rate, queue age, and reconciliation differences stay below explicit thresholds.

  • Quantify rollback, for example more than 2% non-business errors in five minutes.
  • Install duplicate protection before old and new paths can write together.
  • Sequence schema changes so old and new application versions overlap safely.
  • Give operations the failure states, replay permissions, and escalation chain.
  • Run the first live reconciliation as a planned release check.

What an API and system integration design should deliver

A sound integration project delivers more than endpoint inventory: a data ownership matrix, OpenAPI contract, field mapping catalogue, state machine, idempotency scope, retry budget, failure taxonomy, security model, observability fields, reconciliation queries, and rollback plan.

Explore TankDev's system integration approach, system boundaries work, and enterprise software architecture guide. Describe your ERP, CRM, accounting, warehouse, or custom API flow, and we can define who owns each fact and what must happen when a dependency fails.

Related notes

WhatsAppDirect contact