What is API integration?
API integration is the work of making software systems exchange information or perform actions through their APIs. A request is the visible part. A maintained integration also needs an agreement about data, authentication, failures, ownership, and changes at the destination.
For example, an application might use Stripe for payments, SendGrid for transactional email, and Slack for operational notifications. A software vendor might also connect its product to an enterprise customer’s internal API. These are different business relationships, but both require reliable connections and explicit application behavior.
An API defines an interface. An SDK makes that interface easier to call in a particular language. An integration combines calls with the decisions your application needs: which record to send, how to interpret a status, when to wait, and who investigates a failure. Buying an SDK does not settle those decisions.
This guide builds a small integration boundary with fictional providers, explains common execution patterns, and shows where shared middleware can help. The downloadable examples are standalone educational JavaScript. They are not a released Invokation SDK, connectors, or a hosted service.
Start with an operation and a contract
Choose a specific operation before choosing infrastructure. “Connect our systems” is too vague to test. “Read an account’s current display name and status for this application” gives you a useful starting point.
Write down the required fields, identifier namespace, permitted caller, freshness requirement, and behavior when the provider cannot answer. Distinguish missing data from a confirmed inactive account. Decide whether a stale result is acceptable and how the product should explain unavailable information.
For enterprise-client integrations, ask which customers actually support the operation. A read-only gateway cannot implement a write just because your application has a generic update method. For company-owned API dependencies, identify the account, environment, and credential that own each quota and permission.
These decisions belong to your application. An adapter translates them into a destination’s interface; it should not silently rewrite their meaning.
A practical API integration architecture
Keep four responsibilities visible even if they initially live in one repository.
| Layer | Responsibility | Example decision |
|---|---|---|
| Application | Business behavior and authorization | Which account may this user see? |
| Adapter | Request construction, validation, and mapping | Does provider state A mean active here? |
| Connection and execution | Endpoint, credentials, deadlines, and permitted attempts | Which production connection may send this request? |
| Operations | Outcome visibility and recovery ownership | Who investigates a revoked grant? |
This is a boundary for reasoning, not a requirement to deploy four services. A small backend can start with separate modules. A shared integration layer becomes interesting when authentication, traces, policies, and incident handling repeat across several connections.
Keep provider-specific behavior inside adapters, including pagination and supported filters. A single listAccounts signature must not imply that every API has the same consistency, sorting, or page-size guarantees. Document differences that your application cannot safely normalize.
Choose synchronous, asynchronous, or event-driven execution
A synchronous request fits a bounded read whose answer the current interaction needs. Give it a deadline and an explicit unavailable state. An asynchronous job fits work that can finish later; returning an accepted job ID must not be presented as a completed provider action.
Webhooks let a provider notify your application about an event. They introduce signature verification, duplicate delivery, ordering, and durable acceptance. A webhook should not be treated as a trustworthy command merely because it arrived at a public URL. Read the webhook retries and duplicate events guide for the receipt boundary.
Scheduled polling can cover a destination without suitable events. Track cursors carefully and understand the provider’s update semantics. Repeatedly requesting the first page is not a synchronization strategy. Whichever pattern you choose, record the application outcome separately from the transport outcome.
Run a JavaScript adapter example
Download the API integration example, save it locally, and run it with Node.js 22 or newer:
node api-integration-example.mjs
It makes no network calls and needs no credentials or dependencies. Two fictional providers describe accounts differently. The example translates both into an application-owned shape while retaining the source namespace:
{"source":"alpha","id":"A-42","displayName":"Example account","status":"active"}
{"source":"beta","id":"B-18","displayName":"Example account","status":"active"}
Open the downloaded file to inspect the mappings and validation. Change Alpha’s fixture state from enabled to pending, then rerun it. The mapping fails rather than pretending an unknown state is inactive. That failure is useful: the adapter needs a reviewed interpretation before accepting a new provider value.
The transport is injected into readAccount, so tests can provide a response without contacting a real system. The function checks the HTTP result before decoding JSON and validates the application fields after mapping. Fetch-style clients can return a response for an HTTP error; a fulfilled promise alone does not establish application success.
This deliberately small exercise omits live authentication, pagination, request deadlines, and persistence. Before using this pattern with an actual API, implement those requirements against that provider’s documented contract. Do not copy fixture credentials or invent a universal schema from this example.
Treat API authentication as a lifecycle
API keys need protected storage, restricted access, replacement, and revocation handling. OAuth client-credentials flows acquire new access tokens; delegated OAuth flows may use rotating refresh tokens and require a user to reconnect after authorization is revoked. A custom JWT-based API may instead define a proprietary authentication endpoint and expiry contract.
These are outbound provider connections, separate from signing users into your application. Keep provider secrets in trusted backend infrastructure. Select authorized profiles from application context rather than accepting an arbitrary destination or credential reference from an untrusted caller.
Read OAuth token refresh management, custom JWT API authentication, and the proposed managed API authentication model for the different renewal boundaries. A middleware layer can operate a configured flow; it cannot create permissions the provider has not granted.
Classify failures before retrying
| Observation | Initial action | Risk to resolve |
|---|---|---|
| 401 or revoked grant | Inspect connection state and documented renewal behavior | Repeated calls can hide a reconnect requirement |
| 403 | Check operation permission and destination policy | Refreshing a token may not change authorization |
| 429 | Honor provider guidance and the relevant quota | One shared credential may affect several callers |
| 503 on a safe read | Consider bounded backoff within a deadline | Retrying every caller together can amplify load |
| Timeout after a write | Investigate the destination outcome | The action may have succeeded before the reply was lost |
| Invalid response fields | Fail mapping validation and inspect safely | A guessed default can corrupt business meaning |
Download the GET retry exercise and run node retry-backoff-example.mjs. Its simulated replies are 429, 503, then success. It prints the selected waits without actually sleeping or sending requests.
The exercise retries only GET requests and only those two explicit HTTP statuses. It honors both seconds and HTTP-date forms of Retry-After, limits attempts, and stops when the server’s requested wait exceeds its configured per-wait budget. It does not shorten that minimum to retry early. Network exceptions propagate for the caller to classify.
This is an inspectable policy exercise, not a complete retry library. A real transport also needs cancellation, per-attempt deadlines, a total elapsed-time budget, and coordination across callers. Writes need destination-specific idempotency and reconciliation decisions. Continue with retries, idempotency, and replay before applying automatic recovery to side effects.
Observe the operation without exposing secrets
Record the profile, environment, operation, configuration version, elapsed time, attempt count, and final outcome. Separate a token acquisition failure from a mapping failure and an unsuccessful business action. An HTTP 200 can still contain a provider-specific rejection that the adapter must recognize.
Use synthetic fixtures in tests and redact credentials, authorization headers, personal fields, and confidential payloads from logs. Agree on an owner for each failure class. A dashboard without an escalation path does not reduce the work of supporting a broken connection.
Before rollout, test expired credentials, unknown enum values, rate limits, unavailable providers, and ambiguous writes. Promote a small set of connections first, preserve the previous mapping version, and decide how to disable an operation without taking down unrelated dependencies.
When does an integration platform help?
Start with the simplest maintained boundary your team can operate. Repeated credential handling, inconsistent retries, scattered provider configuration, and difficult customer handovers are reasons to evaluate shared infrastructure. A one-off call with stable requirements may need only a well-tested module.
The iPaaS and integration middleware guide explains the category and evaluation questions. For an implementation direction, explore centralizing third-party APIs or customer-specific SaaS integrations.
Invokation is researching a developer-first integration platform for both contexts. Its proposed profiles would centralize connection configuration and execution while your team owns the operation contract. The runtime, SDK, and connectors are in development. Join early access with a concrete recurring integration problem to help shape that work.
Sources and further reading
- MDN: Using the Fetch API explains HTTP response handling and cancellation.
- Node.js: Fetch and related globals documents the runtime primitives used by the examples.
- RFC 9110: HTTP Semantics defines method semantics and Retry-After.
- AWS Builders’ Library: Timeouts, retries, backoff, and jitter discusses failure amplification and recovery tradeoffs.