The API Worked. So Why Did the Integration Still Fail?

A successful API response is not the same as a successful business process. Reliable integration depends on retries, idempotency, reconciliation, state, monitoring and recovery.

Rigg Technologies

Rigg Technologies

Engineering Team

Aug 15, 202616 min read

TL;DR

Reliable integration is not about getting two APIs to talk once. It is about making sure both systems remain consistent after retries, timeouts, duplicates, partial failures, outages and version changes — with reconciliation, auditability and recovery built in.

1. An API call is not an integration

System A sent the request. System B returned HTTP 200 OK. Everybody went home happy.

Three weeks later, Finance discovered that 417 transactions were missing. System A said, “We sent everything.” System B said, “Our API is working.” Both teams were technically correct. The integration was still broken.

An API gives applications a way to communicate. A real integration has to ensure the business process actually completes.

The important distinction

The endpoint can be healthy while the business process is not.

Reliable integration is about state, recovery, consistency and traceability across both systems — not merely whether an HTTP request succeeded.

2. Start with the worst possible timing

Imagine an ERP asking a payment gateway to charge a customer. The gateway succeeds, but the response is lost on the network.

The customer has been charged. The ERP does not know it.

The dangerous middle state
flowchart LR
    E["
ERP · Create Payment
"] --> G["
Payment Gateway
"] G --> C["
Charge Customer
"] C --> S["
SUCCESS
"] S -. "response lost" .-> X["
ERP never receives result
"] classDef default fill:#fff,stroke:#d9d9d9,color:#111,stroke-width:1px; classDef dark fill:#111,stroke:#111,color:#fff; class S dark;

Retry blindly and you may charge twice. Never retry and the ERP may permanently think the payment failed. that is integration design.

3. “Success” has several meanings

What actually succeeded?
Request sent?                  ✓
Remote server received it?     ✓
Remote processing succeeded?   ✓
Local system recorded result?  ?
Both systems agree now?        ?

A network request can succeed while the business transaction fails. A business transaction can succeed while the network request appears to fail.

4. HTTP status codes are not business truth

A 200 OK response might only mean “your request was accepted into a queue.” The business record may not exist yet.

Accepted is not the same as completed
flowchart LR
    A["
Send Request
"] --> B["
Request Accepted
"] --> C["
Queued
"] --> D["
Validated
"] --> E["
Processed
"] --> F["
Business Record Created
"] classDef default fill:#fff,stroke:#d9d9d9,color:#111,stroke-width:1px; classDef dark fill:#111,stroke:#111,color:#fff; class B dark;

5. The most dangerous error is sometimes no error at all

System A

10,421 transactions

System B

10,417 transactions

No exception. No outage. Just four missing records. Silent inconsistency is often more dangerous than a visible failure.

6. This is why reconciliation exists

Reconciliation asks a very simple question: Do both sides agree?

A useful mismatch
TX-98131

System A:
SUCCESS

System B:
MISSING
What makes this operationally useful

A mismatch should become visible and actionable.

Compare transaction IDs, amounts, timestamps and statuses so missing or conflicting records surface before Finance, Operations or a customer discovers them manually.

7. Retries without idempotency create duplicate business effects

If an order request times out, System A may correctly retry. If System B executes both requests, the customer gets two orders.

Same request, one business effect
%%{init: {
    'flowchart': {
        'nodeSpacing': 15,
        'rankSpacing': 20,
        'padding': 6,
        'useMaxWidth': false
    }
}}%%
flowchart LR
    A["
REQ-918281
"] --> Q{"
Seen?
"} Q -->|No| C["
Create Order
"] Q -->|Yes| R["
Return Cached
"] classDef default fill:#fff,stroke:#d9d9d9,color:#111,stroke-width:1px,rx:6,ry:6; classDef dark fill:#111,stroke:#111,color:#fff,stroke-width:1px,rx:6,ry:6; class C dark;
Idempotent behavior
First call:
create_order(request_id = REQ-918281)
→ CREATED

Retry:
create_order(request_id = REQ-918281)
→ ALREADY_PROCESSED

8. Retry the right failures, not every failure

Retries need meaning
%%{init: {
    'flowchart': {
        'nodeSpacing': 15,
        'rankSpacing': 20,
        'padding': 6,
        'useMaxWidth': false
    }
}}%%
flowchart LR
    E["
Integration Error
"] --> Q{"
Type?
"} Q -->|TIMEOUT| R["
Retry
"] Q -->|RATE_LIMIT| L["
Retry later
"] Q -->|503| S["
Retry
"] Q -->|INVALID_REQUEST| N["
Do not retry
"] Q -->|UNAUTHORIZED| A["
Stop + alert
"] Q -->|NOT_FOUND| B["
Business handling
"] classDef default fill:#fff,stroke:#d9d9d9,color:#111,stroke-width:1px,rx:6,ry:6; classDef dark fill:#111,stroke:#111,color:#fff,stroke-width:1px,rx:6,ry:6; class A dark;

If every error enters the same retry loop, you have not built resilience. You have built persistence.

9. Failed records need somewhere to go

Retry forever is not reliability. Eventually, unrecoverable records need a visible manual recovery path.

A simple dead-letter path
%%{init: {
    'flowchart': {
        'nodeSpacing': 15,
        'rankSpacing': 20,
        'padding': 6,
        'useMaxWidth': false
    }
}}%%
flowchart LR
    Q["
Normal Queue
"] --> P["
Process
"] --> R1["
Retry
"] --> R2["
Retry
"] --> F["
Still Failed
"] --> D["
Dead Letter Queue
"] classDef default fill:#fff,stroke:#d9d9d9,color:#111,stroke-width:1px,rx:6,ry:6; classDef dark fill:#111,stroke:#111,color:#fff,stroke-width:1px,rx:6,ry:6; class D dark;

10. Systems also disagree about identity

ERP customer 10082, CRM customer CUS-88231 and payment customer P-9210 may all represent the same business.

That relationship needs an explicit mapping. Display names are not reliable identifiers.

Identity mapping
ERP Customer:
10082

CRM Customer:
CUS-88231

Payment Customer:
P-9210

11. Event order can break otherwise-correct integrations

Created in one order, received in another
Expected:
1. Customer Created
2. Customer Updated

Received:
2. Customer Updated
1. Customer Created

Distributed systems do not always deliver events in the order you expect. That must be part of the design.

12. Partial failure is normal

Suppose an order transfer creates the customer and the order, then fails while reserving stock. “Integration failed” is too vague. Some of it already succeeded.

Make the process state explicit
flowchart LR
    A["NEW"] --> B["CUSTOMER_SYNCED"] --> C["ORDER_CREATED"] --> D["STOCK_RESERVED"] --> E["DELIVERY_CREATED"] --> F["COMPLETED"]
    C -. failure .-> X["STOCK_RESERVATION_FAILED"]
    classDef default fill:#fff,stroke:#d9d9d9,color:#111,stroke-width:1px;
    classDef dark fill:#111,stroke:#111,color:#fff;
    class X dark;

13. Logs should explain the business flow

Operationally useful integration trail
Integration Run:
INT-82910

Source:
ERP

Destination:
Warehouse System

Record:
ORD-10021

12:01:02  Order received
12:01:04  Customer mapped
12:01:05  Order created remotely
12:01:06  Stock reservation failed

Reason:
SKU-1182 not found

Status:
ACTION_REQUIRED

POST /orders returned 200 helps a developer. The trail above helps somebody actually solve the business problem.

14. Monitoring uptime is not enough

An API can be 99.99% available while 1,208 transactions are stuck in a retry queue.

PendingTransactions waiting
FailedTransactions requiring attention
DelayAverage processing time
RetriesRetry count
UnmatchedReconciliation differences
OldestUnprocessed event age
For management

System uptime is a technical metric. Transaction health is a business metric.

15. Eventual consistency is not necessarily a bug

If an order appears in reporting eight seconds after creation, that may be perfectly acceptable. The important part is defining the expected behavior.

Make delay expectations explicit
Expected delay:
< 30 seconds

Alert if:
Delay > 5 minutes

16. Integrations need clear data ownership

If ERP and CRM both believe they own the customer phone number, they can end up synchronizing the same field back and forth forever.

Customer contact

CRM owns

Outstanding balance

ERP owns

Payment status

Accounting owns

Integration rule

Other systems consume; they do not independently redefine the source of truth.

17. Validate data and restrict integration access

A weak integration says, “If System A sent it, insert it.” A stronger one validates amount, currency, customer identity, dates and required fields.

Integration credentials should also follow least privilege, expiry, rotation, encryption, scoped access and audit logging.

Bad data should stop visibly
REJECTED

Reason:
CUSTOMER_NOT_FOUND

18. API contracts change eventually

A harmless-looking contract change
Today:
{
  "customerName": "ABC Ltd"
}

Tomorrow:
{
  "customer": {
    "name": "ABC Ltd"
  }
}

Reliable integrations need versioning and compatibility planning because fields, enums, validation rules and schemas change over time.

19. Good integration architecture expects failure

The goal is not to make failure impossible. It is to make failure detectable, recoverable, traceable and safe.

A more realistic integration flow
%%{init: {
    'flowchart': {
        'nodeSpacing': 15,
        'rankSpacing': 25,
        'padding': 6,
        'useMaxWidth': false
    }
}}%%
flowchart TD
    subgraph row1 [" "]
        direction LR
        S["
Source System
"] --> E["
Create Event
"] --> V["
Validate
"] --> Q["
Queue
"] --> N["
Send
"] --> R["
Remote System
"] end subgraph row2 [" "] direction LR X["
Receive Result
"] --> Y["
Verify
"] --> P["
Persist State
"] --> C["
Reconcile
"] --> D["
Completed
"] end R ==> X classDef default fill:#fff,stroke:#d9d9d9,color:#111,stroke-width:1px,rx:6,ry:6; classDef dark fill:#111,stroke:#111,color:#fff,stroke-width:1px,rx:6,ry:6; style row1 fill:none,stroke:none; style row2 fill:none,stroke:none; class E,Q,C dark;
Retries Idempotency Logging Monitoring Alerts Dead-letter queue Manual recovery

20. The two systems should be able to disagree safely

Do not hide uncertainty
MISMATCH DETECTED

Transaction:
TX-10921

ERP:
PAID

Gateway:
UNPAID

Action:
REVIEW REQUIRED

A dangerous integration silently chooses one side. A safer system makes the disagreement visible.

21. A small reconciliation job can prevent a large business problem

A nightly safety net
Every night:

compare today's transactions
find missing records
find amount mismatches
find status mismatches
attempt safe recovery
report unresolved differences

This may never appear in a product demo. It may prevent months of accounting confusion.

22. What should you ask an integration vendor?

Do not ask only “Can you connect the APIs?”

Ask how the integration behaves when things go wrong

  • How do you handle retries?
  • How do you prevent duplicates?
  • How do you reconcile records?
  • What happens during partial failure?
  • How are failed records recovered?
  • How do we monitor transaction health?
  • How are IDs mapped?
  • Where is the audit trail?
  • How do you handle version changes?

23. APIs are the easy part

Writing http.post(...) is usually not the difficult part.

The difficult part is ensuring that after 100 requests, 10,000 requests, 10 million requests, network failures, server restarts, deployment changes and partner outages, both systems still agree about what happened.

That is integration engineering.

24. What this looks like from the business side

Finance

Missing or duplicate transactions create reconciliation work and financial risk.

Operations

Teams waste time comparing systems and manually repairing broken flows.

Customer experience

A payment can succeed while the order or account still shows the wrong state.

Management

Healthy API uptime can hide unhealthy transaction processing unless business-level monitoring exists.

Rigg’s point of view

The real question is not whether System A can call System B.

It is whether both systems can keep behaving like one business process when networks fail, records disagree, retries happen, schemas change and one side goes offline.

25. Your APIs may already be working. Your integration may still need work.

At Rigg Technologies, we build integrations between internal applications, ERP systems, external services, mobile platforms, payment systems and other business software.

If your systems are connected but your teams still spend time comparing numbers, re-entering data, fixing duplicates or chasing missing transactions, the integration layer is probably where the real work remains.

26. FAQ

What technologies did you use?

We used Node.js, PostgreSQL, Redis, React, and AWS cloud infrastructure to build the complete solution.

How long did the implementation take?

The entire project took approximately 12 weeks from initial discovery to deployment.

How is the system secured?

Role-based access control, end-to-end data encryption, and continuous monitoring ensure high security standards.

Can it integrate with other tools and regions?

Yes, through flexible REST/GraphQL APIs and multi-tenant setup for global scale.

27. Comments & Testimonials

Avatar
Priya Shah
3 days ago

COO

"Fantastic transformation! This platform is an absolute backbone for our operations."

Avatar
Rohit Menon
5 days ago

IT Head

"Real-time visibility has reduced firefighting significantly. Great work, team!"

Ready to solve the problem your current software keeps avoiding?

Partner with Rigg Technologies to design, build and improve software that moves your business forward.