Skip to content
RESTGraphQLHTTPSecuritySystem Design

Complete API GuideREST, RESTful APIs & GraphQL

Learn APIs from zero to production. Understand how clients and servers communicate, how HTTP works, how REST resources are designed, how GraphQL changes data fetching, and how real systems handle authentication, authorization, caching, pagination, retries, rate limits, webhooks and failures.

One request in 6 steps

The simplest mental model

1Client creates HTTP request
2DNS finds the server
3Gateway / server receives request
4Business logic processes it
5Database/cache may be accessed
6HTTP response returns to client
API roadmap

API Fundamentals

What is an API?

API stands for Application Programming Interface. It is a contract that defines how one software component can request data or behavior from another component.

Client

The consumer of the API. It can be a React application, Android app, another backend service, CLI, IoT device or any software capable of making the required request.

Server

Receives the request, validates it, applies business rules, communicates with dependencies and produces a response.

Contract

Defines endpoints, methods, request formats, authentication, response schemas, status codes and expected behavior.

Basic API communication

Frontend / Client
HTTP Request
Backend API
Business Logic
Database
HTTP Response

Think of an API like a restaurant contract

You are the client. The menu describes what can be requested. The waiter carries your request to the kitchen. The kitchen contains the internal implementation. You normally do not need to know how the kitchen prepares the result—you need to know what you can order and what you will receive.

API Architecture

Major API styles

API is a broad concept. REST and GraphQL are two common approaches, but production systems also use RPC, gRPC, SOAP, WebSockets and webhooks.

REST

Resource-oriented API style commonly built on HTTP methods, URLs and representations such as JSON.

Good fit: Public APIs, CRUD services, microservices, mobile/web backends and general HTTP services.

GraphQL

A typed query language where clients specify the fields they need from a schema.

Good fit: Complex frontend data requirements, multiple related resources and rapidly changing clients.

RPC

Treats the API as a collection of remote operations such as createInvoice or calculatePrice.

Good fit: Action-heavy internal services where operations are more natural than resources.

gRPC

High-performance RPC commonly using Protocol Buffers and HTTP/2.

Good fit: Low-latency service-to-service communication and strongly typed internal systems.

SOAP

XML-based messaging protocol with formal contracts and enterprise-oriented standards.

Good fit: Legacy enterprise systems and environments requiring established WS-* standards.

WebSocket

Persistent bidirectional connection between client and server.

Good fit: Chat, multiplayer systems, collaboration, trading dashboards and realtime communication.

Webhook

Server-to-server callback where one system pushes an event to another system.

Good fit: Payment updates, Git events, order events, email delivery events and asynchronous integrations.

Public API

Exposed to external developers or customers. It needs strong documentation, stable contracts, authentication, quotas and backward-compatibility planning.

Private / Internal API

Used inside an organization. It may still require strict contracts, observability, authentication and versioning because internal consumers can be numerous.

Partner API

Exposed to approved business partners under controlled authentication, permissions and usage agreements.

Composite API

Combines multiple underlying operations or services into one client-facing interaction to reduce client round trips.

HTTP

HTTP foundation

Most web APIs communicate over HTTP. Understanding HTTP is therefore fundamental to understanding REST APIs.

URL

Identifies where the request should be sent.
https://api.example.com/api/v1/users/42?include=orders

Method

Describes the intended request semantics—for example GET, POST, PUT, PATCH or DELETE.

Headers

Metadata such as authorization credentials, accepted media types, content type, caching controls, request IDs and client information.

Body

Optional request content. JSON is very common, but an API can use other media types including XML, form data, binary data or protocol-specific formats.

Anatomy of a URL

PartExampleMeaning
SchemehttpsProtocol used for communication.
Hostapi.example.comDomain containing the API.
Base path/api/v1Common prefix, sometimes containing API version.
Resource/usersCollection being addressed.
Resource ID/42A specific resource inside the collection.
Query string?include=ordersOptional query parameters modifying the request.

HTTP Messages

Request and response lifecycle

Every API interaction has two major messages: a request produced by the client and a response produced by the server.

Client → server

HTTP Request

GET /api/v1/users/42?include=orders HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer <access-token>
X-Request-ID: req_f8270

Server → client

HTTP Response

HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: private, max-age=60
ETag: "user-42-v8"
X-Request-ID: req_f8270

{
  "data": {
    "id": 42,
    "name": "Aman",
    "email": "[email protected]"
  }
}

Detailed request lifecycle

User Action
Client
DNS / Network
API
Validation
Business Logic
DB / Cache
Response

Request contains

  • HTTP method
  • URL / path
  • Query parameters
  • Headers
  • Cookies when applicable
  • Optional request body

Response contains

  • Status code
  • Response headers
  • Optional response body
  • Cache instructions
  • Correlation or request ID
  • Structured error details on failure

HTTP Semantics

HTTP methods

Use methods according to their defined semantics. The method should communicate what the client wants to do with the target resource.

MethodPurposeExampleSafeIdempotentCommon success
GETRead a resource or collection.

Should not intentionally change application state.

GET /api/v1/users/42YesYes200 OK
POSTCreate a resource or execute an operation.

Can be made retry-safe with an idempotency key.

POST /api/v1/ordersNoNo*201 Created
PUTReplace the complete representation of a resource.

Repeated identical requests should have the same intended effect.

PUT /api/v1/users/42NoYes200 / 204
PATCHPartially update a resource.

Updates selected fields instead of replacing the complete resource.

PATCH /api/v1/users/42NoDepends200 / 204
DELETERemove a resource.

Deleting an already deleted resource should not create another effect.

DELETE /api/v1/users/42NoYes204 No Content
HEADGet headers that a GET request would return.

Useful for metadata and availability checks.

HEAD /api/v1/books/100YesYes200 OK
OPTIONSDiscover communication options for a resource.

Frequently appears in browser CORS preflight requests.

OPTIONS /api/v1/usersYesYes200 / 204

Safe method

A safe method is defined with essentially read-only semantics. GET should therefore retrieve information rather than request deletion, charging a card or changing account data.

Idempotent method

Repeating the same request should have the same intended server-side effect as sending it once. This matters greatly when networks fail and clients need to retry.

Create a user

HTTP

POST /api/v1/users
Content-Type: application/json
Authorization: Bearer <access-token>

{
  "name": "Aman",
  "email": "[email protected]"
}

Successful creation

HTTP

HTTP/1.1 201 Created
Location: /api/v1/users/42
Content-Type: application/json

{
  "data": {
    "id": 42,
    "name": "Aman",
    "email": "[email protected]",
    "createdAt": "2026-09-30T10:30:00Z"
  }
}

HTTP Response

HTTP status codes

Status codes allow a client to understand the broad result of a request without parsing application-specific response text.

1xx — Informational

The request is still being processed or the protocol is changing.

100 Continue101 Switching Protocols

2xx — Success

The server successfully processed the request.

200 OK201 Created202 Accepted204 No Content206 Partial Content

3xx — Redirection

The client may need another request or can reuse a cached representation.

301 Moved Permanently302 Found304 Not Modified307 Temporary Redirect308 Permanent Redirect

4xx — Client Error

Something about the request, authentication, permissions or requested resource is invalid.

400 Bad Request401 Unauthorized403 Forbidden404 Not Found409 Conflict422 Unprocessable Content429 Too Many Requests

5xx — Server Error

The server or an upstream dependency failed while serving a valid request.

500 Internal Server Error502 Bad Gateway503 Service Unavailable504 Gateway Timeout
CodeUse it when
200 OKRequest succeeded and a normal response representation is returned.
201 CreatedA new resource was successfully created.
202 AcceptedRequest was accepted for asynchronous processing but processing is not complete.
204 No ContentOperation succeeded and no response body is necessary.
304 Not ModifiedConditional request indicates the cached representation is still valid.
400 Bad RequestThe request is malformed or cannot be understood according to the API contract.
401 UnauthorizedAuthentication credentials are missing or invalid.
403 ForbiddenThe caller is authenticated but does not have permission for the operation.
404 Not FoundThe requested resource cannot be found.
409 ConflictThe request conflicts with the current state of the resource.
422 Unprocessable ContentThe request syntax may be valid but the content cannot be processed semantically.
429 Too Many RequestsThe caller has exceeded an enforced request limit.
500 Internal Server ErrorAn unexpected server-side failure occurred.
502 Bad GatewayA gateway/proxy received an invalid response from an upstream service.
503 Service UnavailableThe service cannot currently handle the request.
504 Gateway TimeoutA gateway/proxy did not receive a timely response from an upstream service.

REST

What is REST?

REST stands for Representational State Transfer. It is an architectural style for distributed systems rather than a programming language, framework or wire protocol.

In a typical HTTP REST API, the server exposes resources such as users, products or orders. The client identifies resources using URIs and interacts with them through standardized HTTP semantics.

REST constraints

1

Client–Server

UI/client concerns and server/data concerns are separated. Either side can evolve independently as long as the contract remains compatible.

2

Stateless

Every request should contain the information needed to process it. The server should not depend on conversational client session state between requests.

3

Cacheable

Responses should communicate whether they may be cached. Correct caching can reduce latency, server load and bandwidth.

4

Uniform Interface

Resources use consistent identifiers and standard interaction semantics so clients do not need resource-specific transport behavior.

5

Layered System

The client does not need to know whether it communicates directly with the origin server, an API gateway, proxy, CDN or another intermediary.

6

Code on Demand

An optional REST constraint allowing a server to extend client functionality by transferring executable code.

REST resource model

GET /users/42
User Resource
Representation
JSON Response

REST API vs RESTful API

In everyday engineering conversation, the terms are often used interchangeably. “RESTful” generally emphasizes that the API follows REST principles consistently rather than merely using HTTP and JSON.

REST Design

How to design REST resources

Start with the domain resources, not controller method names. HTTP already provides operation semantics.

Avoid

GET /getAllUsers

Prefer

GET /users

The HTTP method already communicates the action.

Avoid

POST /createUser

Prefer

POST /users

Model the endpoint as a resource rather than a CRUD verb.

Avoid

GET /deleteUser?id=42

Prefer

DELETE /users/42

GET should not be used to request destructive operations.

Avoid

/user/42/orders

Prefer

/users/42/orders

Use consistent resource naming conventions.

Avoid

/api/users/getById/42

Prefer

/api/v1/users/42

Resource path + HTTP method is generally enough.

Collections

/users

Represents a collection of user resources.

Single resource

/users/42

Represents the user whose identifier is 42.

Nested resource

/users/42/orders

Represents orders scoped to a particular user.

Sub-resource

/orders/9001/items

Represents items associated with order 9001.

Request Design

Path, query, header and body parameters

Path parameter

Identifies a particular resource.
GET /users/42

Here, 42 is part of resource identity.

Query parameter

Changes how a collection or representation is selected.
GET /products?page=2&sort=-price

Header

Carries request metadata.
Authorization: Bearer token

Request body

Carries structured data submitted to the API.
{ "name": "Aman" }

Easy rule

Use a path parameter when the value identifies which resource you mean. Use a query parameter when it modifies selection, filtering, searching, sorting, pagination or representation.

Contract Design

Designing consistent API responses

Single resource

{
  "data": {
    "id": 42,
    "name": "Aman"
  }
}

Collection

{
  "data": [
    { "id": 41, "name": "Riya" },
    { "id": 42, "name": "Aman" }
  ],
  "pagination": {
    "page": 1,
    "limit": 20
  }
}
  • Use stable field names and predictable types.
  • Do not change a field from string to object without considering compatibility.
  • Avoid returning HTTP 200 for every failure and hiding error semantics only inside JSON.
  • Include correlation/request identifiers when they help support and debugging.

Reliability

API error handling

A useful error should tell the caller what category of failure occurred, give a stable machine-readable code and provide enough context to correct the request without leaking sensitive internals.

Structured error response

JSON

{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "The request contains invalid fields.",
    "requestId": "req_f8270",
    "details": [
      {
        "field": "email",
        "message": "A valid email address is required."
      }
    ]
  }
}

Bad error

{ "error": "Something went wrong" }

The client cannot programmatically understand the failure.

Better error

Stable error code + readable message + request ID + optional field-level details.

Never expose

  • • Database passwords
  • • Access tokens
  • • Private keys
  • • Internal stack traces to public clients
  • • Raw SQL containing sensitive values
  • • Internal infrastructure secrets

Scalability

API pagination

Never return an unbounded collection when that collection can grow significantly.

Offset / page pagination

HTTP + JSON

GET /api/v1/products?page=3&limit=20

{
  "data": [...],
  "pagination": {
    "page": 3,
    "limit": 20,
    "totalItems": 242,
    "totalPages": 13,
    "hasNext": true,
    "hasPrevious": true
  }
}

Easy for users to understand and jump between pages, but large offsets can become expensive and changing datasets can cause duplicate or skipped items.

Cursor pagination

HTTP + JSON

GET /api/v1/feed?limit=20&after=eyJpZCI6OTg3fQ

{
  "data": [...],
  "pageInfo": {
    "nextCursor": "eyJpZCI6MTAwN30",
    "hasNextPage": true
  }
}

Better suited to large or frequently changing feeds because the cursor points to a position in an ordered dataset rather than a numeric offset.

Jump to page

Easy

Usually not supported directly

Large datasets

Can degrade with large offsets

Usually better

Changing data

May skip/duplicate rows

Usually more stable with correct ordering

Implementation

Simple

More design work

Collections

Filtering, sorting, searching and field selection

One possible query design

HTTP

GET /api/v1/products
  ?category=books
  &minPrice=100
  &maxPrice=1000
  &sort=-createdAt
  &fields=id,title,price
  &search=system+design

Filtering

?status=PAID&currency=INR

Sorting

?sort=-createdAt,price

A minus prefix can represent descending order if documented by your API.

Search

?search=system+design

Sparse field selection

?fields=id,title,price

Can reduce response size when clients only need selected fields.

Compatibility

API versioning

Versioning gives you a controlled path for breaking contract changes. Not every change requires a new API version.

URI versioning

/api/v1/users

Very visible and easy for clients and documentation.

Header versioning

API-Version: 2026-09-01

Keeps URLs clean but is less obvious when inspecting links.

Media type versioning

Accept: application/vnd.app.v2+json

Version information is expressed through content negotiation.

Often backward-compatible

  • Adding an optional response field
  • Adding a new endpoint
  • Adding an optional request parameter

Potentially breaking

  • Removing a field
  • Changing a field type
  • Renaming a field
  • Changing meaning of an existing field
  • Making an optional request field mandatory

Distributed Systems

Idempotency and safe retries

Networks fail in uncomfortable places. A client might not know whether the server processed a request because the connection disappeared before the response arrived.

Why duplicate payments can happen

Client sends payment
Server charges card
Response is lost
Client retries
Risk of second charge

POST with idempotency key

HTTP

POST /api/v1/payments
Idempotency-Key: pay_01928475
Content-Type: application/json

{
  "orderId": "ORD-8429",
  "amount": 19900,
  "currency": "INR"
}

Idempotency-key flow

Receive key
Check idempotency store
Existing result?
Return saved result / Process once
Persist result

A production implementation usually associates the idempotency key with the caller and request, stores the outcome for a defined lifetime, and protects concurrent requests using atomic operations or transactional guarantees.

Security

API authentication

Authentication answers: Who is making this request?

API key

Simple credential identifying an application or consumer.

HTTP

GET /api/v1/weather
X-API-Key: sk_live_xxxxxxxxx

Bearer token / JWT

A bearer access token is included in the Authorization header. JWT is one possible token format.

HTTP

Authorization: Bearer eyJhbGciOiJIUzI1NiIs...

GET /api/v1/profile

Session / cookie

Common for browser applications. The server may keep server-side session state while the browser sends a session identifier in a secure cookie.

OAuth 2.0

Authorization framework frequently used when applications need delegated access to protected APIs. OpenID Connect adds an identity layer for authentication use cases.

Bearer-token request

User authenticates
Identity system
Access token
Client
API
Token validation
Protected resource

Security

Authentication vs authorization

Authentication — Who are you?

Example: verifying a login, API key, session or access token.

Authorization — What may you do?

Example: determining whether a signed-in employee may delete another user's account or access an admin endpoint.

RBAC

Role-Based Access Control.

Permissions are associated with roles such as ADMIN, EDITOR or USER.

ABAC

Attribute-Based Access Control.

Decisions use attributes such as department, resource owner, environment or location.

Resource ownership

A user may be allowed to read /users/42/orders only when user 42 represents that caller or another permitted relationship.

Security

API security checklist

Use HTTPS

Protect credentials and application data in transit using TLS.

Validate input

Treat all client input as untrusted and enforce size, type, range and format constraints.

Authorize every protected resource

Do not assume knowing a resource ID means the caller may access it.

Rate limit sensitive operations

Protect login, OTP, password reset and expensive endpoints from abuse.

Protect secrets

Do not hardcode API secrets in frontend bundles or commit them to source control.

Short-lived credentials

Limit the damage from compromised credentials where your authentication model allows it.

Audit important actions

Record security-relevant changes with actor, target, timestamp and request context.

Limit response data

Do not expose sensitive fields merely because they exist in the database model.

Control payload sizes

Bound uploads, JSON depth, query complexity and other resource-intensive input.

Secure dependencies

Patch frameworks, libraries, gateways and infrastructure components.

Browser Security

CORS

Cross-Origin Resource Sharing is an HTTP-header mechanism used by browsers to decide whether frontend JavaScript from one origin may access resources from another origin.

Typical preflight

Browser
OPTIONS preflight
API
CORS response headers
Actual request

Origin

Origin consists of scheme + host + port.
https://www.targettrek.in

Example response headers

Access-Control-Allow-Origin: https://www.targettrek.in
Access-Control-Allow-Methods: GET, POST
Access-Control-Allow-Headers: Content-Type, Authorization

CORS is primarily a browser-enforced mechanism. It is not a replacement for authentication or authorization. Your backend must still enforce who is allowed to access protected data.

Performance

API caching

Caching avoids repeating work when a previously generated representation can still be reused.

Cache lookup

Client
CDN / Cache
Cache hit?
Return cached data / Call origin
API
Database

Conditional request with ETag

HTTP

GET /api/v1/books/42
If-None-Match: "book-42-v12"

# If unchanged:
HTTP/1.1 304 Not Modified
ETag: "book-42-v12"

# If changed:
HTTP/1.1 200 OK
ETag: "book-42-v13"
Content-Type: application/json

{
  "id": 42,
  "title": "System Design"
}

Cache-Control

Can communicate directives such as freshness duration and whether responses are public, private or should not be stored.

ETag

Validator identifying a representation version. A client can use it in a conditional request.

304 Not Modified

Allows the server to tell the client that its cached representation remains valid without returning the full response body again.

CDN / shared cache

Useful for cacheable public content close to users, reducing origin requests and network latency.

Reliability

Rate limiting

Rate limiting controls how frequently a caller may perform requests. It protects capacity, fairness, costs and sensitive endpoints.

Fixed window

Count requests in fixed intervals such as 100 requests per minute. Simple, but traffic may burst around window boundaries.

Sliding window

Tracks usage over a moving period to provide smoother limits.

Token bucket

Tokens refill at a configured rate. Requests consume tokens, allowing controlled bursts while enforcing a long-term rate.

Leaky bucket

Processes traffic at a controlled output rate and smooths bursts.

Rate limit response

HTTP

HTTP/1.1 429 Too Many Requests
Retry-After: 30
RateLimit-Limit: 100
RateLimit-Remaining: 0

{
  "error": {
    "code": "RATE_LIMIT_EXCEEDED",
    "message": "Too many requests. Retry later."
  }
}

Distributed rate limiting

Client
API Gateway
Rate Limiter
Redis / shared counter
Allow / Reject
Service

GraphQL

GraphQL API

GraphQL exposes a typed schema and lets clients select the fields they need. A GraphQL server commonly exposes operations through queries, mutations and subscriptions.

Query

Reads data.

Similar in intent to data-fetching operations.

Mutation

Changes data or triggers side effects.

Subscription

Represents a long-lived operation for receiving updates as events occur.

GraphQL execution flow

Client Query
GraphQL Endpoint
Parse & Validate
Resolvers
Services / Data Sources
Shape Response

Schema

GraphQL SDL

type User {
  id: ID!
  name: String!
  email: String!
  orders(first: Int, after: String): OrderConnection!
}

type Order {
  id: ID!
  total: Float!
  status: OrderStatus!
}

type Query {
  user(id: ID!): User
  users(first: Int, after: String): UserConnection!
}

type Mutation {
  createUser(input: CreateUserInput!): User!
}

type Subscription {
  orderStatusChanged(orderId: ID!): Order!
}

Query

GraphQL

query GetUser($id: ID!) {
  user(id: $id) {
    id
    name
    email
    orders(first: 3) {
      nodes {
        id
        total
        status
      }
    }
  }
}

Query response

JSON

{
  "data": {
    "user": {
      "id": "42",
      "name": "Aman",
      "email": "[email protected]",
      "orders": {
        "nodes": [
          {
            "id": "ORD-101",
            "total": 199,
            "status": "PAID"
          }
        ]
      }
    }
  }
}

Mutation

GraphQL

mutation CreateUser($input: CreateUserInput!) {
  createUser(input: $input) {
    id
    name
    email
  }
}

Why GraphQL can be useful

Field selection

The client explicitly asks for fields such as id, name, orders, reducing unnecessary fields in the representation.

Relationship traversal

Related data can be expressed in one query structure instead of forcing the client to manually coordinate several resource-specific calls.

Typed schema

The schema describes available types, fields, arguments and operation shapes.

Client flexibility

Different clients can request different representations without creating a dedicated REST endpoint for every UI.

GraphQL challenges

N+1 problem

A naive resolver implementation can issue one query for a collection and then one additional query per item. Batching and data-loader patterns can reduce this.

Query complexity

Clients can construct expensive nested queries. Production systems may enforce depth, complexity, timeout and size limits.

Authorization

Authorization must be applied correctly across fields, resources and resolvers—not merely at the single HTTP endpoint.

Caching

HTTP-level caching is less automatically resource-oriented than classic GET resource URLs, so application and client caching strategies require careful design.

Comparison

REST vs GraphQL

Neither technology is universally superior. Choose based on API consumers, data relationships, caching needs, operational complexity and team experience.

Primary model

Resources identified through URIs.

Typed graph exposed through a schema.

Data selection

Server defines each endpoint representation.

Client selects requested fields.

Endpoints

Typically multiple resource URLs.

Commonly a GraphQL endpoint handling many operations.

Caching

Works naturally with HTTP GET semantics and URL-addressable resources.

Often requires more application/client-aware caching design.

Related data

May require multiple endpoints or purpose-built representations.

Relationships can be expressed inside one query.

Complexity controls

Endpoint cost is usually easier to reason about.

Arbitrary client queries can require depth and complexity limits.

Good fit

Straightforward resource APIs, public APIs, HTTP-centric services and cacheable resources.

Rich applications with complex and changing data-fetching requirements.

Event Integrations

Webhooks

A webhook reverses the usual polling relationship: instead of repeatedly asking whether something changed, the provider sends an HTTP request when an event happens.

Payment webhook example

Payment Provider
payment.success event
POST /webhooks/payment
Verify signature
Process event
Return 2xx

Webhook delivery

HTTP + JSON

POST /webhooks/payment
X-Webhook-Id: evt_18273
X-Webhook-Timestamp: 1790767200
X-Webhook-Signature: sha256=...

{
  "id": "evt_18273",
  "type": "payment.success",
  "data": {
    "orderId": "ORD-8429",
    "paymentId": "PAY-2901"
  }
}

Verify authenticity

Verify a cryptographic signature or other provider-supported authentication mechanism before trusting webhook content.

Expect retries

Providers may deliver the same event more than once. Store a stable event ID and process webhook events idempotently.

Acknowledge quickly

Avoid performing extremely long synchronous processing before acknowledging the delivery. Queue additional work when appropriate.

Observe failures

Track delivery attempts, signature failures, processing failures, retries and dead-lettered events.

Direction

Consumer repeatedly asks provider.

Provider pushes event to consumer.

Latency

Depends on polling interval.

Can be near-real-time.

Waste

Many requests may return no change.

Traffic occurs primarily for events.

Complexity

Simple consumer model.

Requires public callback, security and retry handling.

Beyond REST

RPC, gRPC, SOAP and WebSockets

RPC

Remote Procedure Call APIs model operations rather than resources.

POST /calculateShipping POST /generateInvoice POST /approveLoan

gRPC

gRPC is commonly used for strongly typed high-performance service-to-service APIs. Protocol Buffers define service methods and messages.
service UserService {
  rpc GetUser(GetUserRequest)
      returns (UserResponse);
}

SOAP

SOAP is an XML messaging protocol commonly associated with formal service contracts and enterprise web-service standards.

WebSocket

A WebSocket connection remains open for bidirectional communication.

Realtime communication

Client
Persistent Connection
Server
Server Push
Client

Documentation

OpenAPI and Swagger

OpenAPI defines a machine-readable description format for HTTP APIs. Tooling can use that contract for documentation, validation, client generation, server stubs and testing.

OpenAPI

The specification describing how an HTTP API contract can be represented in JSON or YAML.

Swagger

A family of tools historically associated with the specification and commonly used to edit, visualize and work with OpenAPI descriptions.

OpenAPI example

YAML

openapi: 3.2.0

info:
  title: Target Trek Learning API
  version: 1.0.0
  description: Example API used for learning REST concepts.

servers:
  - url: https://api.example.com

paths:
  /api/v1/users/{userId}:
    get:
      summary: Get a user
      operationId: getUser

      parameters:
        - name: userId
          in: path
          required: true
          schema:
            type: integer

      responses:
        "200":
          description: User found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/User"

        "404":
          description: User not found

components:
  schemas:
    User:
      type: object
      required:
        - id
        - name

      properties:
        id:
          type: integer

        name:
          type: string

        email:
          type: string

API-first workflow

Define Contract
Review
Generate Docs
Implement
Contract Tests
Client SDKs

System Design

API Gateway

An API Gateway can provide a managed entry point between external clients and backend services.

Typical API gateway request path

Client
DNS / CDN
Load Balancer
API Gateway
Authentication
Rate Limiter
Service
Cache / Database

Common responsibilities

  • Authentication integration
  • Authorization policy enforcement
  • Rate limiting
  • Routing
  • Request/response transformation
  • Observability metadata

Gateway vs load balancer

A load balancer primarily distributes traffic among available backends.

An API gateway commonly understands more application/API concerns such as routes, authentication, quotas and API policies.

Real architectures frequently contain both.

Production

API observability

When an API fails in production, you need enough information to answer what failed, where, for whom and why.

Logs

Structured events such as request metadata, errors, business events and dependency failures.

Metrics

Numerical measurements aggregated over time.

Distributed tracing

Follows a request across gateways, services, queues and downstream dependencies.

Useful API metrics

Request rate
p50 latency
p95 latency
p99 latency
4xx rate
5xx rate
Timeout rate
Upstream latency
Cache hit rate
Rate-limit rejections
Database latency
Queue depth

Trace example

Request ID
API Gateway
Order Service
Payment Service
Database
Trace

Quality

API testing strategy

Unit tests

Test isolated business logic and validation rules quickly.

Integration tests

Test your service with real or representative databases, caches, queues and framework layers.

Contract tests

Verify that providers and consumers agree on request and response contracts.

End-to-end tests

Test important user flows through multiple system components.

Load tests

Measure behavior under expected and elevated traffic.

Security tests

Validate authentication, authorization, input handling and sensitive endpoints.

Test more than the happy path

Missing authentication token
Expired or invalid token
Unauthorized resource access
Invalid JSON
Missing required field
Wrong field type
Unknown resource
Duplicate request
Concurrent update
Rate limit exceeded
Database unavailable
Upstream service timeout
Malformed pagination cursor
Maximum page-size enforcement
Webhook duplicate delivery
Webhook invalid signature

Testing with cURL

Bash

curl --request POST \
  --url https://api.example.com/api/v1/users \
  --header "Authorization: Bearer <token>" \
  --header "Content-Type: application/json" \
  --data '{
    "name": "Aman",
    "email": "[email protected]"
  }'

Calling an API from frontend

JavaScript

const response = await fetch(
  "https://api.example.com/api/v1/users/42",
  {
    method: "GET",
    headers: {
      Accept: "application/json",
      Authorization: `Bearer ${accessToken}`,
    },
  }
);

if (!response.ok) {
  throw new Error(`Request failed: ${response.status}`);
}

const result = await response.json();
console.log(result);

Backend

Putting everything together

A production API is more than a controller connected directly to a database. Each layer solves a different concern.

Production API architecture

Client
CDN / WAF
Load Balancer
API Gateway
Service
Cache
Database

Inside the service

Controller
Validation
Authorization
Service Layer
Repository
Database / External API

Controller

Converts the transport request into application input and returns the transport response. Avoid putting the entire business domain here.

Service layer

Holds important business workflows and coordinates domain operations.

Repository / DAO

Encapsulates persistence access instead of spreading database queries throughout controllers.

DTO / API model

Keeps your public contract separate from raw database entities where appropriate.

REST controller example

Java / Spring Boot

@RestController
@RequestMapping("/api/v1/users")
public class UserController {

    private final UserService userService;

    public UserController(UserService userService) {
        this.userService = userService;
    }

    @GetMapping("/{id}")
    public ResponseEntity<UserResponse> getUser(
            @PathVariable Long id
    ) {
        UserResponse user = userService.getById(id);
        return ResponseEntity.ok(user);
    }

    @PostMapping
    public ResponseEntity<UserResponse> createUser(
            @Valid @RequestBody CreateUserRequest request
    ) {
        UserResponse created = userService.create(request);

        URI location = URI.create(
            "/api/v1/users/" + created.id()
        );

        return ResponseEntity
                .created(location)
                .body(created);
    }
}

Concurrent updates

Two clients may read the same resource and attempt to update it at nearly the same time. Depending on the domain, you may use database transactions, optimistic locking/version fields, conditional requests, pessimistic locks or application-specific conflict handling.

Client A reads version = 8
Client B reads version = 8

Client A updates resource -> version = 9

Client B tries:
UPDATE users
SET name = 'New Name', version = 9
WHERE id = 42 AND version = 8

0 rows updated -> conflict detected

Timeouts, retries and circuit breakers

Timeout

Never wait forever for a dependency. Bound how long a request or downstream call may take.

Retry

Retry only when the failure and operation semantics make retry safe. Use bounded retries and backoff rather than infinite loops.

Circuit breaker

Temporarily stop sending requests to a dependency that is repeatedly failing, allowing systems to fail faster and recover.

Retry with exponential backoff

Attempt 1
Fail
Wait
Attempt 2
Fail
Longer wait
Attempt 3

Interview Preparation

Important API interview questions

Use these questions to test whether you understand the concepts rather than only memorizing definitions.

1

What is an API and why is an API contract important?

2

What is REST and what makes an API RESTful?

3

REST vs REST API vs RESTful API — are they exactly the same thing?

4

What is the difference between URI and URL?

5

GET vs POST vs PUT vs PATCH?

6

Why is GET considered safe?

7

What does idempotent mean?

8

Is POST idempotent?

9

Why is DELETE considered idempotent?

10

What is the difference between 401 and 403?

11

When should you return 400, 409 or 422?

12

When should an API return 200 vs 201 vs 202 vs 204?

13

What are path parameters and query parameters?

14

Offset pagination vs cursor pagination?

15

How would you version an API?

16

What is an idempotency key and why do payment APIs use one?

17

JWT vs session authentication?

18

Authentication vs authorization?

19

OAuth 2.0 vs OpenID Connect?

20

What is CORS and why does the browser enforce it?

21

What is a CORS preflight request?

22

What is rate limiting?

23

Token bucket vs fixed window vs sliding window?

24

What does Cache-Control do?

25

What are ETag and If-None-Match?

26

What is GraphQL?

27

GraphQL query vs mutation vs subscription?

28

REST vs GraphQL — when would you use each?

29

What is the N+1 problem in GraphQL?

30

What is an API Gateway?

31

API Gateway vs Load Balancer?

32

What are webhooks?

33

Webhook vs polling?

34

How do you secure a webhook?

35

What is OpenAPI?

36

OpenAPI vs Swagger?

37

How would you design a production-ready payment API?

38

How do you safely retry failed API calls?

39

How do you handle concurrent updates?

40

How would you observe and debug an API in production?

Revision

Production API design checklist

Resources and endpoint naming are consistent.
HTTP methods follow their intended semantics.
Correct HTTP status codes are returned.
Request data is validated.
Authentication is enforced where required.
Authorization is checked per protected operation/resource.
TLS/HTTPS is used.
Sensitive values are never returned accidentally.
Error responses follow one predictable structure.
Collections use bounded pagination.
Filtering and sorting parameters are documented.
Breaking changes have a compatibility/versioning plan.
Retry-sensitive writes use appropriate idempotency protection.
Rate limiting protects capacity and sensitive operations.
Caching behavior is explicitly designed.
External dependency calls have timeouts.
Retries are bounded and safe.
Concurrent modifications are considered.
Webhooks verify authenticity.
Webhook processing handles duplicate events.
Logs contain request/correlation IDs where useful.
Latency, errors and traffic are monitored.
API documentation matches the real contract.
Automated contract/integration tests protect the API.

Final mental model

Good APIs are contracts, not just URLs

A strong API combines clear resource or operation design, predictable request/response contracts, correct transport semantics, authentication, authorization, validation, idempotency, scalability, observability and documentation. REST, GraphQL and gRPC are tools; good engineering comes from understanding the trade-offs and failure modes behind them.

Frequently asked questions

What is an API?

An API is a defined interface that allows software systems to communicate through an agreed contract of operations, inputs, outputs and behavior.

What is a REST API?

A REST API is an API designed around REST architectural ideas, usually exposing resources over HTTP and using standard HTTP semantics.

What is a RESTful API?

RESTful commonly describes an API that follows REST constraints and models interactions consistently around resources.

What is the difference between PUT and PATCH?

PUT conventionally represents replacement of the resource representation, while PATCH applies partial modifications.

What is GraphQL?

GraphQL is a query language and execution model for APIs where a schema defines available types and clients request selected fields.

What is API idempotency?

An operation is idempotent when making the same request repeatedly has the same intended server-side effect as making it once.