Development

What Is an API? How Software Talks to Other Software

Learn what an API is, how requests and responses work, why interfaces matter between systems, and how modern applications use APIs to access data and services.

What Is an API? How Software Talks to Other Software

Most modern applications do far more than their own code could handle alone. A shopping app may need a payment provider, a travel app may need maps, a dashboard may retrieve information from a database, and a weather app obviously needs weather data from somewhere.

These systems communicate through APIs, short for Application Programming Interfaces.

An API provides a controlled way for one piece of software to request data or functionality from another. Instead of needing to know how the other system works internally, an application follows the API’s defined rules, sends a request, and receives a response, which is the same boundary idea that matters in software architecture and system design.

That basic pattern sits behind an enormous amount of the software we use every day.

Application

    │ request

   API

    │ processes request

Underlying system

    │ response

Application

The useful mental model is not that an API is a database or remote program by itself. It is the interface through which one system is allowed to interact with another system’s data or capabilities.

An API Is an Interface Between Software Systems

The word interface is the most important part of the name.

A graphical user interface gives a person a defined way to interact with software. Buttons, menus, forms, and controls expose actions without requiring the user to understand the application’s internal code.

An API does something similar for software, a definition also reflected in MDN’s API overview.

Suppose an online store needs to calculate shipping prices. The store does not need access to all of a shipping company’s internal systems. Instead, the shipping company might expose an API that accepts information such as the destination, package weight, and shipping method.

The store sends that information in the expected format and receives the available shipping rates in return.

The API creates a boundary between the systems. It specifies what can be requested, how requests should be structured, and what kinds of responses the caller should expect.

That lets the shipping provider change much of its internal implementation without forcing every customer to rewrite their application, provided the API contract remains compatible.

Requests Start the Conversation

For many web APIs, communication begins when a client sends an HTTP request to an API endpoint.

Imagine a weather service exposing:

GET /weather?city=Auckland

The request is asking for weather information associated with Auckland.

An API request can contain several pieces of information depending on the operation. It may include the endpoint being accessed, an HTTP method, query parameters, headers, authentication credentials, or a request body containing data.

For example, creating a new customer might use a request resembling:

POST /customers

{
  "name": "Alex",
  "email": "alex@example.com"
}

The precise format is determined by the API rather than by the calling application. The client needs to follow the interface the provider has defined, which is why JSON Schema versus TypeScript types becomes relevant once teams need to formalize request and response shapes.

That agreement is what makes communication possible. Two systems can be written in entirely different programming languages and run on different platforms while still communicating successfully because both understand the same API contract.

The API Processes the Request

Receiving the request is only the beginning.

The API layer typically examines what the caller is asking for, verifies that the request is valid, performs any required authentication or authorization checks, and invokes the underlying application logic.

Consider an API request to retrieve an order:

GET /orders/4821

Behind that apparently simple endpoint, the application might need to determine who made the request, check whether that user is permitted to view order 4821, retrieve information from a database, combine it with other data, and format the result.

The caller does not need to know those details.

From its perspective, the contract might simply be:

Send the correct request to /orders/4821, and if you are authorized, receive information about order 4821.

That abstraction is one of the reasons APIs are so powerful. They expose capabilities without exposing every implementation detail behind those capabilities.

The Response Tells the Caller What Happened

After processing the request, the API sends a response.

A successful response might contain the requested information:

{
  "id": 4821,
  "status": "shipped",
  "total": 84.50
}

A failed request should return useful information too. If the requested record does not exist, the API might return a 404 Not Found response. If authentication is missing or invalid, the result might instead be 401 Unauthorized.

HTTP APIs commonly use status codes to communicate the broad result of a request:

StatusGeneral meaning
200Request succeeded
201Resource was created
400Request was invalid
401Authentication is required or failed
403Request understood, but access is not allowed
404Resource was not found
500Server encountered an error

The response may contain additional details explaining what happened, especially when the caller needs enough information to recover from an error.

A useful API therefore does more than return data when everything works. It also communicates failures in a predictable way, which is the same reason structured logging matters once requests start failing in production.

JSON Is a Common Language for API Data

Many modern web APIs exchange information using JSON, or JavaScript Object Notation, with json.org remaining the classic external reference for the format itself.

JSON represents structured data using objects, arrays, names, strings, numbers, booleans, and null values. A weather API, for example, might return something conceptually like:

{
  "city": "Auckland",
  "temperature": 18,
  "condition": "Cloudy"
}

The client application can parse those fields and decide how to display or use them.

JSON became popular partly because it is relatively lightweight, human-readable, and supported by virtually every major programming language. Java, Python, C#, Go, JavaScript, Rust, and many other languages can all create and parse JSON without requiring the two systems to share the same technology stack.

JSON is not the only API data format. Some systems use XML, Protocol Buffers, form data, plain text, binary formats, or specialized protocols. But for HTTP-based application APIs, JSON is one of the formats developers encounter most frequently.

Endpoints Represent the Things an API Exposes

An API usually exposes specific addresses called endpoints.

A commerce API might have endpoints such as:

/products
/products/42
/orders
/customers

Each endpoint represents a resource or operation the API allows clients to interact with.

The HTTP method can further describe the requested action. In a typical REST-style API, you might see:

GET    /products/42
POST   /products
PATCH  /products/42
DELETE /products/42

These can roughly correspond to reading, creating, updating, and deleting data.

Not every API follows REST conventions, and URLs alone do not define an API’s architecture. But the pattern illustrates the controlled nature of the interface: the caller does not receive unrestricted access to the application’s database or internal code. It receives a specific set of operations the API has chosen to expose.

APIs Let Systems Stay Separate

Without an API boundary, two applications can become tightly coupled.

Imagine a mobile application connecting directly to the tables inside a company’s production database. The mobile developers would need intimate knowledge of the schema, database credentials would have to be distributed to client devices, and even minor database changes could break the application.

An API provides a safer and more stable boundary:

Mobile app → API → application logic → database

The mobile application asks for what it needs through the API. The server decides how to retrieve that information internally, which is why what a mock server is becomes useful when the real backend is unavailable or still evolving.

The database can later be redesigned, moved, partitioned, or even replaced without necessarily changing the public API.

This separation is valuable because it gives different parts of a system room to evolve independently.

Login Systems Often Depend on APIs

Authentication is one place where APIs appear constantly.

When a user enters login credentials, the visible form may send an API request to an authentication service. That service verifies the supplied information and returns the result.

A simplified flow might be:

Login screen → authentication API → identity system

If the credentials are valid, the response might establish a session or return a token that the application can use for subsequent authenticated requests.

Modern applications may also use third-party identity providers. A service offering “Sign in with Google” or another external identity system is communicating through defined authentication protocols and APIs rather than receiving unrestricted access to the provider’s internal user database.

The application gets the information it has been authorized to receive through a controlled interface, a pattern formalized in OAuth 2.0 and related identity standards.

Payment APIs Keep Complex Payment Infrastructure Behind a Boundary

Online payments provide another clear example.

Suppose an online store needs to charge a customer’s card. Building every component of card processing, banking integration, fraud detection, payment networks, refunds, and compliance internally would be enormously complex.

Instead, the application can integrate with a payment provider.

Conceptually, the store might send an API request describing a payment:

{
  "amount": 4999,
  "currency": "USD",
  "payment_method": "..."
}

The payment provider performs the work behind its API and returns information indicating whether the payment succeeded, failed, or requires another step.

The store uses the payment capability without needing direct access to the provider’s internal payment infrastructure, which is why the OpenAPI specification and similar interface contracts matter so much around third-party APIs.

This is one of the central purposes of APIs: complex functionality can be exposed as a controlled service that other applications can build on.

Maps Are Usually Integrated Through APIs Too

When an application displays a map, calculates a route, converts an address to coordinates, or searches for nearby places, it may be using a mapping API.

A delivery application could send an origin and destination and receive routing information. A property website might provide an address and receive geographic coordinates. A travel site might request places around a particular location.

The mapping provider owns the underlying geographic datasets, routing algorithms, and infrastructure. The client application works with a documented API instead.

This lets developers add sophisticated mapping capabilities without building an entire global mapping platform themselves.

It also means the application depends on the API provider’s availability, pricing, rate limits, and rules. Reusing another system’s capabilities saves enormous development effort, but it creates an external dependency that needs to be managed.

Weather Apps Usually Retrieve Data Rather Than Measure It

A weather application on your phone is unlikely to maintain its own worldwide network of meteorological stations.

Instead, it can request forecast or observation data from an API.

The request could include a location:

/weather?latitude=51.5&longitude=-0.1

and the response might contain temperature, precipitation probability, wind information, or forecast periods.

The application then turns that structured data into the icons, charts, and descriptions shown to the user.

This illustrates an important distinction between an API and the underlying data source. The API is the interface through which the application accesses the information. The weather observations, models, and databases exist behind that interface.

Databases Can Sit Behind APIs

Many applications use APIs as the controlled entry point to data stored in databases.

Suppose a customer-facing app needs to display a user’s orders. The client could ask:

GET /users/123/orders

The API determines whether the caller is allowed to access user 123, queries one or more internal databases, and returns only the appropriate fields.

This is safer than simply giving the application arbitrary database access.

It also allows the backend to enforce business rules. A database may contain much more information than one client should see, while an API can deliberately expose only a subset.

For example, an internal customer record might contain support notes, fraud indicators, and administrative metadata. The public API could return only the customer’s name and order history.

The API therefore becomes both an integration mechanism and a control boundary.

Authentication Controls Who Can Call an API

Publicly reachable does not necessarily mean publicly usable.

Many APIs require callers to authenticate themselves with credentials such as API keys, access tokens, signed requests, or OAuth-based authorization.

A request might contain:

Authorization: Bearer <access-token>

The API uses that credential to determine who is making the request and, where appropriate, what that caller is permitted to do.

This distinction between authentication and authorization matters. Authentication establishes an identity or credential context; authorization determines whether that identity is allowed to perform a particular operation.

A valid user might be allowed to read their own account:

GET /accounts/123

but forbidden from requesting another customer’s private information.

A well-designed API therefore controls not only whether a request is technically valid, but also whether the caller is permitted to perform it.

APIs Need Limits Because Software Can Make Requests Very Quickly

Once an API is accessible to software, requests can arrive far faster than a human could generate them manually.

A badly behaved application might accidentally send thousands of requests per second. An attacker might intentionally do the same.

APIs often use rate limiting to control this.

A service might allow a client a certain number of requests within a particular interval. Requests beyond that limit can be delayed or rejected.

Rate limits protect infrastructure, prevent accidental overload, reduce abuse, and help providers allocate resources fairly between customers.

This is another example of the API acting as a controlled boundary. It does not merely expose a capability; it defines how that capability may be consumed, and Stripe’s rate-limiting guidance is a practical example of how real providers communicate those limits.

APIs Can Fail Even When Your Application Is Working

Using another system’s API introduces a distributed-systems problem: the other service may not always be available.

A payment provider might be slow. A map API could temporarily fail, a network connection could time out, or an API might reject requests because a rate limit has been exceeded.

Applications therefore need to handle API failures deliberately.

For some operations, retrying may be appropriate. For others—especially payments or other actions with side effects—blind retries can accidentally perform the operation more than once unless the API provides appropriate idempotency mechanisms.

Client applications should also expect malformed responses, timeouts, authentication failures, and version changes.

Calling an API is ultimately communicating with another system over a boundary. That boundary needs the same defensive engineering as any other external dependency, which is also why how to mock an API before the backend exists is such a common engineering workflow.

Documentation Is Part of the Interface

For developers, an API is only useful if they can understand how to use it.

Good API documentation explains available endpoints or operations, authentication requirements, request fields, response structures, errors, limits, and examples.

A developer might need to know that creating an order requires:

{
  "product_id": 42,
  "quantity": 2
}

rather than:

{
  "item": 42,
  "count": 2
}

Those names are not interchangeable unless the API says they are.

This is why APIs are sometimes described as contracts. The provider defines a set of expectations, and client applications build against them.

Changing that contract carelessly can break every application depending on it.

API Versions Help Systems Evolve

Eventually, APIs need to change.

A provider may need new fields, different behavior, stronger security requirements, or a redesigned data model. If every change immediately breaks existing clients, maintaining the API becomes extremely difficult.

Versioning can provide a transition path.

You may encounter URLs such as:

/api/v1/users
/api/v2/users

where older applications continue using one version while newer clients migrate to another.

Not every change requires a new version. Adding an optional response field, for example, may be backward compatible if clients are designed to ignore fields they do not recognize.

The difficult part is maintaining a predictable contract while allowing the underlying product to evolve.

Stable APIs hide internal change effectively; unstable APIs expose that change to every system that depends on them.

APIs Are Not Limited to the Public Internet

The word API often brings to mind services such as payment or map providers, but APIs also exist inside individual applications and private company networks.

A large system might have separate services for customers, orders, inventory, payments, and notifications. Those services can communicate through internal APIs even though none of those interfaces is directly available to the public.

For example:

Order service → Inventory API
              → Payment API
              → Notification API

The same basic principle applies. Each component exposes a defined way for another component to request data or behavior without directly controlling its internal implementation.

An API can therefore connect different companies, different applications, or simply different modules inside one software system.

Not Every API Is REST

Modern introductory examples frequently use HTTP and JSON because REST-style APIs are easy to recognize, but API is a much broader concept.

GraphQL APIs allow clients to describe the data they want through queries. gRPC systems commonly use strongly defined service contracts and binary Protocol Buffers. WebSockets can support long-lived two-way communication, while operating systems and programming libraries expose APIs directly through functions and system calls.

Even a programming library can have an API:

send_email(to, subject, body)

The function signature is an interface exposed to other code.

So while:

HTTP request → JSON response

is an extremely common form of modern API communication, it is not the definition of an API.

The deeper idea is a defined interface through which software can use another component’s capabilities.

The API Is the Boundary, Not Necessarily the System Behind It

It is useful to separate three things that are often mentally merged together:

Client → API → underlying system

The client is the software making the request. The API defines how that request can be made, while the underlying system performs the actual work.

If you call a weather API, the API is not necessarily the system producing weather forecasts. It may be the controlled interface in front of databases, models, caches, and other services.

If you call a payment API, the API is not the bank or card network. It is the interface through which your software requests payment operations.

This distinction explains why APIs are so valuable architecturally. They allow the complicated system behind the boundary to remain complicated while presenting a much smaller, more predictable surface to callers.

A Good API Exposes Capabilities Without Exposing Everything

Imagine a payment system internally containing hundreds of services, databases, security controls, fraud models, queues, and integrations.

An online shop should not need to understand all of them.

It might only need operations such as:

Create payment
Check payment status
Issue refund

The API compresses a complicated internal system into a controlled set of usable capabilities.

That boundary also protects the underlying system. The caller cannot simply execute arbitrary database queries or run internal functions. It can perform only operations that have deliberately been exposed, subject to whatever authentication, authorization, validation, and limits the API enforces.

The best API boundaries therefore serve both sides: they make integration easier for clients while helping the provider maintain control over its systems.

The Core Pattern Is Request and Response

Despite the number of technologies that can sit behind an API, the everyday model remains simple.

An application needs something another system can provide. It sends a request through that system’s defined interface, the receiving system processes the request, and a response communicates the result.

Application

    │ "I need this data or action"

   API


Other system

    │ "Here is the result"

Application

The exchanged data might be JSON. The request might retrieve weather information, initiate a payment, verify a login, calculate a map route, or retrieve records ultimately stored in a database.

What matters is the boundary.

The calling application does not need unrestricted access to the other system and does not need to understand all of its internal machinery. It needs to understand the interface it is allowed to use.

An API is a controlled way for software to use another system’s data or functions: one side makes a request according to an agreed contract, and the other side returns a predictable response.

Top