Full Stack • Java • System Design • Cloud • AI Engineering

What Is an API?

A complete guide to what APIs are — covering the definition, how they work, the anatomy of a request and response, API types, real-world examples, and the foundational vocabulary every developer needs before designing or consuming any API.

What Is an API?

An API — Application Programming Interface — is a defined contract that allows one piece of software to talk to another.

That one sentence contains everything. An API is not a URL. It is not a server. It is not a framework. It is a contract — a precise specification of how a caller can request something, what data it must provide, what the receiver will do with that request, and what the caller will get back.

When you open a weather app on your phone, the app does not contain weather data. It sends a request to a weather service's API, which responds with the current conditions for your location. The app and the weather service were built by different teams, run on different servers, possibly in different programming languages — and they communicate perfectly because they both honour the same API contract.

This is the core value of APIs: they decouple systems. The weather service does not need to know how the app renders a forecast. The app does not need to know how the weather service collects atmospheric readings. Each side just needs to respect the contract.


A Concrete Example Before the Theory

Before going further, here is what an API interaction looks like in practice.

Scenario: A banking application needs to look up a customer's account balance.

Without an API: The banking frontend would need direct database access, knowledge of the schema, credentials, query syntax, and the ability to handle raw SQL results. Any change to the database breaks the frontend immediately.

With an API: The backend team exposes a single endpoint:

GET /v1/accounts/{accountId}/balance
Authorization: Bearer <token>

The frontend calls it and receives:

{
  "accountId": "acc_7f3a9b2c",
  "currency": "USD",
  "availableBalance": 4250.00,
  "pendingBalance": 4100.00,
  "asOf": "2026-07-18T09:15:00Z"
}

The frontend team only needs to know this contract. The database schema, query logic, caching, and data transformation are completely hidden. The backend team can change all of those internals without touching the frontend, as long as the response structure stays the same.


The Three Parts of Every API Contract

Every API — regardless of protocol, style, or technology — is defined by three things:

1. The Interface

The interface specifies what operations are available and how to invoke them:

  • What is the operation name or endpoint path?
  • What input does the caller need to provide (parameters, headers, body)?
  • What format must the input be in?

2. The Behaviour

The behaviour specifies what the API does with the input:

  • What business logic is executed?
  • What state changes happen?
  • What side effects occur (emails sent, records written, payments processed)?

Behaviour is not directly visible to the caller — it is the implementation. The contract specifies the observable result, not the implementation.

3. The Response

The response specifies what the caller receives back:

  • What is returned on success?
  • What is returned on each category of failure?
  • What format is the response in?
  • What do status codes or error codes mean?

A contract without a complete failure specification is incomplete. How a caller handles a 404 Not Found vs a 409 Conflict vs a 503 Service Unavailable depends entirely on what the API specifies those codes to mean.


How an API Request Works

When a client calls an HTTP API, the following sequence happens:

sequenceDiagram
    participant CLIENT as Client (App / Service)
    participant NET as Network
    participant GW as API Gateway / Load Balancer
    participant SVC as API Server
    participant DB as Data Store

    CLIENT->>NET: HTTP Request (method, URL, headers, body)
    NET->>GW: Route request
    GW->>GW: Auth, rate limit, logging
    GW->>SVC: Forward request
    SVC->>SVC: Parse, validate, execute business logic
    SVC->>DB: Read or write data
    DB-->>SVC: Query result
    SVC->>SVC: Serialize response
    SVC-->>GW: HTTP Response (status code, headers, body)
    GW-->>CLIENT: Response delivered

Each step in this journey is well-defined:

  1. The client forms a request according to the API contract — method, path, required headers, body format.
  2. The network delivers the request — TCP/IP handles routing; TLS encrypts the payload in transit.
  3. The gateway applies cross-cutting concerns — authentication, rate limiting, logging, routing to the right backend.
  4. The server processes the request — validates input, executes business logic, interacts with databases or other services.
  5. The server returns a response — a status code indicating success or failure, headers with metadata, and a body with the result.

Every API interaction is this same pattern, regardless of whether the underlying protocol is HTTP, gRPC, WebSocket, or a message queue.


The Anatomy of an HTTP API Request

The most common API style today is HTTP. Understanding the structure of an HTTP request is foundational:

POST /v1/payments HTTP/1.1
Host: api.bank.com
Content-Type: application/json
Authorization: Bearer eyJhbGciOiJSUzI1NiJ9...
Idempotency-Key: pay_a1b2c3d4
X-Request-ID: req_7f8a9b0c
X-Correlation-ID: corr_e1f2a3b4

{
  "fromAccountId": "acc_7f3a9b2c",
  "toAccountId": "acc_3c9b2e5a",
  "amount": {
    "value": 250.00,
    "currency": "USD"
  },
  "reference": "Invoice INV-2026-1234",
  "scheduledAt": null
}

Breaking it down:

Part Value in the example Purpose
Method POST What action to perform (create a payment)
Path /v1/payments Which resource to act on
Host api.bank.com Which server to send the request to
Content-Type application/json Format of the request body
Authorization Bearer eyJ... Proves the caller's identity
Idempotency-Key pay_a1b2c3d4 Makes the operation safe to retry
X-Request-ID req_7f8a9b0c Unique ID for this specific request (for tracing)
Body JSON object The data needed to execute the operation

The Anatomy of an HTTP API Response

The server's response is equally structured:

HTTP/1.1 201 Created
Content-Type: application/json
Location: https://api.bank.com/v1/payments/pmt_e5f6a7b8
X-Request-ID: req_7f8a9b0c
X-RateLimit-Remaining: 98
Retry-After: (absent — not rate limited)

{
  "paymentId": "pmt_e5f6a7b8",
  "status": "PENDING",
  "fromAccountId": "acc_7f3a9b2c",
  "toAccountId": "acc_3c9b2e5a",
  "amount": {
    "value": 250.00,
    "currency": "USD"
  },
  "reference": "Invoice INV-2026-1234",
  "createdAt": "2026-07-18T09:15:00Z",
  "estimatedSettlementAt": "2026-07-18T17:00:00Z"
}

Breaking it down:

Part Value Purpose
Status code 201 Created Outcome: resource was created successfully
Content-Type application/json Format of the response body
Location https://.../pmt_e5f6a7b8 Where to find the newly created resource
X-Request-ID req_7f8a9b0c Echoes the caller's request ID for tracing
X-RateLimit-Remaining 98 How many requests remain in this rate limit window
Body JSON object The created payment record with server-assigned ID

Why "Interface" Is the Right Word

The word interface in API is deliberate. An interface is a boundary — it separates the caller from the implementation.

Think of a wall socket. You plug in a lamp, a phone charger, or a refrigerator. You don't know what is behind the wall — whether the power comes from a coal plant, a solar farm, or a nuclear reactor. The socket is the interface. The specification says: 120V, 60Hz, two or three prongs. As long as both sides respect that contract, anything can be plugged in.

APIs work the same way. The caller knows the interface contract. The implementation details are hidden. This is called encapsulation, and it is what makes large software systems maintainable.

When a team changes the database schema, caching strategy, or internal service architecture — the API consumers notice nothing, as long as the interface contract is unchanged.


Types of APIs

Not all APIs use the same protocol or style. The right choice depends on the use case.

REST (Representational State Transfer)

REST APIs use HTTP as the transport protocol and model their operations around resources — things that can be named and manipulated.

GET    /v1/orders             → list orders
POST   /v1/orders             → create an order
GET    /v1/orders/ord_abc123  → get a specific order
PUT    /v1/orders/ord_abc123  → replace an order
PATCH  /v1/orders/ord_abc123  → partially update an order
DELETE /v1/orders/ord_abc123  → delete an order

REST is the most common style for public and internal web APIs. It is stateless, cacheable, and built on the well-understood semantics of HTTP.

Best for: Public APIs, web and mobile clients, CRUD-heavy services, integrations with third parties.

RPC (Remote Procedure Call)

RPC APIs model their operations as procedure calls — named functions that the caller invokes, passing arguments and receiving a return value. The most common modern RPC protocol is gRPC, which uses Protocol Buffers (protobuf) for serialization.

service OrderService {
  rpc GetOrder (GetOrderRequest) returns (Order);
  rpc CreateOrder (CreateOrderRequest) returns (Order);
  rpc ListOrders (ListOrdersRequest) returns (ListOrdersResponse);
}

gRPC uses HTTP/2 for transport (supporting bidirectional streaming), protobuf for compact binary serialization, and strongly typed contracts defined in .proto files.

Best for: Service-to-service communication where low latency, streaming, and strong typing matter.

GraphQL

GraphQL is a query language for APIs. Instead of fixed endpoints, the client specifies exactly what data it needs in a structured query, and the server returns precisely that — nothing more, nothing less.

query {
  order(id: "ord_abc123") {
    id
    status
    customer {
      name
      email
    }
    items {
      productName
      quantity
      unitPrice
    }
  }
}

The client determines the shape of the response. No over-fetching (getting fields you don't need) and no under-fetching (making multiple calls to assemble the data you need).

Best for: Applications with complex, variable data requirements — especially when multiple client types (web, mobile, embedded) need different views of the same data.

Event-Driven APIs / Async APIs

Not all APIs follow the request-response model. Event-driven APIs communicate by publishing and subscribing to events on a message broker (Kafka, RabbitMQ, Amazon SNS/SQS).

Producer: order-service → publishes "order.confirmed" event to Kafka
Consumer: fulfillment-service → subscribes to "order.confirmed" events
Consumer: notification-service → subscribes to "order.confirmed" events

The producer does not call the consumers directly — it publishes an event and any interested service can react. This decouples systems temporally (the consumer processes the event when it is ready) and structurally (producers and consumers don't know about each other).

Best for: Workflows where multiple services need to react to state changes, high-throughput event streams, and scenarios where the producer should not wait for consumers.

SOAP (Simple Object Access Protocol)

SOAP is an XML-based protocol for exchanging structured information. It uses WSDL (Web Services Description Language) to formally define the service contract, supports complex security standards (WS-Security), and is common in enterprise integration — particularly in financial services, insurance, healthcare, and government.

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Header>
    <wsse:Security>...</wsse:Security>
  </soap:Header>
  <soap:Body>
    <tns:GetAccountBalanceRequest>
      <tns:AccountId>acc_7f3a9b2c</tns:AccountId>
    </tns:GetAccountBalanceRequest>
  </soap:Body>
</soap:Envelope>

Best for: Legacy enterprise systems, regulated integrations that require WS-Security, ACID transactions, and formal WSDL contracts.


Public APIs, Private APIs, and Partner APIs

APIs are not just a technical category — they are also a business and access category.

Public APIs (Open APIs)

Public APIs are accessible to any developer, often requiring only an API key to get started. They are products in their own right — businesses like Stripe, Twilio, and Google Maps have built enormous value by exposing their capabilities as public APIs.

Examples:

  • Stripe Payments API — any business can accept card payments by integrating Stripe
  • Twilio SMS API — any app can send text messages worldwide
  • Google Maps API — any app can embed maps and routing

Public APIs must be designed with extraordinary care. They are consumed by thousands of developers across hundreds of different use cases, they cannot be changed without deprecation notices, and they are the company's external face.

Private APIs (Internal APIs)

Private APIs are internal to an organization. They connect microservices, frontend applications to backends, and data platforms to consumer services. Most APIs in the world are private.

Private APIs are consumed by a known set of teams within the same organization. They can evolve more rapidly than public APIs, but they still need contracts, documentation, versioning, and security. A sloppy internal API becomes a maintenance burden as the engineering team grows.

Partner APIs

Partner APIs are shared with specific external partners under agreements — B2B integrations. A logistics company exposes a shipping API to its retail partners. A bank exposes an account verification API to partner fintech applications. A healthcare system exposes a patient data API to approved clinical partners.

Partner APIs sit between public (open to all) and private (internal only). They require authentication, authorization, contract governance, and SLA commitments, but only for a defined set of consumers.


APIs as Products

One of the most important shifts in modern API engineering is treating APIs not as technical plumbing but as products.

A product has users. It has a value proposition. It has documentation, onboarding, versioning, and support. It has metrics — adoption rate, error rate, latency, satisfaction.

When an API is treated as a product:

  • Consumers can discover it through a developer portal or catalog
  • Documentation is accurate and includes working examples
  • Breaking changes are announced with migration guides and deprecation periods
  • SLOs (Service Level Objectives) are published — callers know what uptime and latency to expect
  • Feedback from consumers is used to improve the API

When an API is treated as plumbing:

  • It is only documented in someone's head or in an outdated Confluence page
  • Breaking changes are deployed silently
  • There is no way for a new team to discover it exists
  • Consumers reverse-engineer it by reading the source code

The difference in outcomes is enormous. Teams that treat their APIs as products have fewer integration incidents, less coupling between services, and faster onboarding for new consumers.


The API Contract Is a Promise

An API contract is a promise the provider makes to its consumers. This is not metaphorical — in regulated industries, partner integrations, and public APIs, the contract is literally enforced by legal agreements and SLAs.

The contract includes:

Element What It Specifies
Endpoints / operations What you can call and how
Input schema What data you must provide and in what format
Output schema What you will receive back on success
Error schema What you will receive back on failure, and what each error code means
Versioning How breaking changes will be communicated and when old versions retire
SLA Uptime, latency, throughput, and rate limits you can rely on
Security model How the API is authenticated and what permissions are required

Every field in that table is part of the contract. When a provider changes the response schema without notice, consumers break. When a provider removes an error code from their documentation but their server still returns it, consumer error handling becomes unreliable. When a provider provides no versioning policy, consumers live in constant fear of silent breaking changes.

Good API engineering is the discipline of honouring and evolving this contract responsibly.


What Makes an API Good?

An API is not good just because it works. A good API is:

Predictable

A developer who understands one endpoint should be able to correctly guess how the next endpoint works. Consistent naming, consistent error formats, consistent use of HTTP verbs, consistent pagination — these reduce the cognitive load of integration.

Explicit

Good APIs are self-documenting in their structure. Status codes mean what they are supposed to mean. Error responses explain what went wrong. Field names are unambiguous. A caller should not need to read source code or ask the backend team to understand the API.

Stable

Once published and consumed, an API should not change in breaking ways without notice, deprecation, and migration support. Stability is what makes large ecosystems possible — thousands of Stripe integrations exist because Stripe has maintained remarkable API stability for over a decade.

Complete

An API that returns success responses but does not document its failure modes is incomplete. An API that has no documentation for authentication is incomplete. An API that lacks pagination for list endpoints is incomplete. Completeness means the consumer has everything they need, with no gaps that force guesswork.

Secure

An API that exposes data without authentication, leaks internal details in error messages, or allows callers to access data beyond their authorization is not production-ready. Security is not a layer added on top of the API — it is part of the contract.

Observable

An API that provides no request IDs, no rate limit headers, no structured error codes, and no way to correlate failures is extremely difficult to operate and debug. Observability must be designed into the API from the start.


Common Misconceptions About APIs

"An API is a URL"

A URL is the address of a resource. An API is the entire contract — the collection of endpoints, methods, headers, input schemas, output schemas, error codes, versioning policy, and SLA. A URL is one part of that contract.

"An API is just a backend"

An API is a contract, not an implementation. Two different backends can implement the same API contract. A mock server, a real service, and a stub for testing can all satisfy the same contract. The API is the specification; the backend is one implementation of it.

"Internal APIs don't need documentation"

Internal APIs are consumed by real developers who have real integration questions. Undocumented internal APIs lead to bugs (from incorrect assumptions), tight coupling (because consumers read source code instead of contracts), and outages (because breaking changes were not communicated). Documentation is a form of professionalism regardless of audience.

"REST is just HTTP"

REST is an architectural style with specific constraints: stateless interactions, uniform interface, resource-based addressing, self-descriptive messages, and hypermedia as the engine of application state (HATEOAS). HTTP is a protocol that REST APIs happen to use. An HTTP API that does not follow REST constraints is not a REST API — it is just an HTTP API.

"APIs are for external consumers only"

The majority of API calls in any production system are internal — microservice to microservice, frontend to backend, job scheduler to processing service. Every service boundary in a distributed system is an API contract. Treating internal boundaries with the same discipline as external ones is what makes large systems maintainable.


APIs in Production: What You Don't See

When a developer calls GET /v1/orders/ord_abc123, dozens of things happen invisibly:

  1. DNS resolution — the domain name is resolved to an IP address
  2. TLS handshake — client and server negotiate encryption
  3. TCP connection — possibly reused from a connection pool
  4. Load balancer — the request is distributed to a healthy backend instance
  5. API gateway — authentication, authorization, rate limiting, and logging happen here
  6. Routing — the gateway routes to the order service
  7. Authentication verification — the JWT or API key is validated
  8. Authorization check — does this caller have permission to access this order?
  9. Input validation — is the order ID in the expected format?
  10. Cache check — is there a cached response for this request?
  11. Business logic — load the order, check visibility rules, apply transformations
  12. Database query — fetch the order record
  13. Response serialization — convert the internal representation to JSON
  14. Response headers — add cache-control, request ID, rate limit remaining
  15. Compression — gzip the response body if the client accepts it
  16. Response delivery — send over the existing TLS connection

The developer sees a 200 OK and a JSON body. The API contract abstracts all of this into a single, clean interaction.


The Vocabulary of API Engineering

Before going deeper into this learning path, it helps to have a shared vocabulary:

Term Definition
Endpoint A specific URL path that accepts requests (e.g., /v1/orders)
Resource A thing that can be addressed and manipulated via an API (e.g., an order, a user, a payment)
Method / Verb HTTP action to perform (GET, POST, PUT, PATCH, DELETE)
Request body Data sent by the client as part of the request (typically JSON)
Response body Data returned by the server (typically JSON)
Status code Three-digit HTTP code indicating the outcome (200, 201, 400, 401, 404, 500...)
Header Key-value metadata sent with a request or response (Content-Type, Authorization, Cache-Control)
Query parameter Key-value pairs appended to the URL (e.g., ?status=pending&page=2)
Path parameter Variable parts of the URL path (e.g., /orders/{orderId})
Payload The data contained in a request or response body
Schema The structure and type definition of a request or response payload
Contract The complete specification of an API's interface, behaviour, and responses
Consumer A client or service that calls an API
Provider The service that implements and exposes an API
Idempotent An operation that produces the same result regardless of how many times it is called
Rate limit The maximum number of requests a consumer can make in a time window
Versioning The mechanism for evolving an API without breaking existing consumers
Deprecation The formal process of retiring an old API version after giving consumers time to migrate
SLO Service Level Objective — a measurable target for API availability, latency, or error rate
SDK Software Development Kit — a language-specific library that wraps an API
OpenAPI A standard specification format for describing REST APIs

Summary

An API is a contract between a provider and its consumers. It specifies what operations are available, what input is required, what output will be returned, how errors are expressed, and how the contract will evolve over time.

flowchart LR
    A[Client calls API] --> B[Request travels over network]
    B --> C[Gateway: auth + rate limit]
    C --> D[Server executes business logic]
    D --> E[Response returned]
    E --> F[Client handles result]

    G[API Contract] -.->|defines| A
    G -.->|defines| E

Key takeaways:

  • APIs are contracts, not implementations — the same contract can be satisfied by multiple implementations
  • Every API interaction has two sides — the provider that fulfils the contract and the consumer that depends on it
  • There are multiple API styles — REST, RPC/gRPC, GraphQL, event-driven, and SOAP each solve different problems
  • APIs exist at every boundary — public APIs, partner APIs, internal APIs between microservices — all require the same discipline
  • Good APIs are predictable, explicit, stable, complete, secure, and observable — these properties are not accidents; they are the result of deliberate design

Learning Path

This page is part of the API Engineering Fundamentals Learning Path.

Return to the API Engineering Learning Path to continue with the complete roadmap.